Esempio n. 1
0
        private async void TestProcess()
        {
            _nxt = false;

            await Tick;

            double a = 100.0;
            double b = 1.0;

            while (true)
            {
                //ProgramFlow.DoNotUnroll();

                _dividend = SFix.FromDouble(a, iw, fw);
                _divisor  = SFix.FromDouble(b, iw, fw);
                _nxt      = true;
                while (_rdy)
                {
                    //ProgramFlow.DoNotUnroll();
                    await Tick;
                }
                _nxt = false;
                while (!_rdy)
                {
                    //ProgramFlow.DoNotUnroll();
                    await Tick;
                }

                Console.WriteLine(_dividend.DoubleValue + " / " + _divisor.DoubleValue + " = " + _quotient.DoubleValue);
                b = b + 1.0;
            }
        }
Esempio n. 2
0
        private static TypeDescriptor MakeUFixSFix(TypeDescriptor t)
        {
            var fmt = UFix.GetFormat(t);
            var smp = SFix.FromDouble(0.0, fmt.IntWidth + 1, fmt.FracWidth);

            return(TypeDescriptor.GetTypeOf(smp));
        }
Esempio n. 3
0
        //********************************************************************************************************************
        //*******************Hier wird die angegebene Dezimalzahl im Binaere umgewandelt**************************************
        //int intw;
        private StdLogicVector Getbinaer(double x)
        {
            StdLogicVector v = SFix.FromDouble(x, 2, OutputWidth - 2).SignedValue.SLVValue;

            //double y = SFix.FromSigned(v.SignedValue, 10).DoubleValue;
            return(v);
        }
Esempio n. 4
0
        public IEnumerable <IXILMapping> TryMap(ITransactionSite taSite, XILInstr instr, TypeDescriptor[] operandTypes, TypeDescriptor[] resultTypes)
        {
            var fu  = taSite.Host;
            var scc = fu as SinCosLUTCore;

            if (scc == null)
            {
                yield break;
            }

            if (operandTypes.Length != 1 || resultTypes.Length != 2)
            {
                yield break;
            }

            var xType = TypeDescriptor.GetTypeOf(SFix.FromDouble(0.0, scc.XIntWidth, scc.XFracWidth));
            var yType = TypeDescriptor.GetTypeOf(SFix.FromDouble(0.0, scc.YIntWidth, scc.YFracWidth));

            if (!operandTypes[0].Equals(xType) ||
                !resultTypes[0].Equals(yType) ||
                !resultTypes[1].Equals(yType))
            {
                yield break;
            }

            if (instr.Name != InstructionCodes.ScSinCos)
            {
                yield break;
            }

            yield return(new Mapping(scc));
        }
Esempio n. 5
0
 public void TestFromToDouble()
 {
     Assert.AreEqual(0.0, SFix.FromDouble(0.0, 1, 1).DoubleValue, "conversion from/to 0 failed.");
     Assert.AreEqual(1.0, SFix.FromDouble(1.0, 2, 0).DoubleValue, "conversion from/to 1 failed.");
     Assert.AreEqual(-1.0, SFix.FromDouble(-1.0, 2, 0).DoubleValue, "conversion from/to -1 failed.");
     Assert.AreEqual(1.0, SFix.FromDouble(1.5, 3, 0).DoubleValue, "conversion from/to 1 failed.");
     Assert.AreEqual(-1.5, SFix.FromDouble(-1.5, 2, 1).DoubleValue, "conversion from/to 1.6 failed.");
 }
Esempio n. 6
0
        public static SFix Cos(SFix value)
        {
            Contract.Requires <ArgumentOutOfRangeException>(value.Format.FracWidth >= 0, "value.Format.FracWidth");

            return(SFix.FromDouble(
                       Math.Sin(value.DoubleValue),
                       2,
                       value.Format.FracWidth));
        }
