예제 #1
0
        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));
        }
예제 #2
0
파일: LERP.cs 프로젝트: cephdon/systemsharp
        /// <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;
            });
        }
예제 #3
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();
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
 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);
     }
 }
예제 #6
0
파일: LERP.cs 프로젝트: cephdon/systemsharp
        /// <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);
        }
예제 #7
0
 public void TestOverflow2()
 {
     FixedPointSettings.GlobalOverflowMode = EOverflowMode.Fail;
     Assert.AreEqual(EOverflowMode.Fail, FixedPointSettings.GlobalOverflowMode);
     UFix.FromDouble(-2.5, 1, 0);
 }
예제 #8
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.");
 }
예제 #9
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();
            }
        }
예제 #10
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]));
            }
        }
예제 #11
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);
        }
예제 #12
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]));
            }
        }