private void HandleStoreVar(XILSInstr i) { int readPoint; Variable local = i.StaticOperand as Variable; if (DflowAnalyzer.IsReadAfterWrite(i.Index, out readPoint)) { var preds = RemapPreds(i.Preds); // keep expression on the stack, but bury it at the very bottom. for (int j = 1; j < _resultStack.Count; j++) { var resultTypes = TypeStack.Reverse().Skip(1).Concat(TypeStack.Skip(_resultStack.Count - 1)).ToArray(); Emit(DefaultInstructionSet.Instance.Dig(_resultStack.Count - 1).CreateStk( preds, TypeStack.Reverse().ToArray(), resultTypes)); preds = new InstructionDependency[0]; } _read2write[readPoint] = _resultStack[0]; } else if (local == null) { ProcessDefault(i); } else if (DflowAnalyzer.EliminableLocals.Contains(local.LocalIndex)) { Emit(DefaultInstructionSet.Instance.Pop().CreateStk(1, local.Type)); } else { ProcessDefault(i); } }
private void HandleSinOrCos(XILSInstr i) { FixFormat oformat, rformat; IsFix(i.OperandTypes[0], out oformat); IsFix(i.ResultTypes[0], out rformat); var preds = RemapPreds(i.Preds); if (oformat == null) { Emit(i.Command.CreateStk(preds, 1, i.OperandTypes[0], i.ResultTypes[0])); } else { TypeDescriptor otype = i.OperandTypes[0]; if (!i.OperandTypes[0].CILType.Equals(typeof(SFix))) { var itype = SFix.MakeType(oformat.IntWidth + 1, oformat.FracWidth); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, i.OperandTypes, i.ResultTypes)); preds = new InstructionDependency[0]; otype = itype; } var nrtype = SFix.MakeType(2, rformat.FracWidth); Emit(i.Command.CreateStk(preds, 1, otype, nrtype)); if (!i.ResultTypes[0].Equals(nrtype)) { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, nrtype, i.ResultTypes[0])); } } }
private void HandleScSinCos(XILSInstr i) { var preds = RemapPreds(i.Preds); var infmt = i.OperandTypes[0].GetFixFormat(); var outfmt = i.ResultTypes[0].GetFixFormat(); if (infmt == null) { Emit(i.Command.CreateStk(preds, i.OperandTypes, i.ResultTypes)); } else { var otype = i.OperandTypes[0]; if (HaveXilinxCordic && infmt.IntWidth != 3) { // Xilinx Cordic needs exactly 3 integer bits for operand otype = SFix.MakeType(3, infmt.FracWidth); Emit(DefaultInstructionSet.Instance.Convert().CreateStk( preds, 1, i.OperandTypes[0], otype)); } else if (infmt.IntWidth != 2) { // Any reasonable core (e.g. LUT-based implementation) will require 2 integer operand bits otype = SFix.MakeType(2, infmt.FracWidth); Emit(DefaultInstructionSet.Instance.Convert().CreateStk( preds, 1, i.OperandTypes[0], otype)); } preds = new InstructionDependency[0]; var rtype = i.ResultTypes[0]; if (outfmt.IntWidth != 2) { // we gonna need exactly 2 integer bits for results rtype = SFix.MakeType(2, outfmt.FracWidth); } Emit(DefaultInstructionSet.Instance.ScSinCos().CreateStk( preds, 1, otype, rtype, rtype)); if (!rtype.Equals(i.ResultTypes[1])) { Emit(DefaultInstructionSet.Instance.Convert().CreateStk( 1, rtype, i.ResultTypes[1])); } if (!rtype.Equals(i.ResultTypes[0])) { Emit(DefaultInstructionSet.Instance.Swap().CreateStk( 2, i.ResultTypes[0], rtype, rtype, i.ResultTypes[0])); Emit(DefaultInstructionSet.Instance.Convert().CreateStk( 1, rtype, i.ResultTypes[0])); Emit(DefaultInstructionSet.Instance.Swap().CreateStk( 2, rtype, rtype, rtype, rtype)); } } }
private void HandleNeg(XILSInstr i) { var preds = RemapPreds(i.Preds); var nrtype = GetNativeResultType(i, i.OperandTypes); var otype = i.OperandTypes[0]; if (otype.CILType.Equals(typeof(UFix)) && nrtype.CILType.Equals(typeof(SFix))) { var nrformat = nrtype.GetFixFormat(); var itype = SFix.MakeType(nrformat.IntWidth, nrformat.FracWidth); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, otype, itype)); preds = new InstructionDependency[0]; otype = itype; } Emit(i.Command.CreateStk(preds, 1, otype, nrtype)); if (!nrtype.Equals(i.ResultTypes[0])) { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, nrtype, i.ResultTypes[0])); } }
private IEnumerable <XILSInstr> Expand(TypeDescriptor joker, TypeDescriptor rtype, InstructionDependency[] preds) { if (ExpansionCreator != null) { foreach (var instr in ExpansionCreator(joker, rtype, preds)) { yield return(instr); } } else { bool first = true; foreach (XILSInstr xilsi in Expansion) { TypeDescriptor[] otypes = (TypeDescriptor[])xilsi.OperandTypes.Clone(); TypeDescriptor[] rtypes = (TypeDescriptor[])xilsi.ResultTypes.Clone(); for (int i = 0; i < otypes.Length; i++) { if (otypes[i].IsConstrained && !otypes[i].IsComplete) { otypes[i] = joker; } } for (int i = 0; i < rtypes.Length; i++) { if (rtypes[i].IsConstrained && !rtypes[i].IsComplete) { rtypes[i] = joker; } } yield return(xilsi.Command.CreateStk(preds, otypes, rtypes)); if (first) { preds = new InstructionDependency[0]; first = false; } } } }
private void ProcessStoreVariable(XILSInstr i) { var lit = (IStorableLiteral)i.StaticOperand; var local = lit as Variable; IStorableLiteral newLit; if (local != null) { Variable newLocal; if (!_localDic.TryGetValue(local.Name, out newLocal)) { newLocal = new Variable(TypeStack.Peek()) { Name = local.Name }; _localDic[local.Name] = newLocal; } newLit = newLocal; } else { newLit = lit; } var preds = RemapPreds(i.Preds); if (!TypeStack.Peek().Equals(newLit.Type)) { Convert(preds, TypeStack.Peek(), newLit.Type); preds = new InstructionDependency[0]; } var inew = new XILSInstr( DefaultInstructionSet.Instance.StoreVar(newLit), preds, new TypeDescriptor[] { newLit.Type }, new TypeDescriptor[0]); Emit(inew); }
private void ProcessSelect(XILSInstr i) { var preds = RemapPreds(i.Preds); var ot1 = i.OperandTypes[0]; var ot2 = i.OperandTypes[1]; var rt = i.ResultTypes[0]; var ct = GetCommonType(GetCommonType(ot1, ot2), rt); if (!ot2.Equals(ct)) { // stack: [ x y cond ] Swap(preds); // stack: [ x cond y ] Convert(preds, ot2, ct); Swap(); // stack: [ x y cond ] preds = new InstructionDependency[0]; } if (!ot1.Equals(ct)) { // stack: [ x y cond ] Dig(preds, 2); // stack: [ y cond x ] Convert(ot1, ct); Dig(2); // stack: [ cond x y ] Dig(2); // stack: [ x y cond ] preds = new InstructionDependency[0]; } var inew = DefaultInstructionSet.Instance.Select().CreateStk(preds, 3, ct, ct, i.OperandTypes[2], ct); Emit(inew); if (!rt.Equals(ct)) { Convert(ct, rt); } }
private void Remap(XILSInstr xilsi, out InstructionDependency[] preds, out int[] oslots, out int[] rslots) { oslots = new int[xilsi.OperandTypes.Length]; rslots = new int[xilsi.ResultTypes.Length]; for (int i = oslots.Length - 1; i >= 0; i--) oslots[i] = _stack.Pop(); for (int i = 0; i < rslots.Length; i++) { rslots[i] = _curSlot; _stack.Push(_curSlot); Debug.Assert(xilsi.ResultTypes[i] != null); _slotTypes.Add(xilsi.ResultTypes[i]); ++_curSlot; } preds = xilsi.Preds.SelectMany(i => { int j; if (_indexMap.TryGetValue(i.PredIndex, out j)) return new InstructionDependency[] { i.Remap(j) }; else return empty; }).ToArray(); }
/// <summary> /// Remaps input instruction dependencies to the output side /// </summary> /// <param name="preds">input instruction dependencies</param> /// <returns>corresponding output-side dependencies</returns> protected InstructionDependency[] RemapPreds(InstructionDependency[] preds) { var result = new List<InstructionDependency>(); foreach (var pred in preds) { int next, cur; if (!_remap.TryGetValue(pred.PredIndex, out cur)) continue; if (!_remap.TryGetValue(pred.PredIndex + 1, out next)) next = cur + 1; for (int i = cur; i < next; i++) result.Add(pred.Remap(i)); } return result.ToArray(); }
private static IEnumerable<XILSInstr> Rewrite_Sin_ScSinCos_fixpt(TypeDescriptor joker, TypeDescriptor rtype, InstructionDependency[] preds) { var iset = DefaultInstructionSet.Instance; var fmt = joker.GetFixFormat(); var rfmt = rtype.GetFixFormat(); int pifw = fmt.FracWidth; var pitype = SFix.MakeType(0, pifw); int muliw = fmt.IntWidth; var multype = SFix.MakeType(muliw, fmt.FracWidth + pifw); int fw = Math.Max(5, rfmt.FracWidth + 1); // Xilinx Cordic needs at least 8 input bits fw = Math.Min(45, fw); // Xilinx Cordic likes at most 48 input bits var cuttype = SFix.MakeType(3, fw); var modtype = SFix.MakeType(3, fw); // Actually, 1 integer bit less is required. However, Xilinx Cordic needs the additional bit. int fwr = Math.Max(6, rfmt.FracWidth); // Xilinx Cordic needs at least 8 output bits (?) fwr = Math.Min(46, fwr); // Xilinx Cordic likes at most 48 output bits (?) var sintype = SFix.MakeType(2, fwr); if (muliw <= 1) { return new XILSInstr[] { iset.LdConst(SFix.FromDouble(1.0 / Math.PI, 0, pifw)).CreateStk(preds, 0, pitype), iset.Mul().CreateStk(2, joker, pitype, multype), iset.Convert().CreateStk(1, multype, modtype), iset.ScSinCos().CreateStk(1, modtype, sintype, sintype), iset.Swap().CreateStk(2, sintype, sintype, sintype, sintype), iset.Pop().CreateStk(1, sintype) }; } else { return new XILSInstr[] { iset.LdConst(SFix.FromDouble(1.0 / Math.PI, 0, pifw)).CreateStk(preds, 0, pitype), iset.Mul().CreateStk(2, joker, pitype, multype), iset.Convert().CreateStk(1, multype, cuttype), iset.Mod2().CreateStk(1, cuttype, modtype), iset.ScSinCos().CreateStk(1, modtype, sintype, sintype), iset.Swap().CreateStk(2, sintype, sintype, sintype, sintype), iset.Pop().CreateStk(1, sintype) }; } }
public override IEnumerable<XILSInstr> Expand(XILSInstr instr, InstructionDependency[] preds) { if (instr.Name != Match.Name) return null; TypeDescriptor joker = null; Debug.Assert(instr.OperandTypes.Length == Match.OperandTypes.Length); Debug.Assert(instr.ResultTypes.Length == Match.ResultTypes.Length); for (int i = 0; i < instr.OperandTypes.Length; i++) { TypeDescriptor otypei = instr.OperandTypes[i]; TypeDescriptor otypem = Match.OperandTypes[i]; if (!otypei.CILType.Equals(otypem.CILType)) return null; if (otypem.IsConstrained && !otypem.IsComplete) { if (otypei.IsConstrained) { joker = otypei; otypei = otypei.MakeUnconstrainedType(); } else { return null; } } } for (int i = 0; i < instr.ResultTypes.Length; i++) { TypeDescriptor rtypei = instr.ResultTypes[i]; TypeDescriptor rtypem = Match.ResultTypes[i]; if (!rtypei.CILType.Equals(rtypem.CILType)) return null; if (rtypem.IsConstrained && !rtypem.IsComplete) { if (rtypei.IsConstrained) { if (joker == null) joker = rtypei; rtypei = rtypei.MakeUnconstrainedType(); } else { return null; } } } return Expand( joker, instr.ResultTypes.Length == 0 ? null : instr.ResultTypes[0], preds); }
/// <summary> /// Expands a given XIL-S instruction to a sequence /// </summary> /// <param name="instr">XIL-S instruction to expand</param> /// <param name="preds">remapped dependencies</param> /// <returns>expanded sequence</returns> public abstract IEnumerable<XILSInstr> Expand(XILSInstr instr, InstructionDependency[] preds);
private IEnumerable<XILSInstr> Expand(TypeDescriptor joker, TypeDescriptor rtype, InstructionDependency[] preds) { if (ExpansionCreator != null) { foreach (var instr in ExpansionCreator(joker, rtype, preds)) yield return instr; } else { bool first = true; foreach (XILSInstr xilsi in Expansion) { TypeDescriptor[] otypes = (TypeDescriptor[])xilsi.OperandTypes.Clone(); TypeDescriptor[] rtypes = (TypeDescriptor[])xilsi.ResultTypes.Clone(); for (int i = 0; i < otypes.Length; i++) { if (otypes[i].IsConstrained && !otypes[i].IsComplete) otypes[i] = joker; } for (int i = 0; i < rtypes.Length; i++) { if (rtypes[i].IsConstrained && !rtypes[i].IsComplete) rtypes[i] = joker; } yield return xilsi.Command.CreateStk(preds, otypes, rtypes); if (first) { preds = new InstructionDependency[0]; first = false; } } } }
/// <summary> /// Remaps the data dependencies from input instructions to output instructions. /// </summary> /// <param name="preds">dependencies of input instruction</param> /// <returns>corresponding dependencies for output instruction</returns> protected InstructionDependency[] RemapPreds(InstructionDependency[] preds) { var result = new List<InstructionDependency>(); foreach (var pred in preds) { int prev, cur; if (!_remap.TryGetValue(pred.PredIndex, out cur)) continue; if (!_remap.TryGetValue(pred.PredIndex - 1, out prev)) prev = cur - 1; for (int i = prev + 1; i <= cur; i++) result.Add(pred.Remap(i)); } return result.ToArray(); }
private InstructionDependency[] EqualizeTypes(XILSInstr i, bool makeSameSize, TypeDescriptor[] otypes) { var otype0 = i.OperandTypes[0]; var otype1 = i.OperandTypes[1]; FixFormat fmt0, fmt1; bool flag0 = IsFix(otype0, out fmt0); bool flag1 = IsFix(otype1, out fmt1); if (flag0 != flag1) throw new InvalidOperationException("Incompatible types"); var preds = RemapPreds(i.Preds); if (flag0) { otypes[0] = otype0; otypes[1] = otype1; if (fmt0.IsSigned && !fmt1.IsSigned) { var sample = (UFix)otype1.GetSampleInstance(); var signed = sample.SFixValue; var stype1 = TypeDescriptor.GetTypeOf(signed); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, otype1, stype1)); otype1 = stype1; fmt1 = signed.Format; preds = new InstructionDependency[0]; otypes[1] = otype1; } if (!fmt0.IsSigned && fmt1.IsSigned) { var sample = (UFix)otype0.GetSampleInstance(); var signed = sample.SFixValue; var stype0 = TypeDescriptor.GetTypeOf(signed); Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(preds, 2, otype0, otype1, otype1, otype0)); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, otype0, stype0)); otype0 = stype0; Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(preds, 2, otype1, otype0, otype0, otype1)); fmt0 = signed.Format; preds = new InstructionDependency[0]; otypes[0] = otype0; } if (makeSameSize) { int intWidth = Math.Max(fmt0.IntWidth, fmt1.IntWidth); int fracWidth = Math.Max(fmt0.FracWidth, fmt1.FracWidth); object rsample; if (fmt0.IsSigned) rsample = SFix.FromDouble(0.0, intWidth, fracWidth); else rsample = UFix.FromDouble(0.0, intWidth, fracWidth); var rtype = TypeDescriptor.GetTypeOf(rsample); if (intWidth > fmt0.IntWidth || fracWidth > fmt0.FracWidth) { Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(preds, 2, otype0, otype1, otype1, otype0)); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, otype0, rtype)); Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(preds, 2, otype1, rtype, rtype, otype1)); preds = new InstructionDependency[0]; } if (intWidth > fmt1.IntWidth || fracWidth > fmt1.FracWidth) { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, otype1, rtype)); } otypes[0] = rtype; otypes[1] = rtype; } } else { otypes[0] = i.OperandTypes[0]; otypes[1] = i.OperandTypes[1]; } return preds; }
private InstructionDependency[] EqualizeTypes(XILSInstr i, bool makeSameSize, TypeDescriptor[] otypes) { var otype0 = i.OperandTypes[0]; var otype1 = i.OperandTypes[1]; FixFormat fmt0, fmt1; bool flag0 = IsFix(otype0, out fmt0); bool flag1 = IsFix(otype1, out fmt1); if (flag0 != flag1) { throw new InvalidOperationException("Incompatible types"); } var preds = RemapPreds(i.Preds); if (flag0) { otypes[0] = otype0; otypes[1] = otype1; if (fmt0.IsSigned && !fmt1.IsSigned) { var sample = (UFix)otype1.GetSampleInstance(); var signed = sample.SFixValue; var stype1 = TypeDescriptor.GetTypeOf(signed); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, otype1, stype1)); otype1 = stype1; fmt1 = signed.Format; preds = new InstructionDependency[0]; otypes[1] = otype1; } if (!fmt0.IsSigned && fmt1.IsSigned) { var sample = (UFix)otype0.GetSampleInstance(); var signed = sample.SFixValue; var stype0 = TypeDescriptor.GetTypeOf(signed); Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(preds, 2, otype0, otype1, otype1, otype0)); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, otype0, stype0)); otype0 = stype0; Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(preds, 2, otype1, otype0, otype0, otype1)); fmt0 = signed.Format; preds = new InstructionDependency[0]; otypes[0] = otype0; } if (makeSameSize) { int intWidth = Math.Max(fmt0.IntWidth, fmt1.IntWidth); int fracWidth = Math.Max(fmt0.FracWidth, fmt1.FracWidth); object rsample; if (fmt0.IsSigned) { rsample = SFix.FromDouble(0.0, intWidth, fracWidth); } else { rsample = UFix.FromDouble(0.0, intWidth, fracWidth); } var rtype = TypeDescriptor.GetTypeOf(rsample); if (intWidth > fmt0.IntWidth || fracWidth > fmt0.FracWidth) { Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(preds, 2, otype0, otype1, otype1, otype0)); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, otype0, rtype)); Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(preds, 2, otype1, rtype, rtype, otype1)); preds = new InstructionDependency[0]; } if (intWidth > fmt1.IntWidth || fracWidth > fmt1.FracWidth) { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, otype1, rtype)); } otypes[0] = rtype; otypes[1] = rtype; } } else { otypes[0] = i.OperandTypes[0]; otypes[1] = i.OperandTypes[1]; } return(preds); }
private InstructionDependency[] Convert(InstructionDependency[] preds, TypeDescriptor from, TypeDescriptor to) { if (from.Equals(to)) { // nothing to do return preds; } else if (IsSFix(from) && IsUFix(to)) { var fromFmt = SFix.GetFormat(from); var toFmt = UFix.GetFormat(to); int interIW = toFmt.IntWidth + 1; int interFW = toFmt.FracWidth; if (interIW != fromFmt.IntWidth || interFW != fromFmt.FracWidth) { var interType = SFix.MakeType(interIW, interFW); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, interType)); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, interType, to)); } else { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to)); } return new InstructionDependency[0]; } else if (IsUFix(from) && IsSFix(to)) { var fromFmt = UFix.GetFormat(from); var toFmt = SFix.GetFormat(to); int interIW = toFmt.IntWidth - 1; int interFW = toFmt.FracWidth; if (interIW != fromFmt.IntWidth || interFW != fromFmt.FracWidth) { var interType = UFix.MakeType(interIW, interFW); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, interType)); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, interType, to)); } else { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to)); } return new InstructionDependency[0]; } else if (IsSLV(from)) { int wfrom = TypeLowering.Instance.GetWireWidth(from); int wto = TypeLowering.Instance.GetWireWidth(to); if (wfrom == wto) { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to)); } else { var interType = StdLogicVector.MakeType(wto); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, interType)); Convert(interType, to); } return new InstructionDependency[0]; } else if (IsSLV(to)) { int wfrom = TypeLowering.Instance.GetWireWidth(from); int wto = TypeLowering.Instance.GetWireWidth(to); if (wfrom == wto) { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to)); } else { var interType = StdLogicVector.MakeType(wfrom); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, interType)); Convert(interType, to); } return new InstructionDependency[0]; } else { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to)); return new InstructionDependency[0]; } }
private void HandleNeg(XILSInstr i) { var preds = RemapPreds(i.Preds); var nrtype = GetNativeResultType(i, i.OperandTypes); var otype = i.OperandTypes[0]; if (otype.CILType.Equals(typeof(UFix)) && nrtype.CILType.Equals(typeof(SFix))) { var nrformat = nrtype.GetFixFormat(); var itype = SFix.MakeType(nrformat.IntWidth, nrformat.FracWidth); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, otype, itype)); preds = new InstructionDependency[0]; otype = itype; } Emit(i.Command.CreateStk(preds, 1, otype, nrtype)); if (!nrtype.Equals(i.ResultTypes[0])) Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, nrtype, i.ResultTypes[0])); }
private void Swap(InstructionDependency[] preds) { Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(preds, 2, TypeStack.ElementAt(1), TypeStack.Peek(), TypeStack.Peek(), TypeStack.ElementAt(1))); }
private void Dig(InstructionDependency[] preds, int index) { var otypes = new TypeDescriptor[index + 1]; var rtypes = new TypeDescriptor[index + 1]; for (int i = 0; i < otypes.Length; i++) { otypes[i] = TypeStack.ElementAt(index - i); rtypes[i] = TypeStack.ElementAt(i == index ? index : index - i - 1); } Emit(DefaultInstructionSet.Instance.Dig(index).CreateStk(preds, otypes, rtypes)); }