Esempio n. 1
0
        private void HandleSinOrCos(XILSInstr i)
        {
            FixFormat oformat, rformat;

            IsFix(i.OperandTypes[0], out oformat);
            IsFix(i.ResultTypes[0], out rformat);
            var preds = RemapPreds(i.Preds);

            if (oformat == null)
            {
                Emit(i.Command.CreateStk(preds, 1, i.OperandTypes[0], i.ResultTypes[0]));
            }
            else
            {
                TypeDescriptor otype = i.OperandTypes[0];
                if (!i.OperandTypes[0].CILType.Equals(typeof(SFix)))
                {
                    var itype = SFix.MakeType(oformat.IntWidth + 1, oformat.FracWidth);
                    Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, i.OperandTypes, i.ResultTypes));
                    preds = new InstructionDependency[0];
                    otype = itype;
                }
                var nrtype = SFix.MakeType(2, rformat.FracWidth);
                Emit(i.Command.CreateStk(preds, 1, otype, nrtype));
                if (!i.ResultTypes[0].Equals(nrtype))
                {
                    Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, nrtype, i.ResultTypes[0]));
                }
            }
        }
Esempio n. 2
0
        private void HandleScSinCos(XILSInstr i)
        {
            var preds  = RemapPreds(i.Preds);
            var infmt  = i.OperandTypes[0].GetFixFormat();
            var outfmt = i.ResultTypes[0].GetFixFormat();

            if (infmt == null)
            {
                Emit(i.Command.CreateStk(preds, i.OperandTypes, i.ResultTypes));
            }
            else
            {
                var otype = i.OperandTypes[0];
                if (HaveXilinxCordic && infmt.IntWidth != 3)
                {
                    // Xilinx Cordic needs exactly 3 integer bits for operand
                    otype = SFix.MakeType(3, infmt.FracWidth);
                    Emit(DefaultInstructionSet.Instance.Convert().CreateStk(
                             preds, 1, i.OperandTypes[0], otype));
                }
                else if (infmt.IntWidth != 2)
                {
                    // Any reasonable core (e.g. LUT-based implementation) will require 2 integer operand bits
                    otype = SFix.MakeType(2, infmt.FracWidth);
                    Emit(DefaultInstructionSet.Instance.Convert().CreateStk(
                             preds, 1, i.OperandTypes[0], otype));
                }
                preds = new InstructionDependency[0];
                var rtype = i.ResultTypes[0];
                if (outfmt.IntWidth != 2)
                {
                    // we gonna need exactly 2 integer bits for results
                    rtype = SFix.MakeType(2, outfmt.FracWidth);
                }
                Emit(DefaultInstructionSet.Instance.ScSinCos().CreateStk(
                         preds, 1, otype, rtype, rtype));
                if (!rtype.Equals(i.ResultTypes[1]))
                {
                    Emit(DefaultInstructionSet.Instance.Convert().CreateStk(
                             1, rtype, i.ResultTypes[1]));
                }
                if (!rtype.Equals(i.ResultTypes[0]))
                {
                    Emit(DefaultInstructionSet.Instance.Swap().CreateStk(
                             2, i.ResultTypes[0], rtype, rtype, i.ResultTypes[0]));
                    Emit(DefaultInstructionSet.Instance.Convert().CreateStk(
                             1, rtype, i.ResultTypes[0]));
                    Emit(DefaultInstructionSet.Instance.Swap().CreateStk(
                             2, rtype, rtype, rtype, rtype));
                }
            }
        }
Esempio n. 3
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. 4
0
        private void HandleNeg(XILSInstr i)
        {
            var preds  = RemapPreds(i.Preds);
            var nrtype = GetNativeResultType(i, i.OperandTypes);
            var otype  = i.OperandTypes[0];

            if (otype.CILType.Equals(typeof(UFix)) &&
                nrtype.CILType.Equals(typeof(SFix)))
            {
                var nrformat = nrtype.GetFixFormat();
                var itype    = SFix.MakeType(nrformat.IntWidth, nrformat.FracWidth);
                Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, otype, itype));
                preds = new InstructionDependency[0];
                otype = itype;
            }
            Emit(i.Command.CreateStk(preds, 1, otype, nrtype));
            if (!nrtype.Equals(i.ResultTypes[0]))
            {
                Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, nrtype, i.ResultTypes[0]));
            }
        }
