private static void VisitConnect(VisitHelper helper, FIRRTL.Expression exprFrom, FIRRTL.Expression exprTo, bool isPartial) { GraphFIR.IO.FIRIO from = VisitExp(helper, exprFrom, GraphFIR.IO.IOGender.Male); GraphFIR.IO.FIRIO to = (GraphFIR.IO.FIRIO)VisitRef(helper, exprTo, helper.Mod, GraphFIR.IO.IOGender.Female); //Can only connect two aggregates. If any of the two are not an //aggregate type then try convert both to scalar io and connect them. if (from is not GraphFIR.IO.AggregateIO || to is not GraphFIR.IO.AggregateIO) { from = from.GetOutput(); to = to.GetInput(); } ConnectIO(helper, from, to, isPartial); }
private static GraphFIR.IO.IContainerIO VisitRef(VisitHelper helper, FIRRTL.Expression exp, GraphFIR.IO.IContainerIO currContainer, GraphFIR.IO.IOGender gender) { GraphFIR.IO.IContainerIO refContainer; if (exp is FIRRTL.Reference reference) { refContainer = currContainer.GetIO(reference.Name); } else if (exp is FIRRTL.SubField subField) { var subContainer = VisitExp(helper, subField.Expr, gender); refContainer = subContainer.GetIO(subField.Name); } else if (exp is FIRRTL.SubIndex subIndex) { var subVec = VisitExp(helper, subIndex.Expr, gender); var vec = (GraphFIR.IO.Vector)subVec; refContainer = vec.GetIndex(subIndex.Value); } else if (exp is FIRRTL.SubAccess subAccess) { var subVec = VisitExp(helper, subAccess.Expr, gender); var vec = (GraphFIR.IO.Vector)subVec; var index = (GraphFIR.IO.Output)VisitExp(helper, subAccess.Index, GraphFIR.IO.IOGender.Male); if (gender == GraphFIR.IO.IOGender.Male) { GraphFIR.Mux node = new GraphFIR.Mux(vec.GetIOInOrder().ToList(), index, null, true); helper.AddNodeToModule(node); refContainer = node.Result; } else { GraphFIR.VectorAssign vecAssign = new GraphFIR.VectorAssign(vec, index, helper.Mod.EnableCon, null); helper.AddNodeToModule(vecAssign); refContainer = vecAssign.GetAssignIO(); } } else { throw new NotImplementedException(); } if (refContainer is GraphFIR.IO.MemPort memPort) { //Memory ports in high level firrtl are acceses in a different //way compared to low level firrtl. In high level firrtl, a //memory port is treated like a wire connected to its datain/out //sub field whereas in low level firrtl the subfield has to be //specified. if (memPort.FromHighLevelFIRRTL) { return(GetIOGender(helper, memPort, gender)); } } else { //Never return bigender io. Only this method should have to deal //with that mess so the rest of the code doesn't have to. //Dealing with it is ugly which is why i want to contain it. if (refContainer is GraphFIR.IO.FIRIO firIO) { return(GetIOGender(helper, firIO, gender)); } } return(refContainer); }
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(); } }