private void ArgsProcess() { UFix x, xd, xq; _sinFlipSignIn.Next = "0"; _cosFlipSignIn.Next = "0"; if (X.Cur[XFracWidth + 1] == '1') { // x is negative x = (-SFix.FromSigned(X.Cur.SignedValue, XFracWidth - LUTWidth - 1)).UFixValue.Resize(LUTWidth + 2, XFracWidth - LUTWidth - 1); _sinFlipSignIn.Next = "1"; } else { // x is non-negative x = UFix.FromUnsigned(X.Cur[XFracWidth, 0].UnsignedValue, XFracWidth - LUTWidth - 1); } if (x.SLVValue[XFracWidth] == '1' || x.SLVValue[XFracWidth - 1] == '1') { // between Pi/2 and Pi xd = (_mirror - x).Resize(LUTWidth + 1, XFracWidth).Resize(LUTWidth + 1, XFracWidth - LUTWidth - 1); xq = (x - _mirror2).Resize(LUTWidth + 1, XFracWidth).Resize(LUTWidth + 1, XFracWidth - LUTWidth - 1); _cosFlipSignIn.Next = "1"; } else { xd = x.Resize(LUTWidth + 1, XFracWidth - LUTWidth - 1); xq = (_mirror2 - x).Resize(LUTWidth + 1, XFracWidth).Resize(LUTWidth + 1, XFracWidth - LUTWidth - 1); } _x.Next = xd; _xq.Next = xq; }
/// <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 and enum types 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 ConvertUnsigned(Unsigned src, Type dstType) { Contract.Requires <ArgumentNullException>(dstType != null, "dstType"); if (dstType.Equals(typeof(double))) { return(UFix.FromUnsigned(src, 0).DoubleValue); } else { return(ConvertValue(src.ULongValue, dstType)); } }
private async void LERPProcess() { await Tick; while (true) { Addr.Next = X.Cur.GetIntPart().Resize(AddrWidth); SFix alpha = UFix.FromUnsigned(X.Cur.GetFracPart(), XFracWidth).SFixValue; await Tick; SFix v0 = Data.Cur; Addr.Next = (X.Cur.GetIntPart() + Unsigned.One).Resize(AddrWidth); await Tick; SFix v1 = Data.Cur; _yIn.Next = (v0 + alpha * (v1 - v0)).Resize(YIntWidth, YFracWidth).SLVValue; await PipeStages.Ticks(); } }
/// <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 ConvertUnsigned(Unsigned src, TypeDescriptor dstType) { Contract.Requires <ArgumentNullException>(dstType != null, "dstType"); if (dstType.CILType.Equals(typeof(Unsigned))) { return(src.Resize(UFix.GetFormat(dstType).IntWidth)); } else if (dstType.CILType.Equals(typeof(UFix))) { return(UFix.FromUnsigned(src.Resize(UFix.GetFormat(dstType).TotalWidth), UFix.GetFormat(dstType).FracWidth)); } else { return(ConvertUnsigned(src, dstType.CILType)); } }
private async void Computation() { await Tick; while (true) { ProgramFlow.DoNotUnroll(); ProgramFlow.IOBarrier(); Rdy.Next = '0'; Sqrt1.Next = MathExt.Sqrt(UFix.FromUnsigned(X1.Cur.UnsignedValue, _fracWidth)).SLVValue; Sqrt2.Next = MathExt.Sqrt(UFix.FromUnsigned(X2.Cur.UnsignedValue, _fracWidth)).SLVValue; await NTicks(63); ProgramFlow.IOBarrier(); Rdy.Next = '1'; ProgramFlow.IOBarrier(); await Tick; } }
/// <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 ConvertULong(ulong src, TypeDescriptor dstType) { Contract.Requires <ArgumentNullException>(dstType != null, "dstType"); if (dstType.CILType.Equals(typeof(Unsigned))) { return(Unsigned.FromULong(src, UFix.GetFormat(dstType).IntWidth)); } else if (dstType.CILType.Equals(typeof(Signed))) { return(Signed.FromBigInt(new System.Numerics.BigInteger(src), UFix.GetFormat(dstType).IntWidth)); } else if (dstType.CILType.Equals(typeof(UFix))) { return(UFix.FromUnsigned(Unsigned.FromULong(src, UFix.GetFormat(dstType).IntWidth), UFix.GetFormat(dstType).FracWidth)); } else { return(ConvertULong(src, dstType.CILType)); } }
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 static UFix Abs(SFix value) { return(UFix.FromUnsigned( Abs(value.SignedValue), value.Format.FracWidth)); }
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])); } }