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 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) }); } }
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])); } }
/// <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(); } }
/// <summary> /// Returns a type which is able to represent either of two given types without loss of precision /// </summary> /// <param name="td1">first given type</param> /// <param name="td2">second given type</param> /// <returns></returns> private static TypeDescriptor GetCommonType(TypeDescriptor td1, TypeDescriptor td2) { if (td1.Equals(td2)) { return(td1); } if (IsSFix(td1) && IsUFix(td2)) { var fmt1 = SFix.GetFormat(td1); var fmt2 = UFix.GetFormat(td2); return(SFix.MakeType( Math.Max(fmt1.IntWidth, fmt2.IntWidth + 1), Math.Max(fmt1.FracWidth, fmt2.FracWidth))); } else if (IsUFix(td1) && IsSFix(td2)) { return(GetCommonType(td2, td1)); } else if (IsSFix(td1) && IsSFix(td2)) { var fmt1 = SFix.GetFormat(td1); var fmt2 = SFix.GetFormat(td2); return(SFix.MakeType( Math.Max(fmt1.IntWidth, fmt2.IntWidth), Math.Max(fmt1.FracWidth, fmt2.FracWidth))); } else if (IsUFix(td1) && IsUFix(td2)) { var fmt1 = UFix.GetFormat(td1); var fmt2 = UFix.GetFormat(td2); return(UFix.MakeType( Math.Max(fmt1.IntWidth, fmt2.IntWidth), Math.Max(fmt1.FracWidth, fmt2.FracWidth))); } else if (IsSigned(td1)) { var fmt = SFix.GetFormat(td1); var td1x = SFix.MakeType(fmt.IntWidth, fmt.FracWidth); return(GetCommonType(td1x, td2)); } else if (IsSigned(td2)) { return(GetCommonType(td2, td1)); } else if (IsUnsigned(td1)) { var fmt = UFix.GetFormat(td1); var td1x = UFix.MakeType(fmt.IntWidth, fmt.FracWidth); return(GetCommonType(td1x, td2)); } else if (IsUnsigned(td2)) { return(GetCommonType(td2, td1)); } else { throw new NotSupportedException( "Cannot determine common type between " + td1.ToString() + " and " + td2.ToString()); } }
private void ProcessAddSub(XILSInstr i) { var preds = RemapPreds(i.Preds); if (IsFixed(i.OperandTypes[0]) && IsFixed(i.OperandTypes[1])) { if (IsSFix(i.OperandTypes[0]) && IsUFix(i.OperandTypes[1])) { var sfixt = MakeUFixSFix(i.OperandTypes[1]); Convert(preds, i.OperandTypes[1], sfixt); var inew = i.Command.CreateStk(2, i.OperandTypes[0], sfixt, i.ResultTypes[0]); ProcessAddSub(inew); } else if (IsUFix(i.OperandTypes[0]) && IsSFix(i.OperandTypes[1])) { var sfixt = MakeUFixSFix(i.OperandTypes[0]); Swap(preds); Convert(i.OperandTypes[0], sfixt); Swap(); var inew = i.Command.CreateStk(2, sfixt, i.OperandTypes[1], i.ResultTypes[0]); ProcessAddSub(inew); } else if (IsSFix(i.OperandTypes[0]) && IsSFix(i.OperandTypes[1])) { var fmt0 = SFix.GetFormat(i.OperandTypes[0]); var fmt1 = SFix.GetFormat(i.OperandTypes[1]); int iw = Math.Max(fmt0.IntWidth, fmt1.IntWidth); int fw = Math.Max(fmt0.FracWidth, fmt1.FracWidth); var smp = SFix.FromDouble(0.0, iw, fw); var to = TypeDescriptor.GetTypeOf(smp); var fmte = SFix.GetFormat(to); if (!fmte.Equals(fmt1)) { Convert(preds, i.OperandTypes[1], to); var inew = i.Command.CreateStk(2, i.OperandTypes[0], to, i.ResultTypes[0]); ProcessAddSub(inew); } else if (!fmte.Equals(fmt0)) { Swap(preds); Convert(i.OperandTypes[0], to); Swap(); var inew = i.Command.CreateStk(2, to, i.OperandTypes[1], i.ResultTypes[0]); ProcessAddSub(inew); } else { dynamic s0 = i.OperandTypes[0].GetSampleInstance(); dynamic s1 = i.OperandTypes[1].GetSampleInstance(); object r = s0 + s1; var rtype = TypeDescriptor.GetTypeOf(r); Emit(i.Command.CreateStk(preds, 2, i.OperandTypes[0], i.OperandTypes[1], rtype)); if (!rtype.Equals(i.ResultTypes[0])) { Convert(rtype, i.ResultTypes[0]); } } } else if (IsUFix(i.OperandTypes[0]) && IsUFix(i.OperandTypes[1]) && IsSFix(i.ResultTypes[0])) { var sfixt = MakeUFixSFix(i.OperandTypes[1]); Convert(preds, i.OperandTypes[1], sfixt); var inew = i.Command.CreateStk(2, i.OperandTypes[0], sfixt, i.ResultTypes[0]); ProcessAddSub(inew); } else if (IsUFix(i.OperandTypes[0]) && IsUFix(i.OperandTypes[1])) { var fmt0 = UFix.GetFormat(i.OperandTypes[0]); var fmt1 = UFix.GetFormat(i.OperandTypes[1]); int iw = Math.Max(fmt0.IntWidth, fmt1.IntWidth); int fw = Math.Max(fmt0.FracWidth, fmt1.FracWidth); var smp = UFix.FromDouble(0.0, iw, fw); var to = TypeDescriptor.GetTypeOf(smp); var fmte = UFix.GetFormat(to); if (!fmte.Equals(fmt1)) { Convert(preds, i.OperandTypes[1], to); var inew = i.Command.CreateStk(2, i.OperandTypes[0], to, i.ResultTypes[0]); ProcessAddSub(inew); } else if (!fmte.Equals(fmt0)) { Swap(preds); Convert(preds, i.OperandTypes[0], to); Swap(); var inew = i.Command.CreateStk(2, to, i.OperandTypes[1], i.ResultTypes[0]); ProcessAddSub(inew); } else { dynamic s0 = i.OperandTypes[0].GetSampleInstance(); dynamic s1 = i.OperandTypes[1].GetSampleInstance(); object r = s0 + s1; var rtype = TypeDescriptor.GetTypeOf(r); Emit(i.Command.CreateStk(preds, 2, i.OperandTypes[0], i.OperandTypes[1], rtype)); if (!rtype.Equals(i.ResultTypes[0])) { Convert(rtype, i.ResultTypes[0]); } } } else { Emit(i.Command.CreateStk(preds, 2, i.OperandTypes[0], i.OperandTypes[1], i.ResultTypes[0])); } } else if (IsFloat(i.OperandTypes[0]) && IsFloat(i.OperandTypes[1])) { dynamic s0 = i.OperandTypes[0].GetSampleInstance(); dynamic s1 = i.OperandTypes[1].GetSampleInstance(); object r = s0 + s1; var rtype = TypeDescriptor.GetTypeOf(r); Emit(i.Command.CreateStk(preds, 2, i.OperandTypes[0], i.OperandTypes[1], rtype)); if (!rtype.Equals(i.ResultTypes[0])) { Convert(rtype, i.ResultTypes[0]); } } else if (IsFixed(i.OperandTypes[0]) && IsFloat(i.OperandTypes[1]) && IsFixed(i.ResultTypes[0])) { Convert(preds, i.OperandTypes[1], i.OperandTypes[0]); var inew = i.Command.CreateStk(2, i.OperandTypes[0], i.OperandTypes[0], i.ResultTypes[0]); ProcessAddSub(inew); } else if (IsFloat(i.OperandTypes[0]) && IsFixed(i.OperandTypes[1]) && IsFixed(i.ResultTypes[0])) { Swap(preds); Convert(i.OperandTypes[0], i.OperandTypes[1]); Swap(); var inew = i.Command.CreateStk(2, i.OperandTypes[1], i.OperandTypes[0], i.ResultTypes[0]); ProcessAddSub(inew); } else if (IsFixed(i.OperandTypes[0]) && IsFloat(i.OperandTypes[1]) && IsFloat(i.ResultTypes[0])) { Swap(preds); Convert(i.OperandTypes[0], i.OperandTypes[1]); Swap(); var inew = i.Command.CreateStk(2, i.OperandTypes[1], i.OperandTypes[0], i.ResultTypes[0]); ProcessAddSub(inew); } else if (IsFloat(i.OperandTypes[0]) && IsFixed(i.OperandTypes[1]) && IsFloat(i.ResultTypes[0])) { Convert(preds, i.OperandTypes[1], i.OperandTypes[0]); var inew = i.Command.CreateStk(2, i.OperandTypes[0], i.OperandTypes[0], i.ResultTypes[0]); ProcessAddSub(inew); } else if (IsSLV(i.OperandTypes[1])) { var signedType = SFix.MakeType(StdLogicVector.GetLength(i.OperandTypes[1]), 0); Convert(preds, i.OperandTypes[1], signedType); var inew = i.Command.CreateStk(2, i.OperandTypes[0], signedType, i.ResultTypes[0]); ProcessAddSub(inew); } else if (IsSLV(i.OperandTypes[0])) { var signedType = SFix.MakeType(StdLogicVector.GetLength(i.OperandTypes[0]), 0); Swap(preds); Convert(i.OperandTypes[0], signedType); Swap(); var inew = i.Command.CreateStk(2, signedType, i.OperandTypes[1], i.ResultTypes[0]); ProcessAddSub(inew); } else { Emit(i.Command.CreateStk(preds, 2, i.OperandTypes[0], i.OperandTypes[1], i.ResultTypes[0])); } }
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 HandleDiv(XILSInstr i) { var preds = i.Preds; var fmtDividend = i.OperandTypes[0].GetFixFormat(); var fmtDivisor = i.OperandTypes[1].GetFixFormat(); var fmtQuotient = i.ResultTypes[0].GetFixFormat(); if (fmtDividend == null || fmtDivisor == null || fmtQuotient == null) { ProcessDefault(i); return; } if (!fmtDivisor.IsSigned) { // Xilinx divider wants it signed var signedType = SFix.MakeType(fmtDivisor.IntWidth + 1, fmtDivisor.FracWidth); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, i.OperandTypes[1], signedType)); var newi = i.Command.CreateStk(2, i.OperandTypes[0], signedType, i.ResultTypes[0]); HandleDiv(newi); return; } if (!fmtDividend.IsSigned) { // Xilinx divider wants it signed var signedType = SFix.MakeType(fmtDividend.IntWidth + 1, fmtDividend.FracWidth); Emit(DefaultInstructionSet.Instance.Swap().CreateStk(preds, 2, i.OperandTypes[0], i.OperandTypes[1], i.OperandTypes[1], i.OperandTypes[0])); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, i.OperandTypes[0], signedType)); Emit(DefaultInstructionSet.Instance.Swap().CreateStk(2, i.OperandTypes[1], signedType, signedType, i.OperandTypes[1])); var newi = i.Command.CreateStk(2, signedType, i.OperandTypes[1], i.ResultTypes[0]); HandleDiv(newi); return; } if (!fmtQuotient.IsSigned) { // Xilinx divider wants it signed var signedType = SFix.MakeType(fmtQuotient.IntWidth + 1, fmtQuotient.FracWidth); var newi = i.Command.CreateStk(preds, 2, i.OperandTypes[0], i.OperandTypes[1], signedType); HandleDiv(newi); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, signedType, i.ResultTypes[0])); return; } if (fmtDividend.TotalWidth < 4 || fmtDivisor.TotalWidth < 4) { // Xilinx fixed point divider doesn't like divisions of less than 4 bits throw new NotImplementedException("Encountered fixed point division with less than 4 bits of either dividend or divisor. This is not supported, please adjust the division!"); /*Emit(DefaultInstructionSet.Instance.Swap().CreateStk(preds, 2, * i.OperandTypes[0], i.OperandTypes[1], * i.OperandTypes[1], i.OperandTypes[0])); * int delta = 4 - fmtDividend.TotalWidth - 4; * var newDividendType = fmtDividend.IsSigned ? * SFix.MakeType( * Emit(i.Command.CreateStk(1, i.OperandTypes[1]*/ } int hwQuotientTotalWidth = fmtDividend.TotalWidth; int hwQuotientFracWidth = fmtDividend.FracWidth - fmtDivisor.FracWidth; object hwQuotSample = fmtDividend.IsSigned ? (object)SFix.FromDouble(0.0, hwQuotientTotalWidth - hwQuotientFracWidth, hwQuotientFracWidth) : (object)UFix.FromDouble(0.0, hwQuotientTotalWidth - hwQuotientFracWidth, hwQuotientFracWidth); var hwQuotType = TypeDescriptor.GetTypeOf(hwQuotSample); TypeDescriptor hwQuotAndFracType; if (hwQuotientFracWidth >= fmtQuotient.FracWidth) { Emit(i.Command.CreateStk(preds, 2, i.OperandTypes[0], i.OperandTypes[1], hwQuotType)); hwQuotAndFracType = hwQuotType; } else { int fracWidth = fmtQuotient.FracWidth - hwQuotientFracWidth; if (fracWidth > 54) { // Xilinx divider doesn't like fractional width > 54 throw new NotImplementedException("Encountered fixed point division with more than 54 bits of fractional width. This is not supported, please adjust the division!"); } var hwFracSample = UFix.FromDouble(0.0, -hwQuotientFracWidth, fmtQuotient.FracWidth); var hwFracType = TypeDescriptor.GetTypeOf(hwFracSample); Emit(DefaultInstructionSet.Instance.DivQF().CreateStk(preds, 2, i.OperandTypes[0], i.OperandTypes[1], hwQuotType, hwFracType)); var hwQuotSLV = Marshal.SerializeForHW(hwQuotSample); var hwFracSLV = Marshal.SerializeForHW(hwFracSample); var hwQuotSLVType = TypeDescriptor.GetTypeOf(hwQuotSLV); var hwFracSLVType = TypeDescriptor.GetTypeOf(hwFracSLV); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, hwFracType, hwFracSLVType)); Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(2, hwQuotType, hwFracSLVType, hwFracSLVType, hwQuotType)); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, hwQuotType, hwQuotSLVType)); Emit(DefaultInstructionSet.Instance.Dig(1).CreateStk(2, hwFracSLVType, hwQuotSLVType, hwQuotSLVType, hwFracSLVType)); var hwConcSLV = hwQuotSLV.Concat(hwFracSLV); var hwConcSLVType = TypeDescriptor.GetTypeOf(hwConcSLV); Emit(DefaultInstructionSet.Instance.Concat().CreateStk(2, hwQuotSLVType, hwFracSLVType, hwConcSLVType)); object hwConc; if (fmtDividend.IsSigned) { hwConc = SFix.FromSigned(hwConcSLV.SignedValue, fmtQuotient.FracWidth); } else { hwConc = UFix.FromUnsigned(hwConcSLV.UnsignedValue, fmtQuotient.FracWidth); } var hwConcType = TypeDescriptor.GetTypeOf(hwConc); Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, hwConcSLVType, hwConcType)); hwQuotAndFracType = hwConcType; } if (!hwQuotAndFracType.Equals(i.ResultTypes[0])) { Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, hwQuotAndFracType, i.ResultTypes[0])); } }