massive overhaul of fpga code
authormegacz <adam@megacz.com>
Tue, 30 Dec 2008 01:46:51 +0000 (17:46 -0800)
committermegacz <adam@megacz.com>
Tue, 30 Dec 2008 01:46:51 +0000 (17:46 -0800)
13 files changed:
src/edu/berkeley/fleet/fpga/FabricElement.java
src/edu/berkeley/fleet/fpga/FanoutModule.java
src/edu/berkeley/fleet/fpga/FifoModule.java
src/edu/berkeley/fleet/fpga/Fpga.java
src/edu/berkeley/fleet/fpga/FpgaDestination.java
src/edu/berkeley/fleet/fpga/FpgaDock.java
src/edu/berkeley/fleet/fpga/FpgaShip.java
src/edu/berkeley/fleet/fpga/FunnelModule.java
src/edu/berkeley/fleet/fpga/HornModule.java
src/edu/berkeley/fleet/fpga/verilog/Verilog.java
src/edu/berkeley/fleet/two/DockDescription.java
src/edu/berkeley/fleet/two/ShipDescription.java
src/edu/berkeley/fleet/util/Mask.java

index d5a4c9b..bcf44b7 100644 (file)
@@ -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(); }
+    }
+
 }
index 250f536..05bda6b 100644 (file)
@@ -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() },
index ee48cdd..0741e0c 100644 (file)
@@ -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;
     }
 }
index 7a2b410..76016db 100644 (file)
@@ -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<String,FpgaShip> ships = new LinkedHashMap<String,FpgaShip>();
@@ -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<FabricElement>();
-        ArrayList inbox_dests   = new ArrayList<FabricElement>();
-        ArrayList outbox_sources = new ArrayList<FabricElement>();
-        ArrayList outbox_dests   = new ArrayList<FabricElement>();
-        ArrayList instruction_dests   = new ArrayList<FabricElement>();
-        int numdocks = 0;
+        ArrayList dests   = new ArrayList<FabricElement>();
+        ArrayList sources = new ArrayList<FabricElement>();
         for(FpgaShip ship : (Iterable<FpgaShip>)(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<FabricElement>();
-        ArrayList sources = new ArrayList<FabricElement>();
-        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;");
index 17dbc7a..c20ccd0 100644 (file)
@@ -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();
index 2fd0b6e..f0ea9fd 100644 (file)
@@ -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<vals.length; i++)
+                ret = new LogicValue(ret, LogicValue.LogicType.OR, vals[i]);
+            return ret;
         }
     }
 }