Esempio n. 7
0
        public static SFix Cos(SFix value, int fracWidth)
        {
            Contract.Requires <ArgumentOutOfRangeException>(fracWidth >= 0, "fracWidth");

            return(SFix.FromDouble(
                       Math.Cos(value.DoubleValue),
                       2,
                       fracWidth));
        }
Esempio n. 8
0
            private async void Processing()
            {
                await Tick;
                var   aux = SFix.FromDouble(0.5, 1, 1);
                SFix  aux1;

                Ctr.Next  = _ctr.Cur;
                aux1      = _ctr.Cur + aux;
                _ctr.Next = aux1.Resize(7, 1);
            }
Esempio n. 9
0
        /// <summary>
        /// Constructs a new instance.
        /// </summary>
        /// <param name="floatWidth">total bit-width of input floating-point number
        /// (actual partitioning between exponent and mantissa bits does not matter)</param>
        /// <param name="outFormat">desired fixed-point output format</param>
        public FloatSignAsSigned(int floatWidth, FixFormat outFormat)
        {
            FloatWidth = floatWidth;
            OutFormat  = outFormat;

            _outM1 = SFix.FromDouble(-1.0, outFormat.IntWidth, outFormat.FracWidth).SLVValue;
            _out0  = SFix.FromDouble(0.0, outFormat.IntWidth, outFormat.FracWidth).SLVValue;
            _out1  = SFix.FromDouble(1.0, outFormat.IntWidth, outFormat.FracWidth).SLVValue;
            _zeros = StdLogicVector._0s(floatWidth - 1);

            TASite = new TransactionSite(this);
        }
Esempio n. 10
0
        private async void StimulateAndTest()
        {
            DesignContext.Instance.FixPoint.DefaultRadix = 10;

            for (double i = -1.0; i <= 1.0; i += 0.0625)
            {
                var x = SFix.FromDouble(i, 2, _xFracWidth);
                _x.Next = x.SLVValue;
                //DesignContext.Wait(_pipeStages + 4);
                await NTicks(_pipeStages + 3);

                Console.WriteLine("X = " + x +
                                  ", Sin = " + SFix.FromSigned(_sin.Cur.SignedValue, _yFracWidth) +
                                  ", Cos = " + SFix.FromSigned(_cos.Cur.SignedValue, _yFracWidth));
            }
        }
Esempio n. 11
0
        public static void RunTest()
        {
            DesignContext.Reset();
            FixedPointSettings.GlobalArithSizingMode = EArithSizingMode.VHDLCompliant;

            var a = SFix.FromDouble(1.0, 8, 10);
            var b = SFix.FromDouble(2.0, 8, 10);
            var c = SFix.FromDouble(3.0, 8, 10);
            var d = SFix.FromDouble(4.0, 8, 10);

            TestAddMul2 dut = new TestAddMul2()
            {
                Clk = new SLSignal(),
                A   = new Signal <SFix>()
                {
                    InitialValue = a
                },
                B = new Signal <SFix>()
                {
                    InitialValue = b
                },
                C = new Signal <SFix>()
                {
                    InitialValue = c
                },
                D = new Signal <SFix>()
                {
                    InitialValue = d
                },
                R = new Signal <SFix>()
                {
                    InitialValue = a * b + c * d
                }
            };

            DesignContext.Instance.Elaborate();
            XilinxIntegration.RegisterIPCores(DesignContext.Instance.Descriptor);
            DesignContext.Instance.CompleteAnalysis();

            XC6VLX240T_FF1156 fpga = new XC6VLX240T_FF1156()
            {
                SpeedGrade        = ESpeedGrade._2,
                TopLevelComponent = dut
            };

            fpga.Synthesize(@".\hdl_out_TestAddMul2", "TestAddMul2");
        }
Esempio n. 12
0
        /// <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;
            });
        }
Esempio n. 13
0
        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)
                });
            }
        }
