Пример #1
0
        private IXILMapping TryMapOne(ITransactionSite taSite, XILInstr instr, TypeDescriptor[] operandTypes, TypeDescriptor[] resultTypes, bool swap)
        {
            var fu = taSite.Host;
            ALU alu = fu as ALU;
            if (alu == null)
                return null;
            if (resultTypes.Length != 1)
                return null;
            TypeDescriptor rtype = resultTypes[0];
            if (!rtype.IsComplete)
                return null;

            if (!CheckFixCompliance(instr, operandTypes, resultTypes))
                return null;

            int rsize = TypeLowering.Instance.GetWireWidth(rtype);
            int[] osizes = operandTypes.Select(t => TypeLowering.Instance.GetWireWidth(t)).ToArray();
            Func<ISignalSource<StdLogicVector>[], ISignalSink<StdLogicVector>[], IEnumerable<TAVerb>> realize;
            if (operandTypes.Length == 1)
            {
                realize = (os, rs) => alu.Transactor.Do(os[0], rs[0]);

                TypeDescriptor otype = operandTypes[0];
                long osize = osizes[0];
                switch (instr.Name)
                {
                    case InstructionCodes.Neg:
                        if (alu.FuncSel != ALU.EFunction.Neg)
                            return null;
                        if ((!otype.CILType.Equals(typeof(Signed)) ||
                            !rtype.CILType.Equals(typeof(Signed))) &&
                            (!otype.CILType.Equals(typeof(SFix)) ||
                            !rtype.CILType.Equals(typeof(SFix))))
                            return null;
                        if (alu.AWidth != osize ||
                            alu.RWidth != rsize)
                            return null;
                        break;

                    case InstructionCodes.Not:
                        if (alu.FuncSel != ALU.EFunction.Not)
                            return null;
                        if (!otype.CILType.Equals(typeof(StdLogicVector)) ||
                            !rtype.CILType.Equals(typeof(StdLogicVector)))
                            return null;
                        if (alu.AWidth != osize ||
                            alu.RWidth != osize)
                            return null;
                        break;

                    default:
                        return null;
                }
            }
            else
            {
                realize = (os, rs) => alu.Transactor.Do(os[0], os[1], rs[0]);

                TypeDescriptor otype0 = operandTypes[0];
                TypeDescriptor otype1 = operandTypes[1];
                long osize0 = osizes[0];
                long osize1 = osizes[1];
                if (alu.AWidth != osize0 ||
                    alu.BWidth != osize1 ||
                    (alu.FuncSel != ALU.EFunction.Compare && alu.RWidth != rsize))
                    return null;
                bool isArith = false;
                switch (instr.Name)
                {
                    case InstructionCodes.Add:
                    case InstructionCodes.Sub:
                    case InstructionCodes.Mul:
                        isArith = true;
                        goto case InstructionCodes.IsLt;

                    case InstructionCodes.IsLt:
                    case InstructionCodes.IsLte:
                    case InstructionCodes.IsEq:
                    case InstructionCodes.IsNEq:
                    case InstructionCodes.IsGte:
                    case InstructionCodes.IsGt:
                        switch (alu.ArithMode)
                        {
                            case ALU.EArithMode.Signed:
                                if ((!otype0.CILType.Equals(typeof(Signed)) ||
                                    !otype1.CILType.Equals(typeof(Signed)) ||
                                    (isArith && !rtype.CILType.Equals(typeof(Signed))) ||
                                    (!isArith && !rtype.CILType.Equals(typeof(bool)) &&
                                    !rtype.CILType.Equals(typeof(StdLogicVector)))) &&

                                    (!otype0.CILType.Equals(typeof(SFix)) ||
                                    !otype1.CILType.Equals(typeof(SFix)) ||
                                    (isArith && !rtype.CILType.Equals(typeof(SFix))) ||
                                    (!isArith && !rtype.CILType.Equals(typeof(bool)) &&
                                    !rtype.CILType.Equals(typeof(StdLogicVector)))))
                                    return null;
                                break;

                            case ALU.EArithMode.Unsigned:
                                if ((!(otype0.CILType.Equals(typeof(Unsigned)) || otype0.CILType.Equals(typeof(StdLogicVector))) ||
                                    !(otype1.CILType.Equals(typeof(Unsigned)) || otype1.CILType.Equals(typeof(StdLogicVector))) ||
                                    (isArith && !(rtype.CILType.Equals(typeof(Unsigned)) || rtype.CILType.Equals(typeof(StdLogicVector)))) ||
                                    (!isArith && !rtype.CILType.Equals(typeof(bool)) &&
                                    !rtype.CILType.Equals(typeof(StdLogicVector)))) &&

                                    (!(otype0.CILType.Equals(typeof(UFix)) || otype0.CILType.Equals(typeof(StdLogicVector)) || otype0.CILType.Equals(typeof(StdLogic))) ||
                                    !(otype1.CILType.Equals(typeof(UFix)) || otype1.CILType.Equals(typeof(StdLogicVector)) || otype1.CILType.Equals(typeof(StdLogic))) ||
                                    (isArith && !rtype.CILType.Equals(typeof(UFix))) ||
                                    (!isArith && !rtype.CILType.Equals(typeof(bool)) &&
                                    !rtype.CILType.Equals(typeof(StdLogicVector)))))
                                    return null;
                                break;

                            default:
                                throw new NotImplementedException();
                        }
                        switch (alu.FuncSel)
                        {
                            case ALU.EFunction.Add:
                                if (!instr.Name.Equals(InstructionCodes.Add))
                                    return null;
                                break;

                            case ALU.EFunction.Sub:
                                if (!instr.Name.Equals(InstructionCodes.Sub))
                                    return null;
                                break;

                            case ALU.EFunction.Mul:
                                if (!instr.Name.Equals(InstructionCodes.Mul))
                                    return null;
                                break;

                            case ALU.EFunction.Compare:
                                switch (instr.Name)
                                {
                                    case InstructionCodes.IsLt:
                                        realize = (os, rs) => alu.Transactor.IsLt(os[0], os[1], rs[0]);
                                        break;
                                    case InstructionCodes.IsLte:
                                        realize = (os, rs) => alu.Transactor.IsLte(os[0], os[1], rs[0]);
                                        break;
                                    case InstructionCodes.IsEq:
                                        realize = (os, rs) => alu.Transactor.IsEq(os[0], os[1], rs[0]);
                                        break;
                                    case InstructionCodes.IsNEq:
                                        realize = (os, rs) => alu.Transactor.IsNEq(os[0], os[1], rs[0]);
                                        break;
                                    case InstructionCodes.IsGte:
                                        realize = (os, rs) => alu.Transactor.IsGte(os[0], os[1], rs[0]);
                                        break;
                                    case InstructionCodes.IsGt:
                                        realize = (os, rs) => alu.Transactor.IsGt(os[0], os[1], rs[0]);
                                        break;
                                    default:
                                        return null;
                                }
                                break;
                        }
                        break;

                    case InstructionCodes.And:
                        if (alu.FuncSel != ALU.EFunction.And)
                            return null;
                        break;

                    case InstructionCodes.Or:
                        if (alu.FuncSel != ALU.EFunction.Or)
                            return null;
                        break;
                }
            }
            return new ALUXILMapping(alu.Transactor, realize, swap);
        }