public static UFix Sqrt(UFix value) { int iw = (value.Format.IntWidth + 1) / 2; return(UFix.FromDouble( Math.Sqrt(value.DoubleValue), iw, value.Format.TotalWidth - iw)); }
/// <summary> /// Constructs a new instance. /// </summary> /// <param name="xIntWidth">integer bits of operand</param> /// <param name="xFracWidth">fractional bits of operand</param> /// <param name="yIntWidth">integer bits of result</param> /// <param name="yFracWidth">fractional bits of result</param> /// <param name="pipeStages">desired computation-only latency</param> /// <param name="data">data table</param> public LERP11Core(int xIntWidth, int xFracWidth, int yIntWidth, int yFracWidth, int pipeStages, SFix[] data) { Contract.Requires <ArgumentOutOfRangeException>(xIntWidth > 0, "xIntWidth must be positive."); Contract.Requires <ArgumentOutOfRangeException>(xFracWidth >= 0, "xFracWidth must be non-negative."); Contract.Requires <ArgumentOutOfRangeException>(yIntWidth + yFracWidth > 0, "total bit-width of result must be positive"); Contract.Requires <ArgumentOutOfRangeException>(pipeStages >= 0, "pipeStages must be non-negative."); Contract.Requires <ArgumentOutOfRangeException>(xFracWidth > 0 || pipeStages == 0, "xFracWidth == 0 is a degenerate case (lookup-only). No additional pipeline stages allowed."); Contract.Requires <ArgumentNullException>(data != null, "data"); PipeStages = pipeStages; XIntWidth = xIntWidth; XFracWidth = xFracWidth; YIntWidth = yIntWidth; YFracWidth = yFracWidth; DIntWidth = data[0].Format.IntWidth; DFracWidth = data[0].Format.FracWidth; _x = new Signal <UFix>() { InitialValue = UFix.FromDouble(0.0, xIntWidth, xFracWidth) }; _y = new Signal <SFix>() { InitialValue = SFix.FromDouble(0.0, yIntWidth, yFracWidth) }; AddrWidth = MathExt.CeilPow2(data.Length); _unitAddr = new Signal <Unsigned>() { InitialValue = Unsigned.FromUInt(0, AddrWidth) }; _memContent = new VSignal <SFix>(data.Length, _ => new Signal <SFix>() { InitialValue = data[_] }); _lerpUnit = new LERPUnit(xIntWidth, xFracWidth, yIntWidth, yFracWidth, pipeStages); Bind(() => { _lerpUnit.Clk = Clk; _lerpUnit.X = _x; _lerpUnit.Y = _y; _lerpUnit.Addr = _unitAddr; _lerpUnit.Data = _unitData; }); }
/// <summary> /// Converts <paramref name="src"/> to <paramref name="dstType"/> datatype, possibly with loss of precision or overflow. /// </summary> /// <remarks>Currently, conversions between all primitive numeric CIL types, enum types, and System#-intrinsic datatypes /// Signed, Unsigned, SFix, UFix and StdLogicVector are supported.</remarks> /// <exception cref="ArgumentNullException">if <paramref name="dstType"/> is null</exception> /// <exception cref="NotImplementedException">if there is no known conversion to <paramref name="dstType"/></exception> public static object ConvertDouble(double src, TypeDescriptor dstType) { Contract.Requires <ArgumentNullException>(dstType != null, "dstType"); if (dstType.CILType.Equals(typeof(SFix))) { var fmt = SFix.GetFormat(dstType); return(SFix.FromDouble(src, fmt.IntWidth, fmt.FracWidth)); } else if (dstType.CILType.Equals(typeof(UFix))) { var fmt = UFix.GetFormat(dstType); return(UFix.FromDouble(src, fmt.IntWidth, fmt.FracWidth)); } else { throw new NotImplementedException(); } }
public void TestBasicMath() { FixedPointSettings.GlobalArithSizingMode = EArithSizingMode.Safe; Assert.AreEqual(EArithSizingMode.Safe, FixedPointSettings.GlobalArithSizingMode); var v1 = UFix.FromDouble(1.5, 2, 1); var v2 = UFix.FromDouble(2.5, 3, 1); var v3 = UFix.FromDouble(12.5, 5, 1); Assert.AreEqual(4.0, (v1 + v2).DoubleValue); Assert.AreEqual(1.0, (v2 - v1).DoubleValue); Assert.AreEqual(3.75, (v1 * v2).DoubleValue); Assert.AreEqual(0.6, (v1 / v2).DoubleValue, 0.05); Assert.AreEqual(1.5, (v1 % v2).DoubleValue); Assert.AreEqual(1.0, (v2 % v1).DoubleValue); Assert.AreEqual(0.0, (v3 % v2).DoubleValue); Assert.AreEqual(2.5, (v2 % v3).DoubleValue); Assert.AreEqual(0.5, (v3 % v1).DoubleValue); Assert.AreEqual(1.5, (v1 % v3).DoubleValue); }
private async void StimulateAndTest() { for (double i = 0.01; i < 100.0; i *= 2.0) { _x1.Next = UFix.FromDouble(i, 8, 8).SLVValue; _x2.Next = UFix.FromDouble(i, 9, 8).SLVValue; while (_rdy.Cur != '0') { await _rdy; } while (_rdy.Cur != '1') { await _rdy; } var x1 = UFix.FromUnsigned(_x1.Cur.UnsignedValue, 8); var sqrt1 = UFix.FromUnsigned(_sqrt1.Cur.UnsignedValue, 12); Console.WriteLine("X1 = " + x1.DoubleValue + ", Sqrt = " + sqrt1.DoubleValue + ", Sqrt^2 = " + (sqrt1 * sqrt1).DoubleValue); var x2 = UFix.FromUnsigned(_x2.Cur.UnsignedValue, 8); var sqrt2 = UFix.FromUnsigned(_sqrt2.Cur.UnsignedValue, 12); Console.WriteLine("X2 = " + x1.DoubleValue + ", Sqrt = " + sqrt2.DoubleValue + ", Sqrt^2 = " + (sqrt2 * sqrt2).DoubleValue); } }
/// <summary> /// Constructs a new instance /// </summary> /// <param name="lutWidth">resolution of data table</param> /// <param name="xFracWidth">fractional width of operand</param> /// <param name="yFracWidth">fractional width of result</param> /// <param name="pipeStages">additional pipeline stages for interpolation computation</param> public SinCosLUTCore(int lutWidth, int xFracWidth, int yFracWidth, int pipeStages) { PipeStages = pipeStages; XIntWidth = 2; XFracWidth = xFracWidth; YIntWidth = 2; YFracWidth = yFracWidth; DIntWidth = 2; DFracWidth = yFracWidth; LUTWidth = lutWidth; _x = new Signal <UFix>() { InitialValue = UFix.FromDouble(0.0, LUTWidth + 1, XFracWidth - LUTWidth - 1) }; _xq = new Signal <UFix>() { InitialValue = UFix.FromDouble(0.0, LUTWidth + 1, XFracWidth - LUTWidth - 1) }; _sinRaw = new Signal <SFix>() { InitialValue = SFix.FromDouble(0.0, YIntWidth, YFracWidth) }; _cosRaw = new Signal <SFix>() { InitialValue = SFix.FromDouble(0.0, YIntWidth, YFracWidth) }; _sinIn = new SLVSignal(YIntWidth + YFracWidth) { InitialValue = SFix.FromDouble(0.0, YIntWidth, YFracWidth).SLVValue }; _cosIn = new SLVSignal(YIntWidth + YFracWidth) { InitialValue = SFix.FromDouble(0.0, YIntWidth, YFracWidth).SLVValue }; _sinOut = new SLVSignal(YIntWidth + YFracWidth) { InitialValue = SFix.FromDouble(0.0, YIntWidth, YFracWidth).SLVValue }; _cosOut = new SLVSignal(YIntWidth + YFracWidth) { InitialValue = SFix.FromDouble(0.0, YIntWidth, YFracWidth).SLVValue }; AddrWidth = lutWidth + 1; _sinAddr = new Signal <Unsigned>() { InitialValue = Unsigned.FromUInt(0, AddrWidth) }; _cosAddr = new Signal <Unsigned>() { InitialValue = Unsigned.FromUInt(0, AddrWidth) }; _sinData = new Signal <SFix>() { InitialValue = SFix.FromDouble(0.0, YIntWidth, YFracWidth) }; _cosData = new Signal <SFix>() { InitialValue = SFix.FromDouble(0.0, YIntWidth, YFracWidth) }; _sinLUT = new VSignal <SFix>((1 << lutWidth) + 2, _ => new Signal <SFix>() { InitialValue = SFix.FromDouble(Math.Sin(Math.PI * 0.5 * _ / (double)(1 << lutWidth)), 2, yFracWidth) }); _sinFlipSignIn = new SLVSignal(1) { InitialValue = "0" }; _cosFlipSignIn = new SLVSignal(1) { InitialValue = "0" }; _sinFlipSignOut = new SLVSignal(1) { InitialValue = "0" }; _cosFlipSignOut = new SLVSignal(1) { InitialValue = "0" }; _mirror = UFix.FromUnsigned(Unsigned.One.Resize(XFracWidth + 2) << (xFracWidth + 1), xFracWidth - LUTWidth); _mirror2 = UFix.FromUnsigned(Unsigned.One.Resize(XFracWidth + 2) << xFracWidth, xFracWidth - LUTWidth); _sinPipe = new RegPipe(pipeStages, YIntWidth + YFracWidth); Bind(() => { _sinPipe.Clk = Clk; _sinPipe.Din = _sinIn; _sinPipe.Dout = _sinOut; }); _cosPipe = new RegPipe(pipeStages, YIntWidth + YFracWidth); Bind(() => { _cosPipe.Clk = Clk; _cosPipe.Din = _cosIn; _cosPipe.Dout = _cosOut; }); _sinFlipSignPipe = new RegPipe(2, 1); Bind(() => { _sinFlipSignPipe.Clk = Clk; _sinFlipSignPipe.Din = _sinFlipSignIn; _sinFlipSignPipe.Dout = _sinFlipSignOut; }); _cosFlipSignPipe = new RegPipe(2, 1); Bind(() => { _cosFlipSignPipe.Clk = Clk; _cosFlipSignPipe.Din = _cosFlipSignIn; _cosFlipSignPipe.Dout = _cosFlipSignOut; }); _sinUnit = new LERPUnit(lutWidth + 1, xFracWidth - 1 - lutWidth, YIntWidth, yFracWidth, 0); Bind(() => { _sinUnit.Clk = Clk; _sinUnit.X = _x; _sinUnit.Y = _sinRaw; _sinUnit.Addr = _sinAddr; _sinUnit.Data = _sinData; }); _cosUnit = new LERPUnit(lutWidth + 1, xFracWidth - 1 - lutWidth, YIntWidth, yFracWidth, 0); Bind(() => { _cosUnit.Clk = Clk; _cosUnit.X = _xq; _cosUnit.Y = _cosRaw; _cosUnit.Addr = _cosAddr; _cosUnit.Data = _cosData; }); TASite = new TransactionSite(this); }
public void TestOverflow2() { FixedPointSettings.GlobalOverflowMode = EOverflowMode.Fail; Assert.AreEqual(EOverflowMode.Fail, FixedPointSettings.GlobalOverflowMode); UFix.FromDouble(-2.5, 1, 0); }
public void TestFromToDouble() { Assert.AreEqual(0.0, UFix.FromDouble(0.0, 1, 1).DoubleValue, "conversion from/to 0 failed."); Assert.AreEqual(1.0, UFix.FromDouble(1.0, 1, 0).DoubleValue, "conversion from/to 1 failed."); Assert.AreEqual(1.0, UFix.FromDouble(1.5, 2, 0).DoubleValue, "conversion from/to 1 failed."); }
/// <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(); } }
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[] 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 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])); } }