Esempio n. 14
0
        public static Tuple <SFix, SFix> ScSinCos(SFix value, int resultFracBits)
        {
            Contract.Requires <ArgumentOutOfRangeException>(value.DoubleValue >= -1.0, "value");
            Contract.Requires <ArgumentOutOfRangeException>(value.DoubleValue <= 1.0, "value");
            Contract.Requires <ArgumentOutOfRangeException>(resultFracBits >= 0, "resultFracBits");

            var result = Tuple.Create(
                SFix.FromDouble(
                    Math.Cos(Math.PI * value.DoubleValue),
                    2,
                    resultFracBits),
                SFix.FromDouble(
                    Math.Sin(Math.PI * value.DoubleValue),
                    2,
                    resultFracBits));

            return(result);
        }
Esempio n. 15
0
        /// <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();
            }
        }
Esempio n. 16
0
        public void TestBasicMath()
        {
            FixedPointSettings.GlobalArithSizingMode = EArithSizingMode.Safe;
            Assert.AreEqual(EArithSizingMode.Safe, FixedPointSettings.GlobalArithSizingMode);

            var v1 = SFix.FromDouble(1.5, 2, 1);
            var v2 = SFix.FromDouble(-2.5, 3, 1);
            var v3 = SFix.FromDouble(-12.5, 5, 1);

            Assert.AreEqual(-1.0, (v1 + v2).DoubleValue);
            Assert.AreEqual(4.0, (v1 - v2).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);
        }
Esempio n. 17
0
        private async void StimProcess()
        {
            DesignContext.Instance.FixPoint.DefaultRadix = 10;
            await Tick;

            double cur = 2.1;

            while (true)
            {
                var inval = SFix.FromDouble(cur, _mod2.InIntWidth, _mod2.FracWidth);
                _x.Next = inval.SLVValue;
                await Tick;
                var   outval = SFix.FromSigned(_r.Cur.SignedValue, _mod2.FracWidth);
                var   outd   = outval.DoubleValue;
                var   refd   = Math.IEEERemainder(cur, 2.0);
                Debug.Assert(outd >= -1.0 && outd <= 1.0);
                Console.WriteLine(cur + " mod 2 == " + outd);
                cur -= 0.1;
            }
        }
Esempio n. 18
0
        private async void StimulateAndTest()
        {
            DesignContext.Instance.FixPoint.DefaultRadix = 10;

            for (double i = -1.0; i < 1.0; i += 0.0625)
            {
                var x = SFix.FromDouble(i, 2, _xFracWidth);
                _x.Next = x.SLVValue;
                while (_rdy.Cur != '0')
                {
                    await Tick;
                }
                while (_rdy.Cur != '1')
                {
                    await Tick;
                }
                Console.WriteLine("X = " + x +
                                  ", Sin = " + SFix.FromSigned(_sin.Cur.SignedValue, _yFracWidth) +
                                  ", Cos = " + SFix.FromSigned(_cos.Cur.SignedValue, _yFracWidth));
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Returns an expansion pattern which replaces sin(x) by scsin(y). y=(1/PI)*x is converted from double to fixed point,
        /// the result is converted back to double.
        /// Useful if target platform implements sin/cos on fixed-point, scaled-radian basis only.
        /// </summary>
        /// <param name="convIntWidth">desired fixed-point conversion integer width</param>
        /// <param name="convFracWidth">desired fixed-point conversion fractional width</param>
        public static ExpansionPattern Rewrite_Sin_double(int convIntWidth, int convFracWidth)
        {
            TypeDescriptor tmpSFixT = TypeDescriptor.GetTypeOf(
                SFix.FromDouble(0.0, convIntWidth, convFracWidth));
            TypeDescriptor scaSFixT = TypeDescriptor.GetTypeOf(
                SFix.FromDouble(0.0, 3, convFracWidth));
            TypeDescriptor scaSFixT2 = TypeDescriptor.GetTypeOf(
                SFix.FromDouble(0.0, 2, convFracWidth));
            DefaultInstructionSet iset = DefaultInstructionSet.Instance;

            return(new DefaultExpansionPattern(
                       iset.Sin().CreateStk(1, typeof(double), typeof(double)),
                       new XILSInstr[] {
                iset.LdConst(1.0 / Math.PI).CreateStk(0, typeof(double)),
                iset.Mul().CreateStk(2, typeof(double), typeof(double), typeof(double)),
                iset.Convert().CreateStk(1, typeof(double), tmpSFixT),
                iset.Convert().CreateStk(1, tmpSFixT, scaSFixT),
                iset.ScSin().CreateStk(1, scaSFixT, scaSFixT2),
                iset.Convert().CreateStk(1, scaSFixT2, typeof(double))
            }));
        }
Esempio n. 20
0
        /// <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);
        }
Esempio n. 21
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);
        }