index 82b729d..072aae4 100644 (file)
@@ -12,16 +12,22 @@ public class FpgaShip extends FleetTwoShip {
     private Module module;
     private Module.InstantiatedModule instance;
     private LinkedHashMap<String,FpgaDock> ports = new LinkedHashMap<String,FpgaDock>();
+    LinkedHashMap<String,Module.SourcePort> docklessPorts = new LinkedHashMap<String,Module.SourcePort>();
 
     /** 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);
index b138a9e..08f3f5e 100644 (file)
@@ -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);
         }
     }
index 83b91e2..44b8be5 100644 (file)
@@ -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);
index 21d6179..cb1e8bd 100644 (file)
@@ -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<bits.length(); i++) ret.set(i, !bits.get(i));
+            return new ConstantValue(ret);
+        }
+        public String getVerilog() {
+            StringBuffer sb = new StringBuffer();
+            sb.append(bits.length());
+            sb.append("'b");
+            for(int i=bits.length()-1; 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<values.length; i++) {
                 if (values[i]==null) continue;
                 if (!first) sb.append(", ");
-                sb.append(values[i].getVerilogName());
+                sb.append(values[i].getVerilog());
                 first = false;
             }
             sb.append(" }");
             return sb.toString();
         }
-        public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
+        public Value invertBits() {
+            Value[] newvals = new Value[values.length];
+            for(int i=0; i<values.length; i++)
+                newvals[i] = values[i].invertBits();
+            return new CatValue(newvals);
+        }
+        public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
     }
 
-    public static interface Action {
-        public String getVerilogAction();
+    public static class LogicValue implements Value {
+        public static enum LogicType { OR, AND };
+        private final Value v1;
+        private final Value v2;
+        private final LogicType tt;
+        public LogicValue(Value v1, LogicType tt, Value v2) {
+            this.v1 = v1;
+            this.v2 = v2;
+            this.tt = tt;
+            // FIXME: check width match
+        }
+        public String  getVerilog() {
+            switch(tt) {
+                case OR:  return "("+v1.getVerilog()+"||"+v2.getVerilog()+")";
+                case AND: return "("+v1.getVerilog()+"&&"+v2.getVerilog()+")";
+            }
+            throw new RuntimeException("impossible");
+        }
+        public Value   getBits(int high, int low) { return new LogicValue(v1.getBits(high,low),tt,v2.getBits(high,low)); }
+        public Value   getBits(Mask mask) { return new LogicValue(v1.getBits(mask),tt,v2.getBits(mask)); }
+        public Trigger testMask(Mask mask) { throw new RuntimeException("FIXME"); }
+        public Value   invertBits() { 
+            switch(tt) {
+                case OR:  return new LogicValue(v1.invertBits(), LogicType.AND, v2.invertBits());
+                case AND: return new LogicValue(v1.invertBits(), LogicType.OR, v2.invertBits());
+            }
+            throw new RuntimeException("impossible");
+        }
+        public int     getWidth() { return v1.getWidth(); }
+    }
+
+    public static class TestValue implements Value, Trigger {
+        public static enum TestType { NE, EQ, LT, GT, LE, GE };
+        private final Value v1;
+        private final Value v2;
+        private final TestType tt;
+        public TestValue(Value v1, TestType tt, Value v2) {
+            this.v1 = v1;
+            this.v2 = v2;
+            this.tt = tt;
+            // FIXME: check width match
+        }
+        public String  getVerilogTrigger() { return getVerilog(); }
+        public String  getVerilog() {
+            switch(tt) {
+                case NE: return "("+v1.getVerilog()+"!="+v2.getVerilog()+")";
+                case EQ: return "("+v1.getVerilog()+"=="+v2.getVerilog()+")";
+                case LE: return "("+v1.getVerilog()+"<="+v2.getVerilog()+")";
+                case GE: return "("+v1.getVerilog()+">="+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<String> portorder = new ArrayList<String>();
         public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
         public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
+        public final HashMap<String,WireValue> wires = new HashMap<String,WireValue>();
         
-        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<String,Port> ports = new HashMap<String,Port>();
-            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<String,Port> ports = new HashMap<String,Port>();
+            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<triggers.length; i++)
-                    if (triggers[i] instanceof Port)
-                        ((Port)triggers[i]).hasLatch = true;
             }
             public void dump(PrintWriter pw, boolean fix) {
+                if (!fix) throw new RuntimeException();
                 pw.print("if (1");
                 for(Object o : triggers) {
-                    if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
+                    if (o instanceof Trigger) pw.print(" && " + ((Trigger)o).getVerilogTrigger());
                     else                      pw.print(" && " + o);
                 }
                 pw.println(") begin ");
index eaf79d0..eccbe6e 100644 (file)
@@ -10,18 +10,24 @@ public class DockDescription {
     private final String name;
     private final boolean inbox;
     private final boolean left;
+    private final boolean isDockless;
     private final HashMap<String,ShipDescription.Constant> constants = new HashMap<String,ShipDescription.Constant>();
 
     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; }
index 3c8a5ae..699d6bd 100644 (file)
@@ -8,14 +8,18 @@ import java.util.*;
 public class ShipDescription implements Iterable<DockDescription> {
 
     private String name;
-    private LinkedHashMap<String,DockDescription> docks     = new LinkedHashMap<String,DockDescription>();
-    private HashMap<String,String>                sections  = new HashMap<String,String>();
-    private HashMap<String,Constant>              constants = new HashMap<String,Constant>();
+    private LinkedHashMap<String,DockDescription> docks         = new LinkedHashMap<String,DockDescription>();
+    private LinkedHashMap<String,DockDescription> ports = new LinkedHashMap<String,DockDescription>();
+    private HashMap<String,String>                sections      = new HashMap<String,String>();
+    private HashMap<String,Constant>              constants     = new HashMap<String,Constant>();
 
     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<DockDescription> iterator() { return docks.values().iterator(); }
+    public Iterable<DockDescription> ports() {
+        return ports.values();
+    }
 
     public final LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
 
@@ -78,10 +82,12 @@ public class ShipDescription implements Iterable<DockDescription> {
 
                 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<DockDescription> {
                 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);
                 }
             }
         }
index fa4bf24..4c1bd0d 100644 (file)
@@ -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;