public FIRRTL.FirrtlNode GetDefNodeFromLowFirrtlGraph(string nodeName) { GraphFIR.Module lowFirMod = LowFirGraph.MainModule; string[] pathToModule = GetPathToCurrentActualModule(); //Skip first module name as it's the name of the root node //that we start with foreach (var pathModName in pathToModule.Skip(1)) { GraphFIR.FIRRTLNode[] lowModNodes = lowFirMod.GetAllNodes(); GraphFIR.FIRRTLNode childLowModNode = lowModNodes.FirstOrDefault(x => x is GraphFIR.Module mod && mod.Name == pathModName); if (childLowModNode == null) { throw new Exception("High level firrtl module path didn't match low level firrtl module path."); } lowFirMod = (GraphFIR.Module)childLowModNode; } //This is a meh way of going about getting the correct node. //Nodes by themselves don't have a name so it works on the assumption //that there exists an io with the name which points to the correct node. GraphFIR.IO.FIRIO nodeIO = (GraphFIR.IO.FIRIO)lowFirMod.GetIO(nodeName); return(nodeIO.Flatten().First().Node.FirDefNode); }
private static List <FIRIO> CreateIO(FIRIO inputType, int addressWidth, FIRRTLNode node) { FIRIO dataOut = inputType.Flip(node); dataOut.SetName("rdata"); FIRIO dataIn = inputType.Copy(node); dataIn.SetName("wdata"); FIRIO mask = inputType.Copy(node); mask.SetName("wmask"); AsMaskType(mask); List <FIRIO> io = new List <FIRIO>(); io.Add(new Input(node, "wmode", new UIntType(1))); io.Add(dataOut); io.Add(dataIn); io.Add(mask); io.Add(new Input(node, "addr", new UIntType(addressWidth))); io.Add(new Input(node, "en", new UIntType(1))); io.Add(new Input(node, "clk", new ClockType())); return(io); }
protected static void AsMaskType(FIRIO maskFrom) { foreach (ScalarIO scalar in maskFrom.Flatten()) { scalar.SetType(new UIntType(1)); } }
public MemWritePort(FIRRTLNode node, string name, List <FIRIO> io) : base(node, name, io) { this.DataIn = (FIRIO)GetIO("data"); this.Mask = (FIRIO)GetIO("mask"); InitDataToMask(); }
private static void ConnectIO(VisitHelper helper, GraphFIR.IO.FIRIO from, GraphFIR.IO.FIRIO to, bool isPartial, bool canBeConditional = true) { GraphFIR.Module fromMod = from.GetModResideIn(); GraphFIR.Module toMod = to.GetModResideIn(); //If going from inside to outside or outside to outside //then add condition to that connection if currently in //conditional module. GraphFIR.IO.Output condition = null; if (canBeConditional && ((fromMod == helper.Mod && toMod != helper.Mod) || (fromMod != helper.Mod && toMod != helper.Mod))) { condition = helper.Mod.EnableCon; } from.ConnectToInput(to, isPartial, false, condition); //If writing to a memory ports data in high level firrtl, then //the mask also has to be set to true for the part of the port data //that was written to. if (GraphFIR.IO.IOHelper.TryGetParentMemPort(to, out var memPort) && memPort.FromHighLevelFIRRTL && GraphFIR.IO.IOHelper.IsIOInMaskableMemPortData(to, memPort)) { var scopeEnableCond = helper.ScopeEnabledCond; foreach (GraphFIR.IO.Input dataInputWrittenTo in to.Flatten()) { var dataInputMask = memPort.GetMaskFromDataInput(dataInputWrittenTo); scopeEnableCond.ConnectToInput(dataInputMask, false, false, scopeEnableCond); } } }
public MemRWPort(FIRRTLNode node, string name, List <FIRIO> io) : base(node, name, io) { this.DataOut = (FIRIO)GetIO("rdata"); this.DataIn = (FIRIO)GetIO("wdata"); this.Mask = (FIRIO)GetIO("wmask"); this.WriteMode = (FIRIO)GetIO("wmode"); InitDataToMask(); }
public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null) { if (input is Input ioIn) { ioIn.Connect(this, condition); ConnectOnlyOutputSide(ioIn); } else { throw new Exception("Output can only be connected to input."); } }
public Vector(FIRRTLNode node, string name, int length, FIRIO firIO) : base(node, name) { if (!firIO.IsPassive()) { throw new Exception("IO type of vector must be passive."); } this.IO = new FIRIO[length]; for (int i = 0; i < IO.Length; i++) { IO[i] = firIO.Copy(node); IO[i].SetName(i.ToString()); IO[i].SetParentIO(this); } }
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 List <FIRIO> CreateIO(FIRIO inputType, int addressWidth, FIRRTLNode node) { FIRIO dataOut = inputType.Flip(node); dataOut.SetName("data"); List <FIRIO> io = new List <FIRIO>(); io.Add(dataOut); io.Add(new Input(node, "addr", new UIntType(addressWidth))); io.Add(new Input(node, "en", new UIntType(1))); io.Add(new Input(node, "clk", new ClockType())); return(io); }
public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null) { if (input is not Vector) { throw new Exception("Vector can only connect to other vector."); } Vector other = (Vector)input; if (!allowPartial && Length != other.Length) { throw new Exception("Vectors must have the same when when fully connecting them."); } int shortestLength = Math.Min(Length, other.Length); for (int i = 0; i < shortestLength; i++) { IO[i].ConnectToInput(other.IO[i], allowPartial, asPassive, condition); } }
private static GraphFIR.IO.FIRIO GetIOGender(VisitHelper helper, GraphFIR.IO.FIRIO io, GraphFIR.IO.IOGender gender) { if (io is GraphFIR.IO.Input input && gender == GraphFIR.IO.IOGender.Male) { string duplexOutputName = helper.Mod.GetDuplexOutputName(input); //Try see if it was already created if (input.GetModResideIn().TryGetIO(duplexOutputName, out var wireOut)) { return((GraphFIR.IO.Output)wireOut); } //Duplex output for this input wasn't created before so make it now. //Make it in the module that the input comes from so there won't //be multiple duplex inputs residing in different cond modules. return(input.GetModResideIn().AddDuplexOuputWire(input)); } return(io.GetAsGender(gender)); }
public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null) { if (input is not IOBundle) { throw new Exception("Bundle can only connect to other bundle."); } IOBundle bundle = (IOBundle)input; if (asPassive && !IsPassiveOfType <Output>()) { throw new Exception("Bundle must be a passive output bundle but it was not."); } if (asPassive && !bundle.IsPassiveOfType <Input>()) { throw new Exception("Bundle must connect to a passive input bundle."); } if (!allowPartial && IO.Count != bundle.IO.Count) { throw new Exception("Trying to fully connect two bundles that don't match."); } IEnumerable <string> ioConnectNames = IO.Keys; if (allowPartial) { ioConnectNames = ioConnectNames.Intersect(bundle.IO.Keys); } foreach (var ioName in ioConnectNames) { var a = GetIO(ioName); var b = bundle.GetIO(ioName); if (a is Output aOut && b is Input bIn) { aOut.ConnectToInput(bIn, allowPartial, asPassive, condition); }
public string GetFullName() { List <string> pathToRoot = new List <string>(); if (Name != null) { pathToRoot.Add(Name); } FIRIO node = this; while (node.ParentIO != null) { node = node.ParentIO; if (Name != null) { pathToRoot.Add(node.Name); } } pathToRoot.Reverse(); return(string.Join('.', pathToRoot)); }
public MemoryIO(FIRRTLNode node, string name, List <FIRIO> io, FIRIO inputType, int addressWidth) : this(node, name, io, inputType, addressWidth, new List <MemPort>()) { }
public MemReadPort(FIRRTLNode node, string name, List <FIRIO> io) : base(node, name, io) { this.DataOut = (FIRIO)GetIO("data"); }
public MemPort(FIRRTLNode node, string name, List <FIRIO> io) : base(node, name, io) { this.Address = (FIRIO)GetIO("addr"); this.Enabled = (FIRIO)GetIO("en"); this.Clock = (FIRIO)GetIO("clk"); }
private static void VisitStatement(VisitHelper helper, FIRRTL.Statement statement) { if (statement is FIRRTL.EmptyStmt) { return; } else if (statement is FIRRTL.Block block) { for (int i = 0; i < block.Statements.Count; i++) { VisitStatement(helper, block.Statements[i]); } } else if (statement is FIRRTL.Conditionally conditional) { VisitConditional(helper, conditional); } else if (statement is FIRRTL.Stop stop) { var clock = (GraphFIR.IO.Output)VisitExp(helper, stop.Clk, GraphFIR.IO.IOGender.Male); var enable = (GraphFIR.IO.Output)VisitExp(helper, stop.Enabled, GraphFIR.IO.IOGender.Male); var firStop = new GraphFIR.FirStop(clock, enable, stop.Ret, stop); helper.AddNodeToModule(firStop); } else if (statement is FIRRTL.Attach) { return; throw new NotImplementedException(); } else if (statement is FIRRTL.Print) { return; throw new NotImplementedException(); } else if (statement is FIRRTL.Verification) { return; throw new NotImplementedException(); } else if (statement is FIRRTL.Connect connect) { VisitConnect(helper, connect.Expr, connect.Loc, false); } else if (statement is FIRRTL.PartialConnect parConnected) { VisitConnect(helper, parConnected.Expr, parConnected.Loc, true); } else if (statement is FIRRTL.IsInvalid) { return; throw new NotImplementedException(); } else if (statement is FIRRTL.CDefMemory cmem) { //If have access to low firrth graph then get memory definition //from it as it includes all port definitions. This avoids having //to infer memory port types. if (helper.HasLowFirGraph()) { var lowFirMem = (FIRRTL.DefMemory)helper.GetDefNodeFromLowFirrtlGraph(cmem.Name); VisitStatement(helper, lowFirMem); //Low level firrtl addresses the ports through the memory but //high level firrtl directly addreses the ports. Need to //make the ports directly addresseable which is why this is done. var lowMem = (GraphFIR.IO.MemoryIO)helper.Mod.GetIO(cmem.Name); foreach (GraphFIR.IO.MemPort port in lowMem.GetAllPorts()) { port.FromHighLevelFIRRTL = true; helper.Mod.AddMemoryPort(port); } } else { GraphFIR.IO.FIRIO inputType = VisitTypeAsPassive(helper, FIRRTL.Dir.Input, null, cmem.Type); var memory = new GraphFIR.Memory(cmem.Name, inputType, cmem.Size, 0, 0, cmem.Ruw, cmem); helper.AddNodeToModule(memory); } } else if (statement is FIRRTL.CDefMPort memPort) { var memory = (GraphFIR.IO.MemoryIO)helper.Mod.GetIO(memPort.Mem); //Port may already have been created if the memory used the low firrtl //memory definition which contain all ports that will be used GraphFIR.IO.MemPort port; if (memory.TryGetIO(memPort.Name, out var existingPort)) { port = (GraphFIR.IO.MemPort)existingPort; } else { port = memPort.Direction switch { FIRRTL.MPortDir.MInfer => throw new NotImplementedException(), FIRRTL.MPortDir.MRead => memory.AddReadPort(memPort.Name), FIRRTL.MPortDir.MWrite => memory.AddWritePort(memPort.Name), FIRRTL.MPortDir.MReadWrite => memory.AddReadWritePort(memPort.Name), var error => throw new Exception($"Unknown memory port type. Type: {error}") }; port.FromHighLevelFIRRTL = true; helper.Mod.AddMemoryPort(port); } ConnectIO(helper, VisitExp(helper, memPort.Exps[0], GraphFIR.IO.IOGender.Male), port.Address, false); ConnectIO(helper, VisitExp(helper, memPort.Exps[1], GraphFIR.IO.IOGender.Male), port.Clock, false, false); ConnectIO(helper, helper.ScopeEnabledCond, port.Enabled, false); //if port has mask then by default set whole mask to true if (port.HasMask()) { GraphFIR.IO.FIRIO mask = port.GetMask(); GraphFIR.IO.Output const1 = (GraphFIR.IO.Output)VisitExp(helper, new FIRRTL.UIntLiteral(0, 1), GraphFIR.IO.IOGender.Male); foreach (var maskInput in mask.Flatten()) { ConnectIO(helper, const1, maskInput, false); } } } else if (statement is FIRRTL.DefWire defWire) { GraphFIR.IO.FIRIO inputType = VisitTypeAsPassive(helper, FIRRTL.Dir.Output, null, defWire.Type); inputType = inputType.ToFlow(GraphFIR.IO.FlowChange.Sink, null); GraphFIR.Wire wire = new GraphFIR.Wire(defWire.Name, inputType, defWire); helper.AddNodeToModule(wire); } else if (statement is FIRRTL.DefRegister reg) { GraphFIR.IO.Output clock = (GraphFIR.IO.Output)VisitExp(helper, reg.Clock, GraphFIR.IO.IOGender.Male); GraphFIR.IO.Output reset = null; GraphFIR.IO.FIRIO initValue = null; if (reg.HasResetAndInit()) { reset = (GraphFIR.IO.Output)VisitExp(helper, reg.Reset, GraphFIR.IO.IOGender.Male); initValue = VisitExp(helper, reg.Init, GraphFIR.IO.IOGender.Male); } GraphFIR.IO.FIRIO inputType = VisitTypeAsPassive(helper, FIRRTL.Dir.Input, null, reg.Type); GraphFIR.Register register = new GraphFIR.Register(reg.Name, inputType, clock, reset, initValue, reg); helper.AddNodeToModule(register); } else if (statement is FIRRTL.DefInstance instance) { GraphFIR.Module mod = VisitModule(helper, instance.Name, helper.ModuleRoots[instance.Module]); helper.AddNodeToModule(mod); } else if (statement is FIRRTL.DefNode node) { var nodeOut = VisitExp(helper, node.Value, GraphFIR.IO.IOGender.Male); if (node.Value is not FIRRTL.RefLikeExpression) { nodeOut.SetName(node.Name); } helper.Mod.AddIORename(node.Name, nodeOut); } else if (statement is FIRRTL.DefMemory mem) { GraphFIR.IO.FIRIO inputType = VisitTypeAsPassive(helper, FIRRTL.Dir.Input, null, mem.Type); var memory = new GraphFIR.Memory(mem.Name, inputType, mem.Depth, mem.ReadLatency, mem.WriteLatency, mem.Ruw, mem); foreach (var portName in mem.Readers) { memory.AddReadPort(portName); } foreach (var portName in mem.Writers) { memory.AddWritePort(portName); } foreach (var portName in mem.ReadWriters) { memory.AddReadWritePort(portName); } helper.AddNodeToModule(memory); } else { throw new NotImplementedException(); } }
public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null) { throw new Exception("Input can't be connected to output. Flow is reversed."); }
public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null) { throw new Exception("Duplex can't be connected to anything."); }
public MemRWPort(FIRRTLNode node, FIRIO inputType, int addressWidth, string name) : this(node, name, CreateIO(inputType, addressWidth, node)) { }
private MemoryIO(FIRRTLNode node, string name, List <FIRIO> io, FIRIO inputType, int addressWidth, List <MemPort> ports) : base(node, name, io) { this.Ports = ports; this.InputType = inputType.Copy(null); this.AddressWidth = addressWidth; }
public DuplexIO(FIRRTLNode node, string name, FIRIO inIO, FIRIO outIO) : base(node, name) { this.InIO = inIO; this.OutIO = outIO; }