private static GraphFIR.IO.FIRIO VisitExp(VisitHelper helper, FIRRTL.Expression exp, GraphFIR.IO.IOGender gender) { if (exp is FIRRTL.RefLikeExpression) { return((GraphFIR.IO.FIRIO)VisitRef(helper, exp, helper.Mod, gender)); } if (exp is FIRRTL.Literal lit) { GraphFIR.ConstValue value = new GraphFIR.ConstValue(lit); helper.AddNodeToModule(value); return(value.Result); } else if (exp is FIRRTL.DoPrim prim) { var args = prim.Args.Select(x => VisitExp(helper, x, GraphFIR.IO.IOGender.Male)).Cast <GraphFIR.IO.Output>().ToArray(); GraphFIR.FIRRTLPrimOP nodePrim; if (prim.Op is FIRRTL.Add) { nodePrim = new GraphFIR.FIRAdd(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Sub) { nodePrim = new GraphFIR.FIRSub(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Mul) { nodePrim = new GraphFIR.FIRMul(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Div) { nodePrim = new GraphFIR.FIRDiv(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Rem) { nodePrim = new GraphFIR.FIRRem(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Dshl) { nodePrim = new GraphFIR.FIRDshl(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Dshr) { nodePrim = new GraphFIR.FIRDshr(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Cat) { nodePrim = new GraphFIR.FIRCat(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Eq) { nodePrim = new GraphFIR.FIREq(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Neq) { nodePrim = new GraphFIR.FIRNeq(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Geq) { nodePrim = new GraphFIR.FIRGeq(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Leq) { nodePrim = new GraphFIR.FIRLeq(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Gt) { nodePrim = new GraphFIR.FIRGt(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Lt) { nodePrim = new GraphFIR.FIRLt(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.And) { nodePrim = new GraphFIR.FIRAnd(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Or) { nodePrim = new GraphFIR.FIROr(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Xor) { nodePrim = new GraphFIR.FIRXor(args[0], args[1], prim.Type, prim); } else if (prim.Op is FIRRTL.Head) { nodePrim = new GraphFIR.Head(args[0], prim.Type, (int)prim.Consts[0], prim); } else if (prim.Op is FIRRTL.Tail) { nodePrim = new GraphFIR.Tail(args[0], prim.Type, (int)prim.Consts[0], prim); } else if (prim.Op is FIRRTL.Bits) { nodePrim = new GraphFIR.BitExtract(args[0], prim.Type, (int)prim.Consts[1], (int)prim.Consts[0], prim); } else if (prim.Op is FIRRTL.Pad) { nodePrim = new GraphFIR.Pad(args[0], prim.Type, (int)prim.Consts[0], prim); } else if (prim.Op is FIRRTL.AsUInt) { nodePrim = new GraphFIR.FIRAsUInt(args[0], prim.Type, prim); } else if (prim.Op is FIRRTL.AsSInt) { nodePrim = new GraphFIR.FIRAsSInt(args[0], prim.Type, prim); } else if (prim.Op is FIRRTL.AsClock) { nodePrim = new GraphFIR.FIRAsClock(args[0], prim.Type, prim); } else if (prim.Op is FIRRTL.Cvt) { nodePrim = new GraphFIR.FIRCvt(args[0], prim.Type, prim); } else if (prim.Op is FIRRTL.Neg) { nodePrim = new GraphFIR.FIRNeg(args[0], prim.Type, prim); } else if (prim.Op is FIRRTL.Not) { nodePrim = new GraphFIR.FIRNot(args[0], prim.Type, prim); } else if (prim.Op is FIRRTL.Andr) { nodePrim = new GraphFIR.FIRAndr(args[0], prim.Type, prim); } else if (prim.Op is FIRRTL.Orr) { nodePrim = new GraphFIR.FIROrr(args[0], prim.Type, prim); } else if (prim.Op is FIRRTL.Xorr) { nodePrim = new GraphFIR.FIRXorr(args[0], prim.Type, prim); } else if (prim.Op is FIRRTL.Shl) { var constLit = new FIRRTL.UIntLiteral(prim.Consts[0], (int)prim.Consts[0].GetBitLength()); var constOutput = (GraphFIR.IO.Output)VisitExp(helper, constLit, GraphFIR.IO.IOGender.Male); nodePrim = new GraphFIR.FIRShl(args[0], constOutput, prim.Type, prim); } else if (prim.Op is FIRRTL.Shr) { var constLit = new FIRRTL.UIntLiteral(prim.Consts[0], (int)prim.Consts[0].GetBitLength()); var constOutput = (GraphFIR.IO.Output)VisitExp(helper, constLit, GraphFIR.IO.IOGender.Male); nodePrim = new GraphFIR.FIRShr(args[0], constOutput, prim.Type, prim); } else { throw new NotImplementedException(); } helper.AddNodeToModule(nodePrim); return(nodePrim.Result); } else if (exp is FIRRTL.Mux mux) { var cond = (GraphFIR.IO.Output)VisitExp(helper, mux.Cond, GraphFIR.IO.IOGender.Male); var ifTrue = VisitExp(helper, mux.TrueValue, GraphFIR.IO.IOGender.Male); var ifFalse = VisitExp(helper, mux.FalseValue, GraphFIR.IO.IOGender.Male); GraphFIR.Mux node = new GraphFIR.Mux(new List <GraphFIR.IO.FIRIO>() { ifTrue, ifFalse }, cond, mux); helper.AddNodeToModule(node); return(node.Result); } else if (exp is FIRRTL.ValidIf validIf) { var cond = (GraphFIR.IO.Output)VisitExp(helper, validIf.Cond, GraphFIR.IO.IOGender.Male); var ifValid = VisitExp(helper, validIf.Value, GraphFIR.IO.IOGender.Male); GraphFIR.Mux node = new GraphFIR.Mux(new List <GraphFIR.IO.FIRIO>() { ifValid }, cond, validIf); helper.AddNodeToModule(node); return(node.Result); } else { throw new NotImplementedException(); } }
private static void VisitConditional(VisitHelper parentHelper, FIRRTL.Conditionally conditional) { GraphFIR.Conditional cond = new GraphFIR.Conditional(conditional); void AddCondModule(GraphFIR.IO.Output ena, FIRRTL.Statement body) { VisitHelper helper = parentHelper.ForNewCondModule(parentHelper.GetUniqueName(), null); var internalEnaDummy = new GraphFIR.DummyPassthrough(ena); var internalUseEna = new GraphFIR.DummySink(internalEnaDummy.Result); helper.AddNodeToModule(internalEnaDummy); helper.AddNodeToModule(internalUseEna); helper.Mod.SetEnableCond(internalEnaDummy.Result); //Set signal that enables this scope as things like memory //ports need it helper.EnterEnabledScope(internalEnaDummy.Result); //Fill out module VisitStatement(helper, body); cond.AddConditionalModule(internalEnaDummy.InIO, helper.Mod); helper.ExitEnabledScope(); } GraphFIR.IO.Output enableCond = (GraphFIR.IO.Output)VisitExp(parentHelper, conditional.Pred, GraphFIR.IO.IOGender.Male); if (conditional.HasIf()) { GraphFIR.IO.Output ifEnableCond = enableCond; if (parentHelper.Mod.IsConditional) { GraphFIR.FIRAnd chainConditions = new GraphFIR.FIRAnd(parentHelper.Mod.EnableCon, enableCond, new FIRRTL.UIntType(1), null); parentHelper.AddNodeToModule(chainConditions); ifEnableCond = chainConditions.Result; } AddCondModule(ifEnableCond, conditional.WhenTrue); } if (conditional.HasElse()) { GraphFIR.FIRNot notEnableComponent = new GraphFIR.FIRNot(enableCond, new FIRRTL.UIntType(1), null); parentHelper.AddNodeToModule(notEnableComponent); GraphFIR.IO.Output elseEnableCond = notEnableComponent.Result; if (parentHelper.Mod.IsConditional) { GraphFIR.FIRAnd chainConditions = new GraphFIR.FIRAnd(parentHelper.Mod.EnableCon, elseEnableCond, new FIRRTL.UIntType(1), null); parentHelper.AddNodeToModule(chainConditions); elseEnableCond = chainConditions.Result; } AddCondModule(elseEnableCond, conditional.Alt); } parentHelper.AddNodeToModule(cond); }