Esempio n. 5
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. 6
0
        /// <summary>
        /// Returns a type which is able to represent either of two given types without loss of precision
        /// </summary>
        /// <param name="td1">first given type</param>
        /// <param name="td2">second given type</param>
        /// <returns></returns>
        private static TypeDescriptor GetCommonType(TypeDescriptor td1, TypeDescriptor td2)
        {
            if (td1.Equals(td2))
            {
                return(td1);
            }

            if (IsSFix(td1) && IsUFix(td2))
            {
                var fmt1 = SFix.GetFormat(td1);
                var fmt2 = UFix.GetFormat(td2);
                return(SFix.MakeType(
                           Math.Max(fmt1.IntWidth, fmt2.IntWidth + 1),
                           Math.Max(fmt1.FracWidth, fmt2.FracWidth)));
            }
            else if (IsUFix(td1) && IsSFix(td2))
            {
                return(GetCommonType(td2, td1));
            }
            else if (IsSFix(td1) && IsSFix(td2))
            {
                var fmt1 = SFix.GetFormat(td1);
                var fmt2 = SFix.GetFormat(td2);
                return(SFix.MakeType(
                           Math.Max(fmt1.IntWidth, fmt2.IntWidth),
                           Math.Max(fmt1.FracWidth, fmt2.FracWidth)));
            }
            else if (IsUFix(td1) && IsUFix(td2))
            {
                var fmt1 = UFix.GetFormat(td1);
                var fmt2 = UFix.GetFormat(td2);
                return(UFix.MakeType(
                           Math.Max(fmt1.IntWidth, fmt2.IntWidth),
                           Math.Max(fmt1.FracWidth, fmt2.FracWidth)));
            }
            else if (IsSigned(td1))
            {
                var fmt  = SFix.GetFormat(td1);
                var td1x = SFix.MakeType(fmt.IntWidth, fmt.FracWidth);
                return(GetCommonType(td1x, td2));
            }
            else if (IsSigned(td2))
            {
                return(GetCommonType(td2, td1));
            }
            else if (IsUnsigned(td1))
            {
                var fmt  = UFix.GetFormat(td1);
                var td1x = UFix.MakeType(fmt.IntWidth, fmt.FracWidth);
                return(GetCommonType(td1x, td2));
            }
            else if (IsUnsigned(td2))
            {
                return(GetCommonType(td2, td1));
            }
            else
            {
                throw new NotSupportedException(
                          "Cannot determine common type between " +
                          td1.ToString() + " and " + td2.ToString());
            }
        }
Esempio n. 7
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. 8
0
 private InstructionDependency[] Convert(InstructionDependency[] preds, TypeDescriptor from, TypeDescriptor to)
 {
     if (from.Equals(to))
     {
         // nothing to do
         return(preds);
     }
     else if (IsSFix(from) && IsUFix(to))
     {
         var fromFmt = SFix.GetFormat(from);
         var toFmt   = UFix.GetFormat(to);
         int interIW = toFmt.IntWidth + 1;
         int interFW = toFmt.FracWidth;
         if (interIW != fromFmt.IntWidth ||
             interFW != fromFmt.FracWidth)
         {
             var interType = SFix.MakeType(interIW, interFW);
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, interType));
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, interType, to));
         }
         else
         {
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to));
         }
         return(new InstructionDependency[0]);
     }
     else if (IsUFix(from) && IsSFix(to))
     {
         var fromFmt = UFix.GetFormat(from);
         var toFmt   = SFix.GetFormat(to);
         int interIW = toFmt.IntWidth - 1;
         int interFW = toFmt.FracWidth;
         if (interIW != fromFmt.IntWidth ||
             interFW != fromFmt.FracWidth)
         {
             var interType = UFix.MakeType(interIW, interFW);
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, interType));
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(1, interType, to));
         }
         else
         {
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to));
         }
         return(new InstructionDependency[0]);
     }
     else if (IsSLV(from))
     {
         int wfrom = TypeLowering.Instance.GetWireWidth(from);
         int wto   = TypeLowering.Instance.GetWireWidth(to);
         if (wfrom == wto)
         {
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to));
         }
         else
         {
             var interType = StdLogicVector.MakeType(wto);
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, interType));
             Convert(interType, to);
         }
         return(new InstructionDependency[0]);
     }
     else if (IsSLV(to))
     {
         int wfrom = TypeLowering.Instance.GetWireWidth(from);
         int wto   = TypeLowering.Instance.GetWireWidth(to);
         if (wfrom == wto)
         {
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to));
         }
         else
         {
             var interType = StdLogicVector.MakeType(wfrom);
             Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, interType));
             Convert(interType, to);
         }
         return(new InstructionDependency[0]);
     }
     else
     {
         Emit(DefaultInstructionSet.Instance.Convert().CreateStk(preds, 1, from, to));
         return(new InstructionDependency[0]);
     }
 }
Esempio n. 9
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]));
            }
        }