private void ImplementIf(IList <Expression> conds, IList <Statement> branches) { BranchLabel[] skipTargets = new BranchLabel[conds.Count]; BranchLabel beyond = CreateLabel(); for (int i = 0; i < conds.Count; i++) { Expression cond = conds[i].SimplifyMultiValuedLogic(); cond.Accept(this); BranchLabel target = CreateLabel(); skipTargets[i] = target; XILInstr bi = ISet.BranchIfFalse(target); Emit(bi, CloseBB(), 1); BeginBB(); branches[i].Accept(this); target.InstructionIndex = NextInstructionIndex; if (i != branches.Count - 1) { Emit(ISet.Goto(beyond), CloseBB(), 0); } BeginBB(); } skipTargets.Last().InstructionIndex = NextInstructionIndex; if (conds.Count < branches.Count) { branches.Last().Accept(this); BeginBB(); } beyond.InstructionIndex = NextInstructionIndex; }
/// <summary> /// Constructs an instance /// </summary> /// <param name="command">underlying XIL instruction</param> /// <param name="preds">instruction dependencies</param> /// <param name="operandSlots">operand slots</param> /// <param name="resultSlots">result slots</param> public XIL3Instr(XILInstr command, InstructionDependency[] preds, int[] operandSlots, int[] resultSlots) { Command = command; Preds = preds; OperandSlots = operandSlots; ResultSlots = resultSlots; Index = -1; CILRef = null; }
public override bool Equals(object obj) { XILInstr xili = obj as XILInstr; if (xili == null) { return(false); } return(Name.Equals(xili.Name) && object.Equals(Operand, xili.Operand)); }
/// <summary> /// Constructs a new instance /// </summary> /// <param name="command">XIL instruction</param> /// <param name="preds">instruction dependencies</param> /// <param name="operandTypes">operand types expected on the stack</param> /// <param name="resultTypes">result types to appear on the stack</param> public XILSInstr(XILInstr command, InstructionDependency[] preds, TypeDescriptor[] operandTypes, TypeDescriptor[] resultTypes) { Contract.Requires(command != null && preds != null && operandTypes != null && operandTypes.All(t => t != null) && resultTypes != null && resultTypes.All(t => t != null)); Command = command; Preds = preds; OperandTypes = operandTypes; ResultTypes = resultTypes; CILRef = null; }
public IXILMapping TryAllocate(Component host, XILInstr instr, TypeDescriptor[] operandTypes, TypeDescriptor[] resultTypes, IProject proj) { List <IXILMapper> mappers = _mlookup.Get(instr.Name); foreach (IXILMapper mapper in mappers) { IXILMapping mapping = mapper.TryAllocate(host, instr, operandTypes, resultTypes, proj); if (mapping != null) { return(mapping); } } return(null); }
private void Emit(XILInstr xili, object backRef, InstructionDependency[] preds, int numOperands, params TypeDescriptor[] resultTypes) { Contract.Requires(xili != null && preds != null && numOperands >= 0 && resultTypes != null && resultTypes.All(t => t != null)); xili.BackRef = backRef; TypeDescriptor[] operandTypes = new TypeDescriptor[numOperands]; for (int i = numOperands - 1; i >= 0; i--) { operandTypes[i] = _typeStack.Pop(); } for (int i = 0; i < resultTypes.Length; i++) { _typeStack.Push(resultTypes[i]); } Emit(xili.CreateStk(preds, operandTypes, resultTypes)); }
/// <summary> /// Classifies a given XIL instruction, such that all instructions which may be mapped to the same type of hardware functional unit /// belong to the same group. /// </summary> /// <param name="instr">XIL instruction</param> /// <param name="operandTypes">types of instruction operands</param> /// <param name="resultTypes">types of instruction results</param> /// <param name="binder">binder service</param> /// <returns>Opaque group identifier. Do not make any assumptions on the content or type of the returned object. /// The important thing is that any instructions belonging to the same group will see the same object.</returns> public object Classify(XILInstr instr, TypeDescriptor[] operandTypes, TypeDescriptor[] resultTypes, IAutoBinder binder) { var mapping = TryMap(instr, operandTypes, resultTypes, binder); if (mapping == null) { return(null); } if (mapping.ResourceKind == EMappingKind.ExclusiveResource || mapping.ResourceKind == EMappingKind.LightweightResource) { return(new ClassifyCookie(instr)); } else { return(mapping.TASite); } }
private void Emit(XILInstr xili, object backRef, int numOperands, params TypeDescriptor[] resultTypes) { if (_closeBBOnNextInstr) { Emit(xili, backRef, CloseBB(), numOperands, resultTypes); _closeBBOnNextInstr = false; } else { int pred = _barriers[xili.Name]; if (pred >= 0) { Emit(xili, backRef, new InstructionDependency[] { new OrderDependency(pred, OrderDependency.EKind.BeginAfter) }, numOperands, resultTypes); } else { Emit(xili, backRef, new InstructionDependency[0], numOperands, resultTypes); } } }
private void Process(XIL3Instr xil3i) { var preds = xil3i.Preds.Select(p => p.Remap(_slotRemap[p.PredIndex])).ToArray(); _instRemap.Add(_outInstrs.Count); foreach (int oslot in xil3i.OperandSlots) { Emit(DefaultInstructionSet.Instance .LoadVar(_interLocals[oslot]).CreateStk(preds, 0, _interLocals[oslot].Type)); } _slotRemap.Add(_outInstrs.Count); var cmd = xil3i.Command; if (cmd.Name == InstructionCodes.BranchIfFalse || cmd.Name == InstructionCodes.BranchIfTrue || cmd.Name == InstructionCodes.Goto) { var target = (BranchLabel)cmd.Operand; var newTarget = new BranchLabel() { InstructionIndex = target.InstructionIndex }; cmd = new XILInstr(cmd.Name, newTarget) { BackRef = cmd.BackRef }; _labels.Add(newTarget); } Emit(cmd.CreateStk(preds, xil3i.OperandSlots.Length, xil3i.OperandSlots.Select(os => _interLocals[os].Type) .Concat(xil3i.ResultSlots.Select(rs => _interLocals[rs].Type)) .ToArray())); foreach (int rslot in xil3i.ResultSlots.Reverse()) { Emit(DefaultInstructionSet.Instance .StoreVar(_interLocals[rslot]).CreateStk(1, _interLocals[rslot].Type)); } }
/// <summary> /// Tries to map the given XIL instruction to any suitable functional unit. This call will not create any actual hardware. It is used by the /// scheduler to query basic instruction metrics, namely initiation interval and latency. /// </summary> /// <param name="instr">XIL instruction</param> /// <param name="operandTypes">operand types of XIL instruction</param> /// <param name="resultTypes">result types of XIL instruction</param> /// <param name="binder">binder service</param> /// <returns>a hardware mapping for the supplied instruction or null if no such exists</returns> public IXILMapping TryMap(XILInstr instr, TypeDescriptor[] operandTypes, TypeDescriptor[] resultTypes, IAutoBinder binder) { var xilsi = instr.CreateStk(new InstructionDependency[0], operandTypes, resultTypes); IXILMapping mapping; if (_xilMappings.TryGetValue(xilsi, out mapping)) { return(mapping); } IEnumerable <IXILMapper> mappers = _xmm.LookupMappers(instr); foreach (IXILMapper mapper in mappers) { var tas = _taMapLookup.Get(mapper); foreach (var ta in tas) { var mappings = mapper.TryMap(ta, instr, operandTypes, resultTypes); if (mappings.Any()) { mapping = mappings.First(); _xilMappings[xilsi] = mapping; return(mapping); } } } foreach (IXILMapper mapper in mappers) { mapping = mapper.TryAllocate(_host, instr, operandTypes, resultTypes, _targetProject); if (mapping != null) { _taMapLookup.Add(mapper, mapping.TASite); _xilMappings[xilsi] = mapping; return(mapping); } } return(null); }
/// <summary> /// Returns a sequence of adminissible result types, given instruction operand types. /// </summary> /// <param name="instr">XIL instruction</param> /// <param name="operandTypes">operand types</param> /// <returns>admissible result types</returns> public static IEnumerable <TypeDescriptor> GetDefaultResultTypes(this XILInstr instr, TypeDescriptor[] operandTypes) { switch (instr.Name) { case InstructionCodes.Abs: if (operandTypes[0].CILType.Equals(typeof(float)) || operandTypes[0].CILType.Equals(typeof(double)) || operandTypes[0].CILType.Equals(typeof(int)) || operandTypes[0].CILType.Equals(typeof(long)) || operandTypes[0].CILType.Equals(typeof(sbyte)) || operandTypes[0].CILType.Equals(typeof(short))) { yield return(operandTypes[0]); } else if (operandTypes[0].CILType.Equals(typeof(double))) { yield return(typeof(double)); } else if (operandTypes[0].CILType.Equals(typeof(SFix))) { var fmt = SFix.GetFormat(operandTypes[0]); var ssample = SFix.FromDouble(0.0, fmt.IntWidth + 1, fmt.FracWidth); yield return(TypeDescriptor.GetTypeOf(ssample)); var usample = UFix.FromDouble(0.0, fmt.IntWidth, fmt.FracWidth); yield return(TypeDescriptor.GetTypeOf(usample)); } else if (operandTypes[0].CILType.Equals(typeof(UFix))) { yield return(operandTypes[0]); } else { throw new NotSupportedException("Operand type not supported"); } break; case InstructionCodes.Add: { dynamic o1 = operandTypes[0].GetSampleInstance(); dynamic o2 = operandTypes[1].GetSampleInstance(); object r = o1 + o2; yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.And: { dynamic o1 = operandTypes[0].GetSampleInstance(); dynamic o2 = operandTypes[1].GetSampleInstance(); object r = o1 & o2; yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.Barrier: case InstructionCodes.BranchIfFalse: case InstructionCodes.BranchIfTrue: yield break; case InstructionCodes.Ceil: case InstructionCodes.Floor: case InstructionCodes.SinCos: if (operandTypes[0].CILType.Equals(typeof(float)) || operandTypes[0].CILType.Equals(typeof(double))) { yield return(operandTypes[0]); } else { throw new NotSupportedException(); } break; case InstructionCodes.Cos: case InstructionCodes.Sin: if (operandTypes[0].CILType.Equals(typeof(float)) || operandTypes[0].CILType.Equals(typeof(double))) { yield return(operandTypes[0]); } else if (operandTypes[0].CILType.Equals(typeof(UFix)) || operandTypes[0].CILType.Equals(typeof(SFix))) { var fmt = operandTypes[0].GetFixFormat(); // computation works for at most 26 fractional bits double xinc = Math.Pow(2.0, Math.Max(-26, -fmt.FracWidth)); double yinc = 1.0 - Math.Cos(xinc); int fw = -MathExt.FloorLog2(yinc); // Xilinx Cordic doesn't like more than 48 result bits if (fw > 48) { fw = 48; } while (fw >= 0) { yield return(SFix.MakeType(2, fw)); --fw; } } else { throw new NotSupportedException(); } break; case InstructionCodes.ScSin: case InstructionCodes.ScCos: case InstructionCodes.ScSinCos: if (operandTypes[0].CILType.Equals(typeof(float)) || operandTypes[0].CILType.Equals(typeof(double))) { yield return(operandTypes[0]); } else if (operandTypes[0].CILType.Equals(typeof(UFix)) || operandTypes[0].CILType.Equals(typeof(SFix))) { var fmt = operandTypes[0].GetFixFormat(); // computation works for at most 26 fractional bits double xinc = Math.Pow(2.0, Math.Max(-26, -fmt.FracWidth)); double yinc = 1.0 - Math.Cos(xinc); int fw = -MathExt.FloorLog2(yinc); // Xilinx Cordic doesn't like more than 48 result bits if (fw > 48) { fw = 48; } while (fw >= 0) { yield return(SFix.MakeType(2, fw)); --fw; } } else { throw new NotSupportedException(); } break; case InstructionCodes.Sqrt: if (operandTypes[0].CILType.Equals(typeof(float)) || operandTypes[0].CILType.Equals(typeof(double))) { yield return(operandTypes[0]); } else if (operandTypes[0].CILType.Equals(typeof(UFix))) { var fmt = UFix.GetFormat(operandTypes[0]); int iw = (fmt.IntWidth + 1) / 2; yield return(UFix.MakeType(iw, fmt.TotalWidth - iw)); } else if (operandTypes[0].CILType.Equals(typeof(SFix))) { var fmt = SFix.GetFormat(operandTypes[0]); int iw = fmt.IntWidth / 2; yield return(UFix.MakeType(iw, fmt.TotalWidth - iw - 1)); } else if (operandTypes[0].CILType.Equals(typeof(Unsigned))) { var fmt = UFix.GetFormat(operandTypes[0]); int iw = (fmt.IntWidth + 1) / 2; yield return(Unsigned.MakeType(iw)); } else if (operandTypes[0].CILType.Equals(typeof(Signed))) { var fmt = SFix.GetFormat(operandTypes[0]); int iw = fmt.IntWidth / 2; yield return(Unsigned.MakeType(iw)); } else { throw new NotImplementedException(); } break; case InstructionCodes.Cmp: throw new NotImplementedException(); case InstructionCodes.Concat: { var v1 = (StdLogicVector)operandTypes[0].GetSampleInstance(); var v2 = (StdLogicVector)operandTypes[1].GetSampleInstance(); var c = v1.Concat(v2); yield return(TypeDescriptor.GetTypeOf(c)); } break; case InstructionCodes.Convert: throw new NotImplementedException(); case InstructionCodes.Dig: case InstructionCodes.Dup: case InstructionCodes.Swap: throw new NotSupportedException(); case InstructionCodes.Div: { dynamic o1 = operandTypes[0].GetSampleInstance(); dynamic o2 = operandTypes[1].GetSampleInstance(ETypeCreationOptions.NonZero); object r = o1 / o2; yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.ExitMarshal: case InstructionCodes.Goto: case InstructionCodes.Nop: case InstructionCodes.Pop: case InstructionCodes.Return: case InstructionCodes.StelemFixA: case InstructionCodes.StelemFixAFixI: case InstructionCodes.StoreVar: case InstructionCodes.WrMem: case InstructionCodes.WrMemFix: case InstructionCodes.WrPort: yield break; case InstructionCodes.Mod2: { var fmt = operandTypes[0].GetFixFormat(); if (fmt == null) { throw new NotSupportedException("mod2 is only supported for fixed-point types"); } for (int iw = 2; iw <= fmt.IntWidth; iw++) { yield return(new FixFormat(fmt.IsSigned, iw, fmt.FracWidth).ToType()); } } break; case InstructionCodes.DivQF: case InstructionCodes.ExtendSign: case InstructionCodes.Ld0: case InstructionCodes.LdelemFixA: case InstructionCodes.LdelemFixAFixI: case InstructionCodes.LdMemBase: case InstructionCodes.LShift: case InstructionCodes.RdMem: case InstructionCodes.RdMemFix: case InstructionCodes.RShift: case InstructionCodes.Sign: case InstructionCodes.SliceFixI: throw new NotImplementedException(); case InstructionCodes.IsEq: case InstructionCodes.IsGt: case InstructionCodes.IsGte: case InstructionCodes.IsLt: case InstructionCodes.IsLte: case InstructionCodes.IsNEq: yield return(typeof(bool)); break; case InstructionCodes.LdConst: yield return(TypeDescriptor.GetTypeOf(instr.Operand)); break; case InstructionCodes.LoadVar: { var lit = (IStorableLiteral)instr.Operand; yield return(lit.Type); } break; case InstructionCodes.Max: case InstructionCodes.Min: yield return(operandTypes[0]); break; case InstructionCodes.Mul: { dynamic o1 = operandTypes[0].GetSampleInstance(); dynamic o2 = operandTypes[1].GetSampleInstance(); object r = o1 * o2; yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.Neg: { dynamic o1 = operandTypes[0].GetSampleInstance(); object r = -o1; yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.Not: { dynamic o1 = operandTypes[0].GetSampleInstance(); object r = !o1; yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.Or: { dynamic o1 = operandTypes[0].GetSampleInstance(); dynamic o2 = operandTypes[1].GetSampleInstance(); object r = o1 | o2; yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.RdPort: { var port = (ISignalOrPortDescriptor)instr.Operand; yield return(port.ElementType); } break; case InstructionCodes.Rem: { dynamic o1 = operandTypes[0].GetSampleInstance(); dynamic o2 = operandTypes[1].GetSampleInstance(ETypeCreationOptions.NonZero); object r = o1 % o2; yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.Rempow2: { dynamic o1 = operandTypes[0].GetSampleInstance(); int n = (int)instr.Operand; object r = MathExt.Rempow2((dynamic)o1, n); yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.Select: yield return(operandTypes[1]); break; case InstructionCodes.Slice: yield return(typeof(StdLogicVector)); break; case InstructionCodes.Sub: { dynamic o1 = operandTypes[0].GetSampleInstance(); dynamic o2 = operandTypes[1].GetSampleInstance(); object r = o1 - o2; yield return(TypeDescriptor.GetTypeOf(r)); } break; case InstructionCodes.Xor: { dynamic o1 = operandTypes[0].GetSampleInstance(); dynamic o2 = operandTypes[1].GetSampleInstance(); object r = o1 ^ o2; yield return(TypeDescriptor.GetTypeOf(r)); } break; default: throw new NotImplementedException(); } }
public IEnumerable <IXILMapping> TryMap(ITransactionSite taSite, XILInstr instr, TypeDescriptor[] operandTypes, TypeDescriptor[] resultTypes) { var mappers = _mlookup.Get(instr.Name); return(mappers.SelectMany(m => m.TryMap(taSite, instr, operandTypes, resultTypes))); }
public IEnumerable <IXILMapper> LookupMappers(XILInstr instr) { return(_mlookup.Get(instr.Name)); }
public ClassifyCookie(XILInstr instr) { Contract.Requires(instr != null); _instr = instr; }
private XIL3Function Run() { List <XIL3Instr> xil3is = new List <XIL3Instr>(); List <BranchLabel> targets = new List <BranchLabel>(); foreach (XILSInstr xilsi in _func.Instructions) { switch (xilsi.Name) { case InstructionCodes.Pop: _stack.Pop(); break; case InstructionCodes.Dup: _stack.Push(_stack.Peek()); break; case InstructionCodes.Swap: { int a = _stack.Pop(); int b = _stack.Pop(); _stack.Push(a); _stack.Push(b); } break; case InstructionCodes.Dig: { int pos = (int)xilsi.StaticOperand; Stack <int> tmpStack = new Stack <int>(); for (int i = 0; i < pos; i++) { tmpStack.Push(_stack.Pop()); } int dig = _stack.Pop(); for (int i = 0; i < pos; i++) { _stack.Push(tmpStack.Pop()); } _stack.Push(dig); } break; default: { int[] oslots, rslots; InstructionDependency[] preds; Remap(xilsi, out preds, out oslots, out rslots); XIL3Instr xil3i; switch (xilsi.Name) { case InstructionCodes.Goto: case InstructionCodes.BranchIfFalse: case InstructionCodes.BranchIfTrue: { BranchLabel orgTarget = (BranchLabel)xilsi.StaticOperand; BranchLabel target = new BranchLabel() { InstructionIndex = orgTarget.InstructionIndex }; targets.Add(target); xil3i = new XILInstr(xilsi.Name, target).Create3AC(preds, oslots, rslots); } break; default: xil3i = xilsi.Command.Create3AC(preds, oslots, rslots); break; } xil3i.Index = xil3is.Count; xil3i.CILRef = xilsi.CILRef; xil3is.Add(xil3i); _indexMap[xilsi.Index] = xil3i.Index; } break; } } foreach (BranchLabel target in targets) { target.InstructionIndex = _indexMap[target.InstructionIndex]; } return(new XIL3Function(_func.Name, _func.Arguments, _func.Locals, xil3is.ToArray(), _slotTypes.ToArray())); }