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); }