Esempio n. 22
0
 public void TestOverflow2()
 {
     FixedPointSettings.GlobalOverflowMode = EOverflowMode.Fail;
     Assert.AreEqual(EOverflowMode.Fail, FixedPointSettings.GlobalOverflowMode);
     SFix.FromDouble(-2.5, 1, 0);
 }
Esempio n. 23
0
        public static void RunTest()
        {
            FixedPointSettings.GlobalDefaultRadix = 10;
            FixedPointSettings.GlobalOverflowMode = EOverflowMode.Fail;

            SFix s1 = SFix.FromDouble(1.0, 2, 2);
            SFix s2 = SFix.FromDouble(-0.75, 2, 2);
            SFix s3 = s1 / s2;

            Random rnd = new Random();
            int    n   = 10;
            int    iw  = 14;
            int    fw  = 14;
            double eps = Math.Pow(2.0, -fw);

            SFix[,] A    = new SFix[n, n];
            double[,] Ad = new double[n, n];
            SFix[]   b  = new SFix[n];
            double[] bd = new double[n];
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    double a = 2.0 * rnd.NextDouble() - 1.0;
                    Ad[i, j] = a;
                }
            }
            //Ad = new double[,] { { 4, -2, 1 }, { -3, -1, 4 }, { 1, -1, 3 } };
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    double a  = Ad[i, j];
                    SFix   c  = SFix.FromDouble(a, iw, fw);
                    string cs = c.ToString();
                    double ar = c.DoubleValue;
                    double d  = a - ar;
                    double da = Math.Abs(d);
                    Debug.Assert(da < eps);
                    A[i, j]  = c;
                    Ad[i, j] = a;
                }
                double bi = 2.0 * rnd.NextDouble() - 1.0;
                b[i]  = SFix.FromDouble(bi, 3, 33);
                bd[i] = bi;
            }
            SFix[,] Ac = (SFix[, ])A.Clone();
            Console.WriteLine("Original matrix:");
            PrintMatrix(A);
            Console.WriteLine();
            ComputeLU(A, iw, fw);
            Console.WriteLine("LU:");
            PrintMatrix(A);
            Console.WriteLine();

            SFix[] x = new SFix[n];
            SFix[] y = new SFix[n];
            SubstituteLU(A, b, y, x);

            Console.WriteLine("Precisions:");
            for (int i = 0; i < n; i++)
            {
                SFix bc = Ac[i, 0] * x[0];
                for (int j = 1; j < n; j++)
                {
                    bc += Ac[i, j] * x[j];
                }
                SFix d = bc - b[i];
                Console.Write("b[" + i + "] = " + b[i].ToString(10, 2));
                Console.Write(" / " + bc.ToString(10, 2));
                Console.WriteLine(" / d = " + d.ToString(10, 2));
            }
        }
Esempio n. 24
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();
            }
        }
Esempio n. 25
0
        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]));
            }
        }
Esempio n. 26
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]));
            }
        }