public override FIRIO ToFlow(FlowChange flow, FIRRTLNode node) { return(flow switch { FlowChange.Source => OutIO.ToFlow(flow, node), FlowChange.Sink => InIO.ToFlow(flow, node), FlowChange.Flipped => new DuplexIO(node, Name, InIO.ToFlow(flow, node), OutIO.ToFlow(flow, node)), FlowChange.Preserve => new DuplexIO(node, Name, InIO.ToFlow(flow, node), OutIO.ToFlow(flow, node)), var error => throw new Exception($"Unknown flow. Flow: {flow}") });
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 FIRIO ToFlow(FlowChange flow, FIRRTLNode node) { return(new MemoryIO(node, Name, GetIOInOrder().Select(x => x.ToFlow(flow, node)).ToList(), InputType.ToFlow(flow, node), AddressWidth, Ports.Select(x => (MemPort)x.ToFlow(flow, node)).ToList())); }