From 3516d1f4ad38ecc44a6d12b8035d2804f9f18fb0 Mon Sep 17 00:00:00 2001 From: megacz Date: Mon, 29 Dec 2008 17:46:51 -0800 Subject: [PATCH] massive overhaul of fpga code --- src/edu/berkeley/fleet/fpga/FabricElement.java | 11 +- src/edu/berkeley/fleet/fpga/FanoutModule.java | 13 +- src/edu/berkeley/fleet/fpga/FifoModule.java | 23 +- src/edu/berkeley/fleet/fpga/Fpga.java | 163 ++--- src/edu/berkeley/fleet/fpga/FpgaDestination.java | 7 +- src/edu/berkeley/fleet/fpga/FpgaDock.java | 224 +++---- src/edu/berkeley/fleet/fpga/FpgaShip.java | 14 +- src/edu/berkeley/fleet/fpga/FunnelModule.java | 4 +- src/edu/berkeley/fleet/fpga/HornModule.java | 14 +- src/edu/berkeley/fleet/fpga/verilog/Verilog.java | 745 +++++++++++++--------- src/edu/berkeley/fleet/two/DockDescription.java | 6 + src/edu/berkeley/fleet/two/ShipDescription.java | 17 +- src/edu/berkeley/fleet/util/Mask.java | 4 - 13 files changed, 687 insertions(+), 558 deletions(-) diff --git a/src/edu/berkeley/fleet/fpga/FabricElement.java b/src/edu/berkeley/fleet/fpga/FabricElement.java index d5a4c9b..bcf44b7 100644 --- a/src/edu/berkeley/fleet/fpga/FabricElement.java +++ b/src/edu/berkeley/fleet/fpga/FabricElement.java @@ -15,11 +15,20 @@ import static edu.berkeley.fleet.fpga.verilog.Verilog.*; public interface FabricElement { - public FpgaPath getPath(FabricElement dest, BitVector signal); + public FpgaPath getPath(FpgaDestination dest, BitVector signal); public void addInput(FabricElement in, Module.Port inPort); public void addOutput(FabricElement out, Module.Port outPort); public Module.SourcePort getOutputPort(); public Module.Port getInputPort(); + + public static abstract class AbstractFabricElement implements FabricElement { + public abstract FpgaPath getPath(FpgaDestination dest, BitVector signal); + public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); } + public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); } + public Module.SourcePort getOutputPort() { throw new RuntimeException(); } + public Module.Port getInputPort() { throw new RuntimeException(); } + } + } diff --git a/src/edu/berkeley/fleet/fpga/FanoutModule.java b/src/edu/berkeley/fleet/fpga/FanoutModule.java index 250f536..05bda6b 100644 --- a/src/edu/berkeley/fleet/fpga/FanoutModule.java +++ b/src/edu/berkeley/fleet/fpga/FanoutModule.java @@ -16,16 +16,11 @@ public class FanoutModule extends Module { public FanoutModule(int width) { super("fanout"+width); Module.SourcePort in = createInputPort ("in", width); - Module.SinkPort out0 = createOutputPort("out0", width, ""); - Module.SinkPort out1 = createOutputPort("out1", width, ""); - in.hasLatch = false; - out0.hasLatch = false; - out0.forceNoLatch = true; - out1.hasLatch = false; - out1.forceNoLatch = true; + Module.SinkPort out0 = createOutputPort("out0", width); + Module.SinkPort out1 = createOutputPort("out1", width); - out0.latchDriver = in; - out1.latchDriver = in; + out0.connectValue(in); + out1.connectValue(in); Module.StateWire busy = new StateWire("busy", false); new Event(new Object[] { in, out0, out1, busy.isEmpty() }, diff --git a/src/edu/berkeley/fleet/fpga/FifoModule.java b/src/edu/berkeley/fleet/fpga/FifoModule.java index ee48cdd..0741e0c 100644 --- a/src/edu/berkeley/fleet/fpga/FifoModule.java +++ b/src/edu/berkeley/fleet/fpga/FifoModule.java @@ -20,11 +20,9 @@ public class FifoModule extends Module { this.len = len; this.width = width; Module.SourcePort in = createInputPort("in", width); - Module.SinkPort out = createOutputPort("out", width, ""); + Module.SinkPort out = createOutputPort("out", width); Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len]; if (len==0) { - in.hasLatch = false; - out.hasLatch = false; in.connect(out); } else if (len==1) { new Event(new Object[] { in, out }, @@ -49,15 +47,18 @@ public class FifoModule extends Module { public void dump(String prefix) throws IOException { if (len>16) throw new RuntimeException("FifoModule(i>16) not supported due to SRL16 limitation"); - if (len<2) { - super.dump(prefix); + + if (len>=2) { + PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v"))); + pw.println("`define ADDR_BITS "+dislog(len)); + pw.println("`define WIDTH " + width); + pw.println("`define MODULE_NAME "+name); + pw.println("`include \"ramfifo.inc\""); + pw.flush(); return; } - PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v"))); - pw.println("`define ADDR_BITS "+dislog(len)); - pw.println("`define WIDTH " + width); - pw.println("`define MODULE_NAME "+name); - pw.println("`include \"ramfifo.inc\""); - pw.flush(); + + super.dump(prefix); + return; } } diff --git a/src/edu/berkeley/fleet/fpga/Fpga.java b/src/edu/berkeley/fleet/fpga/Fpga.java index 7a2b410..76016db 100644 --- a/src/edu/berkeley/fleet/fpga/Fpga.java +++ b/src/edu/berkeley/fleet/fpga/Fpga.java @@ -19,7 +19,6 @@ import static edu.berkeley.fleet.fpga.verilog.Verilog.PercolatedPort; public class Fpga extends FleetTwoFleet { public Module top; - public FabricElement top_horn; Ship debugShip; public LinkedHashMap ships = new LinkedHashMap(); @@ -58,14 +57,17 @@ public class Fpga extends FleetTwoFleet { } catch (Exception e) { throw new RuntimeException(e); } } - public BitVector getDestAddr(Path path) { + protected BitVector getDestAddr(Path path) { return ((FpgaPath)path).toBitVector(); } // Setup ////////////////////////////////////////////////////////////////////////////// - public Ship createShip(String type, String name) throws IOException { + Ship createShip(String type) throws IOException { ShipDescription sd = new ShipDescription(type, new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship")))); + int count = 0; + for(Ship ship : ships.values()) if (ship.getType().equals(type)) count++; + String name = type+count; FpgaShip ship = new FpgaShip(this, sd); ships.put(name, ship); return ship; @@ -74,105 +76,74 @@ public class Fpga extends FleetTwoFleet { public Fpga() throws Exception { this(new Module("main")); } public Fpga(Module top) throws Exception { this.top = top; - debugShip = createShip("Debug", "debug"); + debugShip = createShip("Debug"); - //boolean small = false; boolean small = true; - - createShip("Memory", "memory1"); + //boolean small = false; if (small) { - for(int i=0; i<2; i++) - createShip("Fifo", "fifo"+i); - for(int i=0; i<2; i++) - createShip("Alu", "alu"+i); - createShip("Counter", "counter"); - createShip("CarrySaveAdder", "csa1"); - createShip("Rotator", "rotator"); - createShip("Lut3", "lut"); + for(int i=0; i<1; i++) createShip("Memory"); + for(int i=0; i<2; i++) createShip("Fifo"); + for(int i=0; i<2; i++) createShip("Alu"); + createShip("Counter"); + createShip("CarrySaveAdder"); + createShip("Rotator"); + createShip("Lut3"); + createShip("DDR2"); } else { - createShip("Memory", "memory2"); - createShip("Memory", "memory3"); - - for(int i=0; i<3; i++) - createShip("Alu", "alu"+i); - - for(int i=0; i<1; i++) - createShip("Fifo", "fifo"+i); - - for(int i=0; i<14; i++) - createShip("Counter", "counter"+i); - - /* - createShip("CarrySaveAdder", "csa1"); - createShip("Rotator", "rotator"); - createShip("Lut3", "lut"); - */ - //createShip("DDR2", "ddr2"); + for(int i=0; i<3; i++) createShip("Memory"); + for(int i=0; i<3; i++) createShip("Alu"); + for(int i=0; i<2; i++) createShip("Fifo"); + for(int i=0; i<14; i++) createShip("Counter"); + + // "really big" configuration: 138 docks + for(int i=0; i<10; i++) createShip("Alu"); + createShip("CarrySaveAdder"); + createShip("Rotator"); + createShip("Lut3"); + + //createShip("DRAM"); + //createShip("Video"); } - createShip("DRAM", "dram"); - createShip("Video", "video"); // for FifoShip new Module.InstantiatedModule(top, new FifoModule(8, WIDTH_WORD)); - Module.Latch temp_in = top.new Latch("temp", WIDTH_PACKET); - Module.Latch count = top.new Latch("count", 8); - - ArrayList inbox_sources = new ArrayList(); - ArrayList inbox_dests = new ArrayList(); - ArrayList outbox_sources = new ArrayList(); - ArrayList outbox_dests = new ArrayList(); - ArrayList instruction_dests = new ArrayList(); - int numdocks = 0; + ArrayList dests = new ArrayList(); + ArrayList sources = new ArrayList(); for(FpgaShip ship : (Iterable)(Object)this) { for(Dock port : ship) { if (port.isInputDock()) { - inbox_sources.add(((FpgaDock)port)); - instruction_dests.add(port.getInstructionDestination()); - inbox_dests.add(port.getDataDestination()); + sources.add(((FpgaDock)port)); + dests.add(port.getInstructionDestination()); + dests.add(port.getDataDestination()); } else { - outbox_sources.add(((FpgaDock)port)); - instruction_dests.add(port.getInstructionDestination()); - outbox_dests.add(port.getDataDestination()); + sources.add(((FpgaDock)port)); + dests.add(port.getInstructionDestination()); + dests.add(port.getDataDestination()); } - numdocks++; + } + for(Module.SourcePort sp0 : ship.docklessPorts.values()) { + final Module.SourcePort sp = sp0; + sources.add(new FabricElement.AbstractFabricElement() { + private FabricElement upstream; + public FpgaPath getPath(FpgaDestination dest, BitVector signal) { return upstream.getPath(dest, signal); } + public void addOutput(FabricElement out, Module.Port outPort) { + this.upstream = out; + sp.connect((Module.SinkPort)outPort); + } + }); } } - ArrayList dests = new ArrayList(); - ArrayList sources = new ArrayList(); - sources.addAll(inbox_sources); - sources.addAll(outbox_sources); - dests.addAll(inbox_dests); - dests.addAll(instruction_dests); - dests.addAll(outbox_dests); - top_horn = mkNode((FabricElement[])dests.toArray(new FabricElement[0]), true); - FabricElement source = mkNode((FabricElement[])sources.toArray(new FabricElement[0]), false); - FunnelModule.FunnelInstance top_funnel = new FunnelModule.FunnelInstance(this, top, null, source.getOutputPort()); - ((FunnelModule.FunnelInstance)source).out = top_funnel; - top_funnel.addOutput(top_horn, top_horn.getInputPort()); - Module.SinkPort debug_in = top_funnel.getInputPort("in1"); - - top.addPreCrap("reg root_in_a_;"); - top.addPreCrap("assign root_in_a = root_in_a_;"); - top.new Event(new Object[] { "(root_in_r && root_in_a)" }, - new Object[] { new SimpleAction("root_in_a_<=0;") }); - top.new Event(new Object[] { "(root_in_r && !root_in_a)", "count<=7" }, - new Object[] { new SimpleAction(temp_in.getVerilogName()+" <= {" + temp_in.getVerilogName() + "["+(WIDTH_PACKET-(1+8))+":0], root_in_d[7:0] };"), - new AssignAction(count, count.getVerilogName()+"+1"), - new SimpleAction("root_in_a_<=1;") - }); - top.new Event(new Object[] { debug_in, "count>7" }, - new Object[] { new AssignAction(count, "0"), - new AssignAction(debug_in, temp_in), - debug_in - }); + FabricElement top_horn = mkNode((FabricElement[])dests.toArray(new FabricElement[0]), true); + mkNode((FabricElement[])sources.toArray(new FabricElement[0]), false) + .addOutput(top_horn, top_horn.getInputPort()); } public FabricElement mkNode(FabricElement[] ports, boolean is_horn) { return mkNode(ports, is_horn, 0, ports.length); } public FabricElement mkNode(FabricElement[] ports, boolean is_horn, int start, int end) { switch(end-start) { - case 0: return null; + case 0: throw new RuntimeException("this should never happen"); case 1: return ports[start]; default: { FabricElement leftPort = mkNode(ports, is_horn, start, (end+start)/2); @@ -201,7 +172,7 @@ public class Fpga extends FleetTwoFleet { pw.println("`define CODEBAG_SIZE_BITS "+CBD_SIZE.valmaskwidth); pw.println(); - for(DockDescription dd : sd) { + for(DockDescription dd : sd.ports()) { String name = dd.getName(); pw.println("`define "+name+"_full ("+name+"_r && !"+name+"_a)"); pw.println("`define "+name+"_empty (!"+name+"_r && !"+name+"_a)"); @@ -209,12 +180,11 @@ public class Fpga extends FleetTwoFleet { pw.println("`define drain_"+name+" "+name+"_a <= 1;"); } else { pw.println("`define fill_"+name+" "+name+"_r <= 1;"); - pw.println("`define "+name+"_draining ("+name+"_r && "+name+"_a)"); } } pw.print("`define reset "); - for(DockDescription bb : sd) { + for(DockDescription bb : sd.ports()) { String bb_name = bb.getName(); if (bb.isInputDock()) pw.print(bb_name+"_a <= 1; "+bb_name+"_f <= 0; "); else pw.print(bb_name+"_r <= 0; "); @@ -222,7 +192,7 @@ public class Fpga extends FleetTwoFleet { pw.println(); pw.print("`define cleanup "); - for(DockDescription bb : sd) { + for(DockDescription bb : sd.ports()) { String bb_name = bb.getName(); if (bb.isInputDock()) pw.print("if (!"+bb_name+"_r && "+bb_name+"_a) "+bb_name+"_a <= 0; "); else pw.print("if ( "+bb_name+"_r && "+bb_name+"_a) "+bb_name+"_r <= 0; "); @@ -232,39 +202,39 @@ public class Fpga extends FleetTwoFleet { // FIXME: this corresponds to something /* pw.print("`define flush_happening (1"); - for(DockDescription bb : sd) + for(DockDescription bb : sd.ports()) if (bb.isInputDock()) pw.print(" && "+bb.getName()+"_r_ && !"+bb.getName()+"_a && "+bb.getName()+"_d["+WIDTH_WORD+"]"); pw.println(")"); */ pw.print("`define flush "); - for(DockDescription bb : sd) + for(DockDescription bb : sd.ports()) if (bb.isInputDock()) pw.print(" if (!"+bb.getName()+"_r_) "+bb.getName()+"_f <= 0; "); pw.print("if (1"); - for(DockDescription bb : sd) + for(DockDescription bb : sd.ports()) if (bb.isInputDock()) pw.print(" && "+bb.getName()+"_r_ && !"+bb.getName()+"_a"); pw.print(") begin "); if (true) { pw.print("if (1"); - for(DockDescription bb : sd) + for(DockDescription bb : sd.ports()) if (bb.isInputDock()) pw.print(" && "+bb.getName()+"_d["+WIDTH_WORD+"] "); pw.print(") begin "); if (true) { - for(DockDescription bb : sd) + for(DockDescription bb : sd.ports()) if (bb.isInputDock()) pw.print(bb.getName()+"_f <= 1; "); } pw.print(" end else if (0"); - for(DockDescription bb : sd) + for(DockDescription bb : sd.ports()) if (bb.isInputDock()) pw.print(" || "+bb.getName()+"_d["+WIDTH_WORD+"] "); pw.print(") begin "); if (true) { - for(DockDescription bb : sd) + for(DockDescription bb : sd.ports()) if (bb.isInputDock()) pw.print(" if (!"+bb.getName()+"_d["+WIDTH_WORD+"]) "+bb.getName()+"_f <= 1; "); } @@ -274,7 +244,7 @@ public class Fpga extends FleetTwoFleet { pw.println(); pw.println("module " + filename + "( clk, rst "); - for(DockDescription bb : sd) { + for(DockDescription bb : sd.ports()) { String bb_name = bb.getName(); pw.print(" "); if (bb.isInputDock()) { @@ -310,13 +280,14 @@ public class Fpga extends FleetTwoFleet { pw.println(";"); } - for(DockDescription bb : sd) { + for(DockDescription bb : sd.ports()) { String bb_name = bb.getName(); + int width = bb.isDockless() ? WIDTH_PACKET : WIDTH_WORD; if (bb.isInputDock()) { - pw.println(" input ["+WIDTH_WORD+":0] "+bb_name+"_d;"); + pw.println(" input ["+width+":0] "+bb_name+"_d;"); pw.println(" input "+bb_name+"_r_;"); pw.println(" wire "+bb_name+"_r;"); - pw.println(" assign "+bb_name+"_r = "+bb_name+"_r_ & ~"+bb_name+"_d["+WIDTH_WORD+"];"); + pw.println(" assign "+bb_name+"_r = "+bb_name+"_r_ & ~"+bb_name+"_d["+width+"];"); pw.println(" output "+bb_name+"_a_;"); pw.println(" reg "+bb_name+"_a;"); pw.println(" initial "+bb_name+"_a = 0;"); @@ -324,7 +295,7 @@ public class Fpga extends FleetTwoFleet { pw.println(" initial "+bb_name+"_f = 0;"); pw.println(" assign "+bb_name+"_a_ = "+bb_name+"_a || "+bb_name+"_f;"); } else { - pw.println(" output ["+WIDTH_WORD+":0] "+bb_name+"_d_;"); + pw.println(" output ["+width+":0] "+bb_name+"_d_;"); pw.println(" input "+bb_name+"_a;"); pw.println(" output "+bb_name+"_r_;"); pw.println(" reg "+bb_name+"_r;"); diff --git a/src/edu/berkeley/fleet/fpga/FpgaDestination.java b/src/edu/berkeley/fleet/fpga/FpgaDestination.java index 17dbc7a..c20ccd0 100644 --- a/src/edu/berkeley/fleet/fpga/FpgaDestination.java +++ b/src/edu/berkeley/fleet/fpga/FpgaDestination.java @@ -30,15 +30,12 @@ public class FpgaDestination extends Destination implements FabricElement { public Module.Port getInputPort() { throw new RuntimeException(); } public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); } - public long getAddr() { - return ((Fpga)dock.getShip().getFleet()).top_horn.getPath(this,null).toLong(); - } - public FpgaPath getPath(FabricElement dest, BitVector signal) { + public FpgaPath getPath(FpgaDestination dest, BitVector signal) { if (dest==this) return FpgaPath.emptyPath(this, signal); return null; } public void addInput(FabricElement in, Module.Port inPort) { - inPort.connect((Module.SinkPort)port); + ((Module.SourcePort)inPort).connect((Module.SinkPort)port); } public String toString() { return dock.toString(); diff --git a/src/edu/berkeley/fleet/fpga/FpgaDock.java b/src/edu/berkeley/fleet/fpga/FpgaDock.java index 2fd0b6e..f0ea9fd 100644 --- a/src/edu/berkeley/fleet/fpga/FpgaDock.java +++ b/src/edu/berkeley/fleet/fpga/FpgaDock.java @@ -16,7 +16,6 @@ import edu.berkeley.fleet.api.Dock; import edu.berkeley.fleet.two.*; import java.util.*; -/** the pump itself is a */ public class FpgaDock extends FleetTwoDock implements FabricElement { private static final int INSTRUCTION_FIFO_SIZE = 12; @@ -56,8 +55,8 @@ public class FpgaDock extends FleetTwoDock implements FabricElement { private FabricElement upstream; public Module.SourcePort getOutputPort() { throw new RuntimeException(); } public Module.Port getInputPort() { throw new RuntimeException(); } - public FpgaPath getPath(FabricElement dest, BitVector signal) { return upstream.getPath((FabricElement)dest, signal); } - public FpgaPath getPath(Destination dest,BitVector signal) { return upstream.getPath((FabricElement)dest, signal); } + public Path getPath(Destination dest,BitVector signal) { return getPath((FpgaDestination)dest, signal); } + public FpgaPath getPath(FpgaDestination dest,BitVector signal) { return upstream.getPath(dest, signal); } public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); } public void addOutput(FabricElement out, Module.Port outPort) { this.upstream = out; @@ -68,19 +67,18 @@ public class FpgaDock extends FleetTwoDock implements FabricElement { public TorpedoBranchModule() { super("torpedobranch"); Module.SourcePort in = createInputPort ("in", fpga.WIDTH_PACKET); - Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth, ""); - Module.SinkPort torpedo = createOutputPort("torpedo", 0, ""); + Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth); + Module.SinkPort torpedo = createOutputPort("torpedo", 0); Module.StateWire busy = new StateWire("busy", false); - out.forceNoLatch = true; new Event(new Object[] { in, busy.isFull(), out }, new Action[] { in, busy.doDrain() }); - new Event(new Object[] { in, busy.isEmpty(), out, torpedo, in.getBits(fpga.PACKET_TOKEN) }, + new Event(new Object[] { in, busy.isEmpty(), out, torpedo, in.testMask(fpga.PACKET_IS_TOKEN) }, new Action[] { in, torpedo }); - new Event(new Object[] { in, busy.isEmpty(), out, in.getBits(fpga.PACKET_TOKEN).invertBits() }, + new Event(new Object[] { in, busy.isEmpty(), out, in.testMask(fpga.PACKET_IS_TOKEN).invert() }, new Action[] { busy.doFill(), out }); - out.latchDriver = in.getBits(fpga.PACKET_DATA); + out.connectValue(in.getBits(fpga.PACKET_DATA)); } } @@ -90,15 +88,14 @@ public class FpgaDock extends FleetTwoDock implements FabricElement { Module.SourcePort fabric_in = createInputPort ("fabric_in", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth); Module.SourcePort ondeck_in = createInputPort ("ondeck_in", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth); Module.SourcePort flag_z = createInputPort ("flag_z", 1); - Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth, ""); - out.forceNoLatch = true; + Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth); Module.StateWire using = new StateWire("using", false); Module.StateWire circulating = new StateWire("circulating", false); Module.StateWire doResetFabric = new StateWire("doResetFabric", false); Module.StateWire doResetOndeck = new StateWire("doResetOndeck", false); - addPreCrap("assign out = "+circulating.isEmpty()+" ? "+fabric_in.getName()+" : "+ondeck_in.getName()+";"); + out.connectValue(new MuxValue(circulating.isEmpty(), fabric_in, ondeck_in)); // always: discard one-shot instructions new Event(new Object[] { ondeck_in, fpga.OS.verilog(ondeck_in.getName()) }, @@ -140,34 +137,22 @@ public class FpgaDock extends FleetTwoDock implements FabricElement { Module.SourcePort fabric_in = createInputPort("fabric_in", fpga.WIDTH_PACKET); // FIXME: at inboxes, no need for a full set of latches - Module.SinkPort fabric_out = createOutputPort("fabric_out", fpga.WIDTH_PACKET, ""); + Module.SinkPort fabric_out = createOutputPort("fabric_out", fpga.WIDTH_PACKET); Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m); - fabric_in.hasLatch = false; fabric_in.connect(dfifo.getInputPort("in")); - dfifo.getInputPort("in").noDriveLatches = true; - if (inbox) - addPreCrap("assign "+dfifo.getInputPort("in").getName()+ - " = { "+fpga.PACKET_SIGNAL.verilogVal("fabric_in")+ - ", "+fpga.PACKET_DATA.verilogVal("fabric_in")+" };\n"); - else - addPreCrap("assign "+dfifo.getInputPort("in").getName()+ - " = "+fpga.PACKET_SIGNAL.verilogVal("fabric_in")+";\n"); - + dfifo.getInputPort("in").connectValue( + !inbox + ? fabric_in.getBits(fpga.PACKET_SIGNAL) + : new CatValue(new Value[] { + fabric_in.getBits(fpga.PACKET_SIGNAL), + fabric_in.getBits(fpga.PACKET_DATA) + })); - Module.SourcePort dfifo_out = dfifo.getOutputPort("out"); - Module.SourcePort ship_out = null; - if (!inbox) { - ship_out = createInputPort("ship", fpga.getWordWidth()+1); - ship_out.hasLatch = true; - } - - Module.SinkPort ship_in = null; - if (inbox) { - ship_in = createOutputPort("ship", fpga.getWordWidth()+1, ""); - ship_in.hasLatch = true; - } + Module.SourcePort dfifo_out = dfifo.getOutputPort("out"); + Module.SourcePort ship_out = !inbox ? createInputPort("ship", fpga.getWordWidth()+1) : null; + Module.SinkPort ship_in = inbox ? createOutputPort("ship", fpga.getWordWidth()+1) : null; Module.Latch ilc = new Latch("ilc", fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1); Module.Latch olc = new Latch("olc", fpga.SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1); @@ -185,8 +170,6 @@ public class FpgaDock extends FleetTwoDock implements FabricElement { Module.SinkPort ififo_in = ififo.getInputPort("in"); Module.SourcePort ififo_out = ififo.getOutputPort("out"); - Module.SinkPort data_latch_output_p = createWirePort("data_latch_output", inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth()); - Module.InstantiatedModule torpedo_branch = new Module.InstantiatedModule(this, new TorpedoBranchModule()); instruction.connect(torpedo_branch.getInputPort("in")); Module.SourcePort efifo_out = torpedo_branch.getOutputPort("out"); @@ -209,16 +192,25 @@ public class FpgaDock extends FleetTwoDock implements FabricElement { fanout_module_out0.connect(requeue_ondeck); Module.SourcePort ondeck = fanout_module_out1; - addPreCrap("assign data_latch_output = " + (inbox ? data_out.getName() : fpga.PACKET_DATA.verilogVal(data_out.getName()))+";"); - addPreCrap("wire ["+(Math.max(ilc.width,olc.width)-1)+":0] decremented;"); - addPreCrap("assign decremented = ("+fpga.SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName())+" ? {1'b0, olc} : ilc)-1;"); - addPreCrap("assign "+requeue_flag_z.getName()+" = (olc==0);"); + WireValue decremented = new WireValue("decremented", Math.max(ilc.width,olc.width), + new SimpleValue("("+ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE).getVerilogTrigger()+ + " ? {1'b0, olc} : ilc)-1")); + WireValue data_latch_output_p = new WireValue("data_latch_output", + inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth(), + (inbox + ? new SimpleValue(data_out.getName()) + : new SimpleValue(data_out.getBits(fpga.PACKET_DATA).getVerilog())) + ); + requeue_flag_z.connectValue(new SimpleValue("(olc==0)")); - Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : fpga.PACKET_DATA.verilogVal(data_out.getName())); - String data_latch_input = inbox ? data_in.getName() : data_in.getName(); + Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : data_out.getBits(fpga.PACKET_DATA).getVerilog()); + Module.SourcePort data_latch_input = inbox ? data_in : data_in; - String magic_standing_value = "(1<<"+fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+")"; - String done_executing = "((ilc==0) || (ilc==1) || !"+fpga.MOVE.verilog(ondeck.getName())+")"; + BitVector bv = new BitVector(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1); + bv.set(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth, true); + Value magic_standing_value = new ConstantValue(bv); + + Trigger done_executing = new SimpleTrigger("((ilc==0) || (ilc==1) || !"+fpga.MOVE.verilog(ondeck.getName())+")"); String predicate_met = "("+ @@ -252,15 +244,16 @@ public class FpgaDock extends FleetTwoDock implements FabricElement { new Object[] { ondeck, torpedo_branch_torpedo, - new AssignAction(olc, "0"), - new AssignAction(flag_z, "1"), - new AssignAction(ilc, "1") + new AssignAction(olc, new ConstantValue(new BitVector(olc.width).set(0))), + new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0))), + new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1))) }); // Predicate not met new Event(new Object[] { ondeck, "!("+predicate_met+")" }, new Action[] { ondeck, - new ConditionalAction(fpga.MOVE.verilog(ondeck.getName()), new AssignAction(ilc, "1")) + new ConditionalAction(ondeck.testMask(fpga.MOVE), + new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))) }); new Event(new Object[] { ondeck, @@ -268,76 +261,91 @@ public class FpgaDock extends FleetTwoDock implements FabricElement { token_out, predicate_met, "(!"+fpga.MOVE.verilog(ondeck.getName())+" || "+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName())+" || !"+torpedo_branch_torpedo.isFull()+")", - new ConditionalTrigger(fpga.DI.verilog(ondeck.getName()), data_in), - new ConditionalTrigger(fpga.TI.verilog(ondeck.getName()), token_in) + new ConditionalTrigger(ondeck.testMask(fpga.DI), data_in), + new ConditionalTrigger(ondeck.testMask(fpga.TI), token_in) }, new Action[] { - new ConditionalAction(done_executing+" && "+fpga.MOVE.verilog(ondeck.getName()), new AssignAction(ilc, "1")), + new ConditionalAction(new AndTrigger(done_executing, ondeck.testMask(fpga.MOVE)), + new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))), new ConditionalAction(done_executing, ondeck), - new ConditionalAction("!"+done_executing, - new AssignAction(ilc, - "ilc=="+magic_standing_value+"?"+magic_standing_value+":decremented")), - - new ConditionalAction(fpga.SET_OLC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(olc, "data_latch_output")), - new ConditionalAction(fpga.SET_OLC_FROM_IMMEDIATE.verilog(ondeck.getName()), - new AssignAction(olc, fpga.SET_OLC_FROM_IMMEDIATE.verilogVal(ondeck.getName()))), - new ConditionalAction(fpga.SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName()), - new AssignAction(olc, "olc==0 ? 0 : decremented")), - - new ConditionalAction(fpga.SET_OLC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(flag_z, "0")), - new ConditionalAction(fpga.SET_OLC_FROM_IMMEDIATE.verilog(ondeck.getName()), new AssignAction(flag_z, "0")), - new ConditionalAction(fpga.SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName()), new AssignAction(flag_z, "(olc==0 || olc==1)")), - - new ConditionalAction(fpga.SET_ILC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(ilc, "data_latch_output")), - new ConditionalAction(fpga.SET_ILC_FROM_IMMEDIATE.verilog(ondeck.getName()), - new AssignAction(ilc, fpga.SET_ILC_FROM_IMMEDIATE.verilogVal(ondeck.getName()))), - new ConditionalAction(fpga.SET_ILC_FROM_INFINITY.verilog(ondeck.getName()), new AssignAction(ilc, magic_standing_value)), - new ConditionalAction(fpga.SHIFT.verilog(ondeck.getName()), + new ConditionalAction(done_executing.invert(), + new AssignAction(ilc, new MuxValue(new TestValue(ilc, TestValue.TestType.EQ, magic_standing_value), + magic_standing_value, + decremented))), + new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH), + new AssignAction(olc, new SimpleValue("data_latch_output"))), + new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE), + new AssignAction(olc, ondeck.getBits(fpga.SET_OLC_FROM_IMMEDIATE))), + new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE), + new AssignAction(olc, new SimpleValue("olc==0 ? 0 : decremented"))), + + new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH), + new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0)))), + new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE), + new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0)))), + new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE), + new AssignAction(flag_z, new SimpleValue("(olc==0 || olc==1)"))), + + new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_DATA_LATCH), + new AssignAction(ilc, new SimpleValue("data_latch_output"))), + + new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_IMMEDIATE), + new AssignAction(ilc, ondeck.getBits(fpga.SET_ILC_FROM_IMMEDIATE))), + new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_INFINITY), + new AssignAction(ilc, magic_standing_value)), + new ConditionalAction(ondeck.testMask(fpga.SHIFT), new AssignAction(data_latch, - "{ data_latch_output["+(fpga.getWordWidth()-1-fpga.SHIFT.valmaskwidth)+":0], "+ - fpga.SHIFT.verilogVal(ondeck.getName())+"}")), - new ConditionalAction(fpga.SET_IMMEDIATE.verilog(ondeck.getName()), + new SimpleValue("{ data_latch_output["+(fpga.getWordWidth()-1-fpga.SHIFT.valmaskwidth)+":0], "+ + ondeck.getBits(fpga.SHIFT).getVerilog()+"}"))), + new ConditionalAction(ondeck.testMask(fpga.SET_IMMEDIATE), new AssignAction(data_latch, - "{ {"+(fpga.getWordWidth()-fpga.DataLatch_WIDTH)+ - "{"+fpga.SET_IMMEDIATE_EXTEND.verilogVal(ondeck.getName())+"}}, "+ - fpga.SET_IMMEDIATE.verilogVal(ondeck.getName())+" }")), - new ConditionalAction(fpga.SET_FLAGS.verilog(ondeck.getName()), new AssignAction(flag_a, new_flag(fpga.SET_FLAGS_A.verilogVal(ondeck.getName())))), - new ConditionalAction(fpga.SET_FLAGS.verilog(ondeck.getName()), new AssignAction(flag_b, new_flag(fpga.SET_FLAGS_B.verilogVal(ondeck.getName())))), + new SimpleValue("{ {"+(fpga.getWordWidth()-fpga.DataLatch_WIDTH)+ + "{"+ondeck.getBits(fpga.SET_IMMEDIATE_EXTEND).getVerilog()+"}}, "+ + ondeck.getBits(fpga.SET_IMMEDIATE).getVerilog()+" }"))), + new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS), + new AssignAction(flag_a, new_flag(ondeck.getBits(fpga.SET_FLAGS_A),flag_a,flag_b,flag_c))), + new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS), + new AssignAction(flag_b, new_flag(ondeck.getBits(fpga.SET_FLAGS_B),flag_a,flag_b,flag_c))), new ConditionalAction(inbox - ? "("+fpga.DI.verilog(ondeck.getName())+" || "+fpga.TI.verilog(ondeck.getName())+")" - : "(!"+fpga.DI.verilog(ondeck.getName())+" && "+fpga.TI.verilog(ondeck.getName())+")", + ? new OrTrigger(ondeck.testMask(fpga.DI), ondeck.testMask(fpga.TI)) + : new AndTrigger(ondeck.testMask(fpga.DI).invert(), ondeck.testMask(fpga.TI)), new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1))), - new ConditionalAction(fpga.DI.verilog(ondeck.getName()), data_in), - new ConditionalAction(fpga.DO.verilog(ondeck.getName()), data_out), - new ConditionalAction(fpga.FLUSH.verilog(ondeck.getName()), data_out), + new ConditionalAction(ondeck.testMask(fpga.DI), data_in), + new ConditionalAction(ondeck.testMask(fpga.DO), data_out), + new ConditionalAction(ondeck.testMask(fpga.FLUSH), data_out), inbox - ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"), fpga.FLUSH.verilog(ondeck.getName())+"?1:0") - : new ConditionalAction(fpga.DI.verilog(ondeck.getName()), new AssignAction(flag_c, data_latch_input+"["+fpga.getWordWidth()+"]")), - new ConditionalAction(fpga.TI.verilog(ondeck.getName()), token_in), - new ConditionalAction(fpga.TO.verilog(ondeck.getName()), token_out), - new ConditionalAction(fpga.DC.verilog(ondeck.getName()), new AssignAction(data_latch, data_latch_input)), - new AssignAction(new SimpleAssignable(fpga.PACKET_TOKEN.verilogVal(token_out.getName())), "("+fpga.TO.verilog(ondeck.getName())+")?1:0"), - new ConditionalAction(fpga.PATH_DATA.verilog(ondeck.getName()), - new AssignAction(new SimpleAssignable("{ "+fpga.PACKET_SIGNAL.verilogVal(token_out.getName())+", "+ - fpga.PACKET_DEST.verilogVal(token_out.getName())+" }"), - fpga.DISPATCH_PATH.verilogVal(data_latch_input))), - new ConditionalAction(fpga.PATH_IMMEDIATE.verilog(ondeck.getName()), - new AssignAction(new SimpleAssignable("{ "+fpga.PACKET_SIGNAL.verilogVal(token_out.getName())+", "+ - fpga.PACKET_DEST.verilogVal(token_out.getName())+" }"), - fpga.PATH_IMMEDIATE.verilogVal(ondeck.getName()))), + ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"), new SimpleValue(fpga.FLUSH.verilog(ondeck.getName())+"?1:0")) + : new ConditionalAction(ondeck.testMask(fpga.DI), new AssignAction(flag_c, new SimpleValue(data_latch_input.getVerilog()+"["+fpga.getWordWidth()+"]"))), + new ConditionalAction(ondeck.testMask(fpga.TI), token_in), + new ConditionalAction(ondeck.testMask(fpga.TO), token_out), + new ConditionalAction(ondeck.testMask(fpga.DC), new AssignAction(data_latch, data_latch_input)), + new AssignAction(token_out.getBits(fpga.PACKET_TOKEN), + new SimpleValue("("+fpga.TO.verilog(ondeck.getName())+")?1:0")), + new ConditionalAction(ondeck.testMask(fpga.PATH_DATA), + new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+ + token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"), + data_latch_input.getBits(fpga.DISPATCH_PATH))), + new ConditionalAction(ondeck.testMask(fpga.PATH_IMMEDIATE), + new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+ + token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"), + ondeck.getBits(fpga.PATH_IMMEDIATE))) } - ); + ); } - private String new_flag(String x) { - return "("+ - "( (("+x+" >> 0) & 1) & !flag_c) |" + - "( (("+x+" >> 1) & 1) & flag_c) |" + - "( (("+x+" >> 2) & 1) & !flag_b) |" + - "( (("+x+" >> 3) & 1) & flag_b) |" + - "( (("+x+" >> 4) & 1) & !flag_a) |" + - "( (("+x+" >> 5) & 1) & flag_a) | 0" + - ")"; + private Value new_flag(Value v, Value flag_a, Value flag_b, Value flag_c) { + Value[] vals = new Value[] { + new LogicValue(v.getBits(0,0), LogicValue.LogicType.AND, flag_c.invertBits()), + new LogicValue(v.getBits(1,1), LogicValue.LogicType.AND, flag_c), + new LogicValue(v.getBits(2,2), LogicValue.LogicType.AND, flag_b.invertBits()), + new LogicValue(v.getBits(3,3), LogicValue.LogicType.AND, flag_b), + new LogicValue(v.getBits(4,4), LogicValue.LogicType.AND, flag_a.invertBits()), + new LogicValue(v.getBits(5,5), LogicValue.LogicType.AND, flag_a), + }; + Value ret = new ConstantValue(new BitVector(1).set(0)); + for(int i=0; i ports = new LinkedHashMap(); + LinkedHashMap docklessPorts = new LinkedHashMap(); /** You should instantiate a bunch of Inboxes and Outboxes in your constructor */ public FpgaShip(Fpga fleet, ShipDescription sd) { super(fleet, sd); this.module = new Module(getType().toLowerCase()); this.instance = new Module.InstantiatedModule(fleet.getVerilogModule(), module); - for(DockDescription sdbb : sd) { - if (sdbb.isInputDock()) module.createInputPort(sdbb.getName(), getFleet().getWordWidth()+1); - else module.createOutputPort(sdbb.getName(), getFleet().getWordWidth()+1, ""); - ports.put(sdbb.getName(), new FpgaDock(this, sdbb)); + for(DockDescription sdbb : sd.ports()) { + if (sdbb.isDockless()) { + module.createOutputPort(sdbb.getName(), fleet.WIDTH_PACKET); + docklessPorts.put(sdbb.getName(), instance.getOutputPort(sdbb.getName())); + } else { + if (sdbb.isInputDock()) module.createInputPort(sdbb.getName(), getFleet().getWordWidth()+1); + else module.createOutputPort(sdbb.getName(), getFleet().getWordWidth()+1); + ports.put(sdbb.getName(), new FpgaDock(this, sdbb)); + } } for(PercolatedPort pp : sd.percolatedPorts) this.module.percolatedPorts.add(pp); diff --git a/src/edu/berkeley/fleet/fpga/FunnelModule.java b/src/edu/berkeley/fleet/fpga/FunnelModule.java index b138a9e..08f3f5e 100644 --- a/src/edu/berkeley/fleet/fpga/FunnelModule.java +++ b/src/edu/berkeley/fleet/fpga/FunnelModule.java @@ -17,7 +17,7 @@ public class FunnelModule extends Module { public FunnelModule(Fpga fpga) { super("funnel"); - Module.SinkPort outp = createOutputPort("out", fpga.WIDTH_PACKET, ""); + Module.SinkPort outp = createOutputPort("out", fpga.WIDTH_PACKET); Module.SourcePort in1p = createInputPort("in1", fpga.WIDTH_PACKET); Module.SourcePort in2p = createInputPort("in2", fpga.WIDTH_PACKET); @@ -55,7 +55,7 @@ public class FunnelModule extends Module { public void addInput(FabricElement in, Module.Port source) { throw new RuntimeException("cannot add inputs to a funnel once constructed"); } - public FpgaPath getPath(FabricElement dest, BitVector signal) { + public FpgaPath getPath(FpgaDestination dest, BitVector signal) { return out.getPath(dest, signal); } } diff --git a/src/edu/berkeley/fleet/fpga/HornModule.java b/src/edu/berkeley/fleet/fpga/HornModule.java index 83b91e2..44b8be5 100644 --- a/src/edu/berkeley/fleet/fpga/HornModule.java +++ b/src/edu/berkeley/fleet/fpga/HornModule.java @@ -27,17 +27,17 @@ public class HornModule extends Module { int bot) { super("horn"); Module.SourcePort in = createInputPort("in", top+1); - Module.SinkPort out0 = createOutputPort("out0", top+1, ""); - Module.SinkPort out1 = createOutputPort("out1", top+1, ""); + Module.SinkPort out0 = createOutputPort("out0", top+1); + Module.SinkPort out1 = createOutputPort("out1", top+1); Module.Latch out = new Module.Latch("out", top+1); - out.connect(out0); - out.connect(out1); + out0.connectValue(out); + out1.connectValue(out); Value shifted_packet = new CatValue(new Value[] { (top_of_addr_field < top) ? in.getBits(top, top_of_addr_field+1) : null, //in.getBits(bot_of_addr_field, bot_of_addr_field), // we drop address bits instead of rotating to help synthesis eliminate unused junk - new SimpleValue("1'b0"), + new ConstantValue(new BitVector(1).set(0)), in.getBits(top_of_addr_field, bot_of_addr_field+1), (bot_of_addr_field > 0) ? in.getBits(bot_of_addr_field-1, 0) : null, }); @@ -50,7 +50,7 @@ public class HornModule extends Module { public static class HornInstance extends Module.InstantiatedModule implements FabricElement { private FabricElement out0; private FabricElement out1; - public void addInput(FabricElement in, Module.Port source) { source.connect(getInputPort("in")); } + public void addInput(FabricElement in, Module.Port source) { ((Module.SourcePort)source).connect(getInputPort("in")); } public Module.SourcePort getOutputPort() { throw new RuntimeException("horn has multiple outputs"); } public Module.Port getInputPort() { return getInputPort("in"); } public HornInstance(Fpga fpga, Module thisModule, FabricElement out0, FabricElement out1) { @@ -61,7 +61,7 @@ public class HornModule extends Module { out1.addInput(this, getOutputPort("out1")); } public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); } - public FpgaPath getPath(FabricElement dest, BitVector signal) { + public FpgaPath getPath(FpgaDestination dest, BitVector signal) { FpgaPath path0 = out0==null ? null : out0.getPath(dest, signal); FpgaPath path1 = out1==null ? null : out1.getPath(dest, signal); if (path0 != null) path0 = path0.prepend(false); diff --git a/src/edu/berkeley/fleet/fpga/verilog/Verilog.java b/src/edu/berkeley/fleet/fpga/verilog/Verilog.java index 21d6179..cb1e8bd 100644 --- a/src/edu/berkeley/fleet/fpga/verilog/Verilog.java +++ b/src/edu/berkeley/fleet/fpga/verilog/Verilog.java @@ -9,74 +9,258 @@ import java.io.*; import static edu.berkeley.fleet.two.FleetTwoFleet.*; /* -=> get rid of getInputPort(String) and instead use members -=> get rid of addcrap -=> automatic width-setting/checking on ports + +- ideally: want to merge Fpga.dump() with this... but have to resolve + the handling of flushing first. + +- eliminate uses of SimpleXXX + - force width parameter in remaining uses + - re-enable width checking (add zero-extend and sign-extend) + +- ideally: make getVerilog() package-private somehow + +- change Event constructors from Object[] to Event[]/Action[] +- change portorder to LinkedHashMap + => mangle the names given for strings +=> ensure uniquification of percolated ports + +=> later: scan chain */ +/** + * Among the benefits are: + * - automatic scan-chain insertion + * - better error-checking (for example, width mismatches) than Verilog provides + * - pin percolation + * + * One of the most annoying things about Verilog is that you cannot + * "double-slice" a value; in other words, foo[10:2] is valid + * Verilog, but foo[10:2][4:3] is not; the programmer must write + * foo[4+2:3+2]. This lack of compositionality is the reason for + * most of the complexity in the Value class. + */ public class Verilog { - public static class PercolatedPort { - public static enum PortType { UP, DOWN, INOUT }; - public final String name; - public final int width; - public final PortType type; - public PercolatedPort(String name, int width, PortType type) { - this.name = name; - this.width = width; - this.type = type; - } + public static interface Value { + public String getVerilog(); + public Value getBits(int high, int low); + public Value getBits(Mask mask); + public Trigger testMask(Mask mask); + public Value invertBits(); + public int getWidth(); } public static class SimpleValue implements Value { public final String s; - public SimpleValue(String s) { this.s = s; } - public SimpleValue(String s, int high, int low) { this.s = s+"["+high+":"+low+"]"; } - public Value getBits(int high, int low) { return new SimpleValue(s, high, low); } + private final String s0; + private final int high; + private final int low; + private final int width; + public SimpleValue(String s) { this(s, -1); } + public SimpleValue(String s, int width) { + this.s = s; + this.s0 = s; + this.high = -1; + this.low = -1; + this.width = width; + } + public SimpleValue(String s, int high, int low) { + this.s = s+"["+high+":"+low+"]"; + this.s0 = s; + this.high = high; + this.low = low; + this.width = 1+high-low; + } public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); } - public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); } - public String getVerilogName() { return s; } - public String toString() { return s; } - public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); } + public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); } + public Value getBits(int high, int low) { + if (this.high==-1 && this.low==-1) return new SimpleValue(s, high, low); + if (high+this.low > this.high) throw new RuntimeException("out of range"); + return new SimpleValue(s0, high+this.low, low+this.low); + } + public String getVerilog() { return s; } + public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",width); } + public int getWidth() { + if (width==-1) throw new RuntimeException("not implemented"); + return width; + } + } + + public static class MuxValue implements Value { + private final Trigger sel; + private final Value if0; + private final Value if1; + public MuxValue(Trigger sel, Value if1, Value if0) { + this.sel = sel; + this.if0 = if0; + this.if1 = if1; + if (if0.getWidth() != if1.getWidth()) + throw new RuntimeException("width mismatch; "+if0+"="+if0.getWidth()+", "+if1+"="+if1.getWidth()); + } + public int getWidth() { return if0.getWidth(); } + public String getVerilog() { return "("+sel.getVerilogTrigger()+" ? "+if1.getVerilog()+" : "+if0.getVerilog()+")"; } + public Value getBits(int high, int low) { return new MuxValue(sel, if1.getBits(high,low), if0.getBits(high,low)); } + public Value getBits(Mask mask) { return new MuxValue(sel, if1.getBits(mask), if0.getBits(mask)); } + public Value invertBits() { return new MuxValue(sel, if1.invertBits(), if0.invertBits()); } + public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); } + } + + public static class ConstantValue implements Value { + private final BitVector bits; + public ConstantValue(BitVector bits) { this.bits = bits; } + public Value getBits(int high, int low) { return new ConstantValue(bits.get(high, low)); } + public Value getBits(Mask mask) { throw new RuntimeException("FIXME"); } + public Value invertBits() { + BitVector ret = new BitVector(bits.length()); + for(int i=0; i=0; i--) + sb.append(bits.get(i) ? '1' : '0'); + return sb.toString(); + } + public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); } + public int getWidth() { return bits.length(); } } public static class CatValue implements Value { private final Value[] values; public CatValue(Value[] values) { this.values = values; } public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); } - public Value getBits(int high, int low) { - throw new RuntimeException(); - } - public Assignable getAssignableBits(int high, int low) { - throw new RuntimeException(); + public Value getBits(int high, int low) { throw new RuntimeException(); } + public int getWidth() { + int ret = 0; + for (Value val : values) ret += val.getWidth(); + return ret; } - public String toString() { return getVerilogName(); } - public String getVerilogName() { + public String getVerilog() { StringBuffer sb = new StringBuffer(); sb.append("{ "); boolean first = true; for(int i=0; i="+v2.getVerilog()+")"; + case LT: return "("+v1.getVerilog()+"<" +v2.getVerilog()+")"; + case GT: return "("+v1.getVerilog()+">" +v2.getVerilog()+")"; + } + throw new RuntimeException("impossible"); + } + public Value getBits(int high, int low) { throw new RuntimeException("you probably didn't mean to do this"); } + public Value getBits(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); } + public Trigger testMask(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); } + public Trigger invert() { return invertMe(); } + public Value invertBits() { return invertMe(); } + private TestValue invertMe() { + switch(tt) { + case NE: return new TestValue(v1, TestType.EQ, v2); + case EQ: return new TestValue(v1, TestType.NE, v2); + case LE: return new TestValue(v1, TestType.GT, v2); + case GE: return new TestValue(v1, TestType.LT, v2); + case LT: return new TestValue(v1, TestType.GE, v2); + case GT: return new TestValue(v1, TestType.LE, v2); + } + throw new RuntimeException("impossible"); + } + public int getWidth() { return 1; } } + // Triggers ////////////////////////////////////////////////////////////////////////////// + public static interface Trigger { public String getVerilogTrigger(); public Trigger invert(); } + public static class SimpleTrigger implements Trigger { + private final String s; + public SimpleTrigger(String s) { this.s = s; } + public String getVerilogTrigger() { return s; } + public Trigger invert() { return new SimpleTrigger("!("+s+")"); } + } + + public static class AndTrigger implements Trigger { + private final Trigger t1, t2; + public AndTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; } + public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" && "+t2.getVerilogTrigger()+")"; } + public Trigger invert() { return new InvertedTrigger(this); } + } + + public static class OrTrigger implements Trigger { + private final Trigger t1, t2; + public OrTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; } + public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" || "+t2.getVerilogTrigger()+")"; } + public Trigger invert() { return new InvertedTrigger(this); } + } + public static class InvertedTrigger implements Trigger { private final Trigger original; public InvertedTrigger(Trigger original) { this.original = original; } @@ -84,74 +268,78 @@ public class Verilog { public Trigger invert() { return original; } } - public static interface Assignable { - public String getVerilogName(); - public Assignable getAssignableBits(int high, int low); + public static class ConditionalTrigger implements Trigger { + public Trigger condition; + public Trigger trigger; + public ConditionalTrigger(Trigger condition, Trigger trigger) { + this.condition = condition; + this.trigger = trigger; + } + public String getVerilogTrigger() { + return "(("+condition.getVerilogTrigger()+") ? (" + trigger.getVerilogTrigger() + ") : 1)"; + } + public Trigger invert() { return new InvertedTrigger(this); } } - public static interface Value extends Assignable { - public String getVerilogName(); - public Value getBits(int high, int low); - public Value getBits(Mask mask); - public Value invertBits(); + // Actions ////////////////////////////////////////////////////////////////////////////// + + public static interface Action { + public String getVerilogAction(); } public static class ConditionalAction implements Action { - public String condition; + public Trigger condition; public Action action; - public ConditionalAction(String condition, Action action) { + public ConditionalAction(Trigger condition, Action action) { this.condition = condition; this.action = action; } - public String toString() { return getVerilogAction(); } - public String getVerilogAction() { return "if ("+condition+") begin "+action.getVerilogAction()+" end"; } + public String getVerilogAction() { return "if ("+condition.getVerilogTrigger()+") begin "+action.getVerilogAction()+" end"; } } - public static class ConditionalTrigger implements Trigger { - public String condition; - public Trigger trigger; - public ConditionalTrigger(String condition, Trigger trigger) { - this.condition = condition; - this.trigger = trigger; - if (trigger instanceof Module.Port) - ((Module.Port)trigger).hasLatch = true; - } - public String getVerilogTrigger() { - return "&& (("+condition+") ? (1 " + trigger.getVerilogTrigger() + ") : 1)"; + public static class AssignAction implements Action { + public Assignable left; + public Value right; + public AssignAction(Assignable left, Value right) { + this.left = left; + this.right = right; } - public Trigger invert() { return new InvertedTrigger(this); } + public String getVerilogAction() { return left.getVerilog() + "<=" + right.getVerilog() + ";"; } + } + + // Assignables ////////////////////////////////////////////////////////////////////////////// + + public static interface Assignable { + public String getVerilog(); } public static class SimpleAssignable implements Assignable { public final String s; public SimpleAssignable(String s) { this.s = s; } - public String getVerilogName() { return s; } - public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); } - public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); } + public String getVerilog() { return s; } } - public static class AssignAction implements Action { - public String left; - public String right; - public AssignAction(Assignable left, Value right) { - this.left = left.getVerilogName(); - this.right = right.getVerilogName().toString(); - } - public AssignAction(Assignable left, String right) { - this.left = left.getVerilogName(); - this.right = right; - } - public String getVerilogAction() { return left + "<=" + right + ";"; } - public String toString() { return getVerilogAction(); } - } + // Percolated Ports ////////////////////////////////////////////////////////////////////////////// - public static class SimpleAction implements Action { - public final String verilog; - public SimpleAction(String verilog) { this.verilog = verilog; } - public String getVerilogAction() { return verilog; } - public String toString() { return verilog; } + /** + * A PercolatedPort is a connection to a top-level pin; it is + * propagated up or down the hierarchy + */ + public static class PercolatedPort { + public static enum PortType { UP, DOWN, INOUT }; + public final String name; + public final int width; + public final PortType type; + public PercolatedPort(String name, int width, PortType type) { + this.name = name; + this.width = width; + this.type = type; + } } + + // Module Internals ////////////////////////////////////////////////////////////////////////////// + public static class Module { public void dump(String prefix) throws IOException { PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v"))); @@ -177,53 +365,24 @@ public class Verilog { public final ArrayList portorder = new ArrayList(); public final HashMap statewires = new HashMap(); public final HashMap latches = new HashMap(); + public final HashMap wires = new HashMap(); - public StringBuffer crap = new StringBuffer(); - public StringBuffer precrap = new StringBuffer(); - //public void addCrap(String s) { crap.append(s); crap.append('\n'); } - public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); } - public void addPreCrap0(String s) { precrap.append(s); } + public Module(String name) { this.name = name; } - public Module(String name) { - this.name = name; - } + public SourcePort createInputPort(String name, int width) { return new SourcePort(name, width, true); } + public SinkPort createOutputPort(String name, int width) { return new SinkPort(name, width, true); } - public SourcePort createInputPort(String name, int width) { - if (ports.get(name)!=null) throw new RuntimeException(); - return new SourcePort(name, width, true); - } - public SourcePort getInputPort(String name) { - SourcePort ret = (SourcePort)ports.get(name); - if (ret==null) throw new RuntimeException(); - return ret; - } - public SinkPort createOutputPort(String name, int width, String resetBehavior) { - if (ports.get(name)!=null) throw new RuntimeException(); - return new SinkPort(name, width, true, resetBehavior); - } - public SinkPort createWirePort(String name, int width) { - if (ports.get(name)!=null) throw new RuntimeException(); - return new SinkPort(name, width, false, ""); - } - public SourcePort createWireSourcePort(String name, int width) { - if (ports.get(name)!=null) throw new RuntimeException(); - return new SourcePort(name, width, false); - } - public SinkPort getOutputPort(String name) { - SinkPort ret = (SinkPort)ports.get(name); - if (ret==null) throw new RuntimeException(); - return ret; - } + // Latches and Wires ////////////////////////////////////////////////////////////////////////////// public class StateWire { public final String name; public final boolean initiallyFull; public String getName() { return name; } - public Action isFull() { return new SimpleAction(name+"==1"); } - public Action isEmpty() { return new SimpleAction(name+"==0"); } - public Action doFill() { return new SimpleAction(name+"<=1;"); } - public Action doDrain() { return new SimpleAction(name+"<=0;"); } - public String doReset() { return name+"<="+(initiallyFull?"1":"0")+";"; } + public Trigger isFull() { return new SimpleTrigger("("+name+"==1)"); } + public Trigger isEmpty() { return new SimpleTrigger("("+name+"==0)"); } + public Action doFill() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(1))); } + public Action doDrain() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(0))); } + public String getResetCode() { return name+"<="+(initiallyFull?"1":"0")+";"; } public StateWire(String name) { this(name, false); } public StateWire(String name, boolean initiallyFull) { this.name = name; @@ -247,129 +406,102 @@ public class Verilog { this.initial = initial; latches.put(name, this); } - public String getVerilogName() { return name; } - public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } + public int getWidth() { return width; } + public String getVerilog() { return name; } + public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); } public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); } - public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); } - public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } - public String doReset() { return name+"<="+initial+";"; } + public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); } + public String getResetCode() { return name+"<="+initial+";"; } public void dump(PrintWriter pw) { pw.println(" reg ["+(width-1)+":0] "+name+";"); pw.println(" initial "+name+"="+initial+";"); } - public void connect(SinkPort driven) { - driven.latchDriver = this; - } + public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); } } - public abstract class Port implements Action, Assignable, Trigger { - public abstract String doReset(); + public class WireValue implements Value { public final String name; - public String getName() { return name; } public final int width; + public final Value assign; + public WireValue(String name, int width, Value assign) { + this.width = width; + this.name = name; + this.assign = assign; + wires.put(name, this); + } public int getWidth() { return width; } - public boolean hasLatch = false; - public boolean external; + public String getVerilog() { return name; } + public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); } + public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); } + public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); } + public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); } + public void dump(PrintWriter pw) { pw.println(" wire ["+(width-1)+":0] "+name+";"); } + public String getAssignments() { return " assign "+name+" = "+assign.getVerilog()+";"; } + } + + // Ports ////////////////////////////////////////////////////////////////////////////// + + public abstract class Port implements Action, Trigger { + final String name; + final int width; + final boolean external; public Port(String name, int width, boolean external) { this.width = width; this.name = name; this.external = external; + if (ports.get(name)!=null) + throw new RuntimeException("port "+name+" already exists"); ports.put(name, this); if (external) portorder.add(name); } - public String getVerilogName() { return name; } + public String getName() { return name; } + public int getWidth() { return width; } + public String getVerilog() { return name; } String getAck() { return name+"_a"; } String getReq() { return name+"_r"; } public String isFull() { return "("+name+"_r"+" && !"+name+"_a)"; } + public abstract String getResetCode(); public abstract String getInterface(); public abstract String getSimpleInterface(); public abstract String getDeclaration(); public abstract String getAssignments(); - public abstract void connect(SinkPort driven); + public abstract String getCleanup(); public Trigger invert() { return new InvertedTrigger(this); } - } - - public static class InstantiatedModule { - public final Module module; - public final Module thisModule; - public final int id; - public final HashMap ports = new HashMap(); - public String getName() { return module.getName()+"_"+id; } - public InstantiatedModule(Module thisModule, Module module) { - this.thisModule = thisModule; - this.module = module; - this.id = thisModule.id++; - thisModule.instantiatedModules.add(this); - } - public void dump(PrintWriter pw) { - pw.println(" " + module.getName() + " " + getName() + "(clk, rst "); - for(String s : module.portorder) - pw.println(", " + getPort(s).getSimpleInterface()); - for(PercolatedPort pp : module.percolatedPorts) - pw.println(" , "+pp.name); - pw.println(" );"); - } - public Port getPort(String name) { - return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name); - } - public SinkPort getInputPort(String name) { - int width = module.getPort(name).getWidth(); - SinkPort port = (SinkPort)ports.get(name); - if (port == null) { - port = thisModule.new SinkPort(getName()+"_"+name, width, false, ""); - ports.put(name, port); - } - return port; - } - public SourcePort getOutputPort(String name) { - int width = module.getPort(name).getWidth(); - SourcePort port = (SourcePort)ports.get(name); - if (port == null) { - port = thisModule.new SourcePort(getName()+"_"+name, width, false); - ports.put(name, port); - } - return port; - } + public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); } } public class SourcePort extends Port implements Value { - public SourcePort(String name, int width, boolean external) { - super(name, width, external); } - public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } + private SinkPort driven = null; + public SourcePort(String name, int width, boolean external) { super(name, width, external); } + public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); } public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); } - public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); } - public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } - public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); } + public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); } + public String getVerilogTrigger() { return getReq() + " && !"+getAck(); } public String getVerilogAction() { return getAck() + " <= 1;"; } public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; } public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; } - public String testBit(int index, boolean value) { - return "("+name+"["+index+"]=="+(value?1:0)+")"; - } + public String testBit(int index, boolean value) { return "("+name+"["+index+"]=="+(value?1:0)+")"; } public String getDeclaration() { StringBuffer sb = new StringBuffer(); if (external) { - sb.append("input " + name +"_r;\n"); - sb.append("output " + name +"_a_;\n"); - if (width>0) - sb.append("input ["+(width-1)+":0]" + name +";\n"); - else - sb.append("input [0:0]" + name +";\n"); // waste a bit, I guess + sb.append("input " + name +"_r;\n"); + sb.append("output " + name +"_a_;\n"); + sb.append("input ["+Math.max(0,width-1)+":0]" + name +";\n"); } else { - sb.append("wire " + name +"_r;\n"); - if (width>0) - sb.append("wire ["+(width-1)+":0]" + name +";\n"); + sb.append("wire " + name +"_r;\n"); + sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n"); } - if (!hasLatch) { + if (driven!=null) { sb.append("wire " + name +"_a;\n"); } else { - sb.append("reg " + name +"_a;\n"); - sb.append("initial " + name +"_a = 0;\n"); + sb.append("reg " + name +"_a;\n"); + sb.append("initial " + name +"_a = 0;\n"); } return sb.toString(); } - public String doReset() { return hasLatch ? name+"_a<=1;" : ""; } + public String getCleanup() { return driven==null ? "if (!"+getReq()+" && "+getAck()+") "+getAck()+"<=0;" : ""; } + public String getResetCode() { return driven==null ? name+"_a<=1;" : ""; } public String getAssignments() { StringBuffer sb = new StringBuffer(); if (external) @@ -377,107 +509,131 @@ public class Verilog { return sb.toString(); } public void connect(SinkPort driven) { - driven.driver = this; + if (driven.controlDriver!=null) throw new RuntimeException("driven net already has a driver"); + if (driven.latchDriver!=null) throw new RuntimeException("driven net already has a driver"); + if (this.driven!=null) throw new RuntimeException("driver already has a driven net"); + this.driven = driven; + driven.controlDriver = this; + driven.latchDriver = this; + // FIXME + // if (getWidth() != driven.getWidth()) + // throw new RuntimeException("width mismatch: " + getWidth() + " " + driven.getWidth()); } } - public class SinkPort extends Port { - public SourcePort driver = null; - public boolean forceNoLatch = false; - public SinkPort driven = null; - public Value latchDriver = null; - public boolean noDriveLatches = false; - public final String resetBehavior; - public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } + + public class SinkPort extends Port implements Assignable { + SourcePort controlDriver = null; + Value latchDriver = null; + public SinkPort(String name, int width, boolean external) { super(name, width, external); } public String getVerilogAction() { return getReq() + " <= 1;"; } - public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); } - public SinkPort(String name, int width, boolean external, String resetBehavior) { - super(name, width, external); this.resetBehavior=resetBehavior; } - public String getResetBehavior() { return resetBehavior; } + public String getVerilogTrigger() { return "!" + getReq() + " && !"+getAck(); } public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; } public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; } + public String getCleanup() { return controlDriver==null ? "if ("+getReq()+" && "+getAck()+") begin "+getReq()+"<=0; end" : ""; } + public Assignable getBits(Mask mask) { return new SimpleAssignable(name+"["+mask.valmaskmax+":"+mask.valmaskmin+"]"); } + public String getResetCode() { return controlDriver!=null ? "" : name+"_r<=0;"; } + public void connectControl(SourcePort controlDriver) { + if (this.controlDriver != null) throw new RuntimeException("attempt to connect control twice"); + this.controlDriver = controlDriver; + } + public void connectValue(Value val) { + //if (latchDriver!=null) throw new RuntimeException("attempt to re-assign via connectValue()"); + this.latchDriver = val; + // FIXME + //if (getWidth() != val.getWidth()) + //throw new RuntimeException("width mismatch: " + getWidth() + " " + val.getWidth()); + } public String getDeclaration() { StringBuffer sb = new StringBuffer(); if (external) { - sb.append("output " + name +"_r_;\n"); - sb.append("input " + name +"_a;\n"); - if (width>0) - sb.append("output ["+(width-1)+":0]" + name +"_;\n"); - else - sb.append("output [0:0]" + name +"_;\n"); // waste a bit, I guess + sb.append("output " + name +"_r_;\n"); + sb.append("input " + name +"_a;\n"); + sb.append("output ["+Math.max(0,width-1)+":0]" + name +"_;\n"); } else { sb.append("wire " + name +"_a;\n"); } - - if (forceNoLatch || latchDriver!=null) { - sb.append("reg " + name +"_r;\n"); - sb.append("initial " + name +"_r = 0;\n"); - if (width>0) - sb.append("wire ["+(width-1)+":0]" + name +";\n"); - } else if (!hasLatch) { + if (controlDriver!=null) { sb.append("wire " + name +"_r;\n"); - if (width>0) - sb.append("wire ["+(width-1)+":0]" + name +";\n"); + sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n"); } else { sb.append("reg " + name +"_r;\n"); sb.append("initial " + name +"_r = 0;\n"); - if (width>0) { - sb.append("reg ["+(width-1)+":0]" + name +";\n"); - if (!"/*NORESET*/".equals(resetBehavior)) - sb.append("initial " + name +" = 0;\n"); - } + if (latchDriver!=null) sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n"); + else sb.append("reg ["+Math.max(0,width-1)+":0]" + name +";\n"); } return sb.toString(); } - public String doReset() { - return (forceNoLatch||latchDriver!=null||width==0) - ? name+"_r<=0;" - : hasLatch - ? (name+"_r<=0; "+("/*NORESET*/".equals(resetBehavior) ? "" : (name+"<=0;"))) - : ""; - } public String getAssignments() { StringBuffer sb = new StringBuffer(); if (external) { sb.append("assign " + name +"_r_ = " + name + "_r;\n"); - if (width>0) - sb.append("assign " + name +"_ = " + name + ";\n"); + sb.append("assign " + name +"_ = " + name + ";\n"); } - if (driven != null) { - sb.append("assign " + driven.name +"_r = " + name + "_r;\n"); - sb.append("assign " + name +"_a = " + driven.name + "_a;\n"); - if (width>0) - sb.append("assign " + driven.name +" = " + name + ";\n"); - } - if (driver != null) { - sb.append("assign " + name +"_r = " + driver.name + "_r;\n"); - sb.append("assign " + driver.name +"_a = " + name + "_a;\n"); - if (width>0 && !noDriveLatches && latchDriver==null) - sb.append("assign " + name +" = " + driver.name + ";\n"); - } - if (latchDriver != null) { - if (width>0) - sb.append("assign " + name +" = " + latchDriver.getVerilogName() + ";\n"); + if (controlDriver != null) { + sb.append("assign " + name +"_r = " + controlDriver.name + "_r;\n"); + sb.append("assign " + controlDriver.name +"_a = " + name + "_a;\n"); + if (latchDriver==null) + sb.append("assign " + name +" = " + controlDriver.name + ";\n"); } + if (latchDriver != null) + sb.append("assign " + name +" = " + latchDriver.getVerilog() + ";\n"); return sb.toString(); } - public void connect(SinkPort driven) { - this.driven = driven; - throw new RuntimeException(); + } + + // InstantiatedModule ////////////////////////////////////////////////////////////////////////////// + + public static class InstantiatedModule { + public final Module module; + public final Module thisModule; + public final int id; + public final HashMap ports = new HashMap(); + public String getName() { return module.getName()+"_"+id; } + public InstantiatedModule(Module thisModule, Module module) { + this.thisModule = thisModule; + this.module = module; + this.id = thisModule.id++; + thisModule.instantiatedModules.add(this); + for(String s : module.portorder) + getPort(s); + } + public void dump(PrintWriter pw) { + pw.println(" " + module.getName() + " " + getName() + "(clk, rst "); + for(String s : module.portorder) + pw.println(", " + getPort(s).getSimpleInterface()); + for(PercolatedPort pp : module.percolatedPorts) + pw.println(" , "+pp.name); + pw.println(" );"); + } + public Port getPort(String name) { + return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name); + } + public SinkPort getInputPort(String name) { + int width = module.getPort(name).getWidth(); + SinkPort port = (SinkPort)ports.get(name); + if (port == null) { + port = thisModule.new SinkPort(getName()+"_"+name, width, false); + ports.put(name, port); + } + return port; + } + public SourcePort getOutputPort(String name) { + int width = module.getPort(name).getWidth(); + SourcePort port = (SourcePort)ports.get(name); + if (port == null) { + port = thisModule.new SourcePort(getName()+"_"+name, width, false); + ports.put(name, port); + } + return port; } } public void dump(PrintWriter pw, boolean fix) { + if (!fix) throw new RuntimeException(); boolean isRoot = name.equals("main"); pw.print("module "+name); - if (isRoot) { - pw.println("(clk_pin, rst_pin "); - } else { - pw.println("(clk, rst "); - } - for(String name : portorder) { - Port p = ports.get(name); - pw.println(" , " + p.getInterface()); - } + pw.println(isRoot ? "(clk_pin, rst_pin " : "(clk, rst "); + for(String name : portorder) pw.println(" , " + ports.get(name).getInterface()); for (InstantiatedModule im : this.instantiatedModules) for(PercolatedPort pp : im.module.percolatedPorts) if (!isRoot || (!pp.name.startsWith("root_in_") && !pp.name.startsWith("rst_"))) @@ -491,7 +647,11 @@ public class Verilog { pw.println(" wire clk;"); pw.println(" wire clk_fb;"); pw.println(" wire clk_unbuffered;"); + pw.println(" assign clk_unbuffered = clk_pin;"); + //pw.println(" assign clk = clk_pin;"); + pw.println(" BUFG GBUF_FOR_MUX_CLOCK (.I(clk_unbuffered), .O(clk));"); + /* pw.println(" DCM"); pw.println(" #("); pw.println(" .CLKFX_MULTIPLY(4),"); @@ -503,6 +663,7 @@ public class Verilog { pw.println(" .CLKFX (clk_unbuffered),"); pw.println(" .CLK0 (clk_fb)"); pw.println(" );"); + */ pw.println(" wire rst;"); } else { pw.println(" input clk;"); @@ -531,50 +692,24 @@ public class Verilog { pw.println(" assign rst_in = rst_pin;"); } - for(String name : ports.keySet()) { - Port p = ports.get(name); - pw.println(" " + p.getDeclaration()); - } - for(StateWire sw : statewires.values()) - sw.dump(pw); - for(Latch l : latches.values()) - l.dump(pw); - for(String name : ports.keySet()) { - Port p = ports.get(name); - pw.println(" " + p.getAssignments()); - } - for(InstantiatedModule m : instantiatedModules) { - m.dump(pw); - } - pw.println(precrap); + for(String name : ports.keySet()) pw.println(" " + ports.get(name).getDeclaration()); + for(StateWire sw : statewires.values()) sw.dump(pw); + for(Latch l : latches.values()) l.dump(pw); + for(WireValue wv : wires.values()) wv.dump(pw); + for(String name : ports.keySet()) pw.println(" " + ports.get(name).getAssignments()); + for(WireValue wv : wires.values()) pw.println(" " + wv.getAssignments()); + for(InstantiatedModule m : instantiatedModules) m.dump(pw); pw.println("always @(posedge clk) begin"); pw.println(" if (!rst) begin"); - for(Latch l : latches.values()) - pw.println(l.doReset()); - for(StateWire sw : statewires.values()) - pw.println(sw.doReset()); - for(Port p : ports.values()) - pw.println(p.doReset()); + for(Latch l : latches.values()) pw.println(l.getResetCode()); + for(StateWire sw : statewires.values()) pw.println(sw.getResetCode()); + for(Port p : ports.values()) pw.println(p.getResetCode()); pw.println(" end else begin"); - for(Port p : ports.values()) { - if (p instanceof SourcePort) { - SourcePort ip = (SourcePort)p; - if (ip.hasLatch) - pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;"); - } else { - SinkPort op = (SinkPort)p; - if (op.hasLatch) - pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+ - op.getReq()+"<=0; "+ - op.getResetBehavior()+" end"); - } - } + for(Port p : ports.values()) pw.println(p.getCleanup()); for(Event a : events) a.dump(pw, fix); pw.println(" begin end"); pw.println(" end"); pw.println(" end"); - - pw.println(crap); pw.println("endmodule"); } @@ -586,14 +721,12 @@ public class Verilog { Module.this.events.add(this); this.triggers = triggers; this.actions = actions; - for(int i=0; i constants = new HashMap(); DockDescription(ShipDescription ship, String name, boolean left, boolean inbox) { + this(ship, name, left, inbox, false); + } + DockDescription(ShipDescription ship, String name, boolean left, boolean inbox, boolean isDockless) { this.left = left; this.ship = ship; this.name = name; this.inbox = inbox; + this.isDockless = isDockless; } public String getName() { return name; } public boolean isInputDock() { return inbox; } public boolean isOutputDock() { return !inbox; } + public boolean isDockless() { return isDockless; } /** Indicates if this dock should be drawn on the "left hand side" of the ship for visual purposes */ boolean isLeft() { return left; } diff --git a/src/edu/berkeley/fleet/two/ShipDescription.java b/src/edu/berkeley/fleet/two/ShipDescription.java index 3c8a5ae..699d6bd 100644 --- a/src/edu/berkeley/fleet/two/ShipDescription.java +++ b/src/edu/berkeley/fleet/two/ShipDescription.java @@ -8,14 +8,18 @@ import java.util.*; public class ShipDescription implements Iterable { private String name; - private LinkedHashMap docks = new LinkedHashMap(); - private HashMap sections = new HashMap(); - private HashMap constants = new HashMap(); + private LinkedHashMap docks = new LinkedHashMap(); + private LinkedHashMap ports = new LinkedHashMap(); + private HashMap sections = new HashMap(); + private HashMap constants = new HashMap(); public String getName() { return name; } public String getSection(String sectionName) { return sections.get(sectionName); } public DockDescription getDockDescription(String name) { return docks.get(name); } public Iterator iterator() { return docks.values().iterator(); } + public Iterable ports() { + return ports.values(); + } public final LinkedList percolatedPorts = new LinkedList(); @@ -78,10 +82,12 @@ public class ShipDescription implements Iterable { String key = s.substring(0, s.indexOf(':')).trim(); boolean inbox = false; + boolean dockless = false; key = key.replaceAll(" +", " "); if (key.equals("data in")) { inbox = true; } else if (key.equals("data out")) { inbox = false; } else if (key.equals("in")) { inbox = true; } + else if (key.equals("dockless out")) { inbox = false; dockless = true; } else if (key.equals("out")) { inbox = false; } else if (key.startsWith("percolate")) { key = s; @@ -112,8 +118,9 @@ public class ShipDescription implements Iterable { String dest = val.indexOf('.') != -1 ? val.substring(val.indexOf('.')+1) : ""; p = docks.get(boxname); if (p==null) { - p = new DockDescription(this, boxname, !rightSide, inbox); - docks.put(boxname, p); + p = new DockDescription(this, boxname, !rightSide, inbox, dockless); + ports.put(boxname, p); + if (!dockless) docks.put(boxname, p); } } } diff --git a/src/edu/berkeley/fleet/util/Mask.java b/src/edu/berkeley/fleet/util/Mask.java index fa4bf24..4c1bd0d 100644 --- a/src/edu/berkeley/fleet/util/Mask.java +++ b/src/edu/berkeley/fleet/util/Mask.java @@ -38,10 +38,6 @@ public class Mask { return "("+sb.toString()+")"; //return "(("+var+" & "+allmax+"'b"+Long.toString(mask,2)+")=="+allmax+"'b"+Long.toString(val,2)+")"; } - public String verilogVal(String var) { - //return "(("+var+" & "+allmax+"'b"+Long.toString(valmask,2)+") >> "+valmaskmin+")"; - return ""+var+"["+valmaskmax+":"+valmaskmin+"]"; - } public long getval(long in) { return (in & valmask) >>> valmaskmin; -- 1.7.10.4