massive revamp of fpga code
authoradam <adam@megacz.com>
Mon, 20 Aug 2007 06:55:23 +0000 (07:55 +0100)
committeradam <adam@megacz.com>
Mon, 20 Aug 2007 06:55:23 +0000 (07:55 +0100)
doc/archman.tex
src/edu/berkeley/fleet/slipway/Generator.java
src/edu/berkeley/fleet/slipway/Slipway.java

index 6938fc6..06798bf 100644 (file)
@@ -245,11 +245,11 @@ Normal
   \item [\tt Do] ({\bf Data Output}) emit a datum.
 
   \item [\tt To] ({\bf Token Output}) emit a token.\footnote{ {\tt To}=1,{\tt
-                 Do}=1 is invalid on outbox.}
+                 Do}=1 have special meaning on an outbox.}
 
   \item [\tt Ig] ({\bf Ignore {\tt To} Until Last Iteration}) ignore
                  the {\tt To} bit unless {\tt Count=0} \footnote{{\tt
-                 To}=0,{\tt Ig}=1 is invalid, {\tt Rq}=0,{\tt Ig}=1 is invalid}
+                 To}=0,{\tt Ig}=1 is invalid}
 
   \item [\tt Rq] ({\bf ReQueue}) if set, instructions having nonzero
                  count are ``Re-Queued'' rather than RePeated.  See
@@ -262,7 +262,7 @@ Normal
 if (Count==0) {
     discard this instruction
 } else {
-    if Count<1111111 {
+    if Count < MAX_COUNT {
       decrement count
     }
     if Rq=1 or Literal {
@@ -275,8 +275,15 @@ if (Count==0) {
 Note how a ``standing'' instruction is encoded as {\tt Count=1111111}       
 
 \item [\tt Dest] ({\bf Data/Token Destination})
-   This field is copied into the address portion of any outgoing
-   packet ({\tt Do} on an outbox or {\tt To}).
+   Normally, this field is copied into the address portion of any
+   outgoing packet ({\tt Do} on an outbox or {\tt To}).
+
+   However, in the special case of an outbox, if {\tt Do=1,To=1}, then
+   the {\it most significant} {\tt 11} bits of the value in the {\it
+   data register} are used as a destination address instead.  \footnote{This
+   functionality eliminates the need for any sort of ``{\tt Execute}''
+   ship, and lets a {\tt Fifo} ship act as an extension of the
+   instruction queue in the pump.}
 
 \end{itemize}
 
index 35b606c..32e39c8 100644 (file)
@@ -15,18 +15,102 @@ import java.io.*;
 
 public class Generator {
 
+    public static class SimpleValue implements Value {
+        private 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); }
+        public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
+        public String getVerilogName() { return s; }
+        public String toString() { return s; }
+    }
+
+    public static interface Action {
+        public String getVerilogAction();
+    }
+
+    public static interface Trigger {
+        public String getVerilogTrigger();
+    }
+
+    public static interface Assignable {
+        public String getVerilogName();
+        public Assignable getAssignableBits(int high, int low);
+    }
+
+    public static interface Value extends Assignable {
+        public String getVerilogName();
+        public Value getBits(int high, int low);
+    }
+
+    public static class ConditionalAction implements Action {
+        private String condition;
+        private Action action;
+        public ConditionalAction(String 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 static class ConditionalTrigger implements Trigger {
+        private String condition;
+        private 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 SimpleAssignable implements Assignable {
+        private 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 static class AssignAction implements Action {
+        private String left;
+        private 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(); }
+    }
+    
+    public static class SimpleAction implements Action {
+        private final String verilog;
+        public SimpleAction(String verilog) { this.verilog = verilog; }
+        public String getVerilogAction() { return verilog; }
+        public String toString() { return verilog; }
+    }
 
     public static class Module {
         private int id = 0;
         private final String name;
         public String getName() { return name; }
+        public Port getPort(String name) { return ports.get(name); }
 
         private HashSet<InstantiatedModule> instantiatedModules = new HashSet<InstantiatedModule>();
-        private final ArrayList<Action> actions = new ArrayList<Action>();
+        private final ArrayList<Event> events = new ArrayList<Event>();
 
         // FIXME: always-alphabetical convention?
         private final HashMap<String,Port> ports = new HashMap<String,Port>();
         private final ArrayList<String> portorder = new ArrayList<String>();
+        private final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
+        private final HashMap<String,Latch> latches = new HashMap<String,Latch>();
         
         private StringBuffer crap = new StringBuffer();
         private StringBuffer precrap = new StringBuffer();
@@ -37,26 +121,69 @@ public class Generator {
             this.name = name;
         }
 
-        public SourcePort getInputPort(String name, int width) {
+        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) ret = new SourcePort(name, width, true);
+            if (ret==null) throw new RuntimeException();
             return ret;
         }
-        public SinkPort getOutputPort(String name, int width, String resetBehavior) {
+        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 getOutputPort(String name) {
             SinkPort ret = (SinkPort)ports.get(name);
-            if (ret==null) ret = new SinkPort(name, width, true, resetBehavior);
+            if (ret==null) throw new RuntimeException();
             return ret;
         }
-        private abstract class Port {
+
+        private 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 StateWire(String name) { this(name, false); }
+            public StateWire(String name, boolean initiallyFull) {
+                this.name = name;
+                this.initiallyFull = initiallyFull;
+                statewires.put(name, this);
+            }
+            public void dump(PrintWriter pw) {
+                pw.println("  reg "+name+";");
+                pw.println("  initial "+name+"="+(initiallyFull?"1":"0")+";");
+            }
+        }
+
+        public class Latch implements Assignable, Value {
+            public final String name;
             public final int width;
+            public Latch(String name, int width) {
+                this.width = width;
+                this.name = name;
+                latches.put(name, this);
+            }
+            public String getVerilogName() { return name; }
+            public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
+            public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
+            public void dump(PrintWriter pw) {
+                pw.println("  reg ["+(width-1)+":0] "+name+";");
+                //pw.println("  initial "+name+"="+(initiallyFull?"1":"0")+";");
+            }
+        }
+
+        private abstract class Port implements Action, Assignable, Trigger {
+            public final String name;
+            public String getName() { return name; }
+            public final int width;
+            public int getWidth() { return width; }
             public boolean hasLatch = false;
-            public boolean supress = false;
-            public boolean noAssignData = false;
             public boolean external;
-            public boolean pretendDriven = false;
-            public boolean noreg = false;
             public Port(String name, int width, boolean external) {
                 this.width = width;
                 this.name = name;
@@ -65,6 +192,7 @@ public class Generator {
                 if (external)
                     portorder.add(name);
             }
+            public String getVerilogName() { return name; }
             public String getAck() { return name+"_a"; }
             public String getReq() { return name+"_r"; }
             public abstract String getInterface();
@@ -86,15 +214,14 @@ public class Generator {
             public void dump(PrintWriter pw) {
                 pw.println("  " + module.getName() + " " + getName() + "(clk");
                 for(String s : module.portorder)
-                    pw.println(", " + getPort(s, module.ports.get(s).width).getSimpleInterface());
+                    pw.println(", " + getPort(s).getSimpleInterface());
                 pw.println("   );");
             }
-            public Port getPort(String name, int width) {
-                if (module.ports.get(name) instanceof SinkPort)
-                    return getOutputPort(name, width, "");
-                return getInputPort(name, width);
+            public Port getPort(String name) {
+                return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
             }
-            public SinkPort getInputPort(String name, int width) {
+            public SinkPort getInputPort(String name) {
+                int width = module.getPort(name).getWidth();
                 SinkPort port = (SinkPort)ports.get(name);
                 if (port == null) {
                     port = new SinkPort(getName()+"_"+name, width, false, "");
@@ -102,7 +229,8 @@ public class Generator {
                 }
                 return port;
             }
-            public SourcePort getOutputPort(String name, int width, String resetBehavior) {
+            public SourcePort getOutputPort(String name) {
+                int width = module.getPort(name).getWidth();
                 SourcePort port = (SourcePort)ports.get(name);
                 if (port == null) {
                     port = new SourcePort(getName()+"_"+name, width, false);
@@ -112,10 +240,14 @@ public class Generator {
             }
         }
 
-        private class SourcePort extends Port {
+        private class SourcePort extends Port implements Value {
             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(getVerilogName(), high, low); }
+            public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
+            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 getDeclaration() {
@@ -138,9 +270,8 @@ public class Generator {
             }
             public String getAssignments() {
                 StringBuffer sb = new StringBuffer();
-                if (external && !pretendDriven) {
+                if (external)
                     sb.append("assign " +                 name +"_a_ = " + name + "_a;\n");
-                }
                 if (driven != null) {
                     sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
                     sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
@@ -154,6 +285,9 @@ public class Generator {
         }
         private class SinkPort extends Port {
             public final String resetBehavior;
+            public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
+            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; }
@@ -174,20 +308,16 @@ public class Generator {
                 } else {
                     sb.append("reg "    +                  name +"_r;\n");
                     sb.append("initial " +                 name +"_r = 0;\n");
-                    if (!noreg) {
-                        sb.append("reg    ["+(width-1)+":0]" + name +";\n");
-                        sb.append("initial " +                 name +" = 0;\n");
-                    }
+                    sb.append("reg    ["+(width-1)+":0]" + name +";\n");
+                    sb.append("initial " +                 name +" = 0;\n");
                 }
                 return sb.toString();
             }
             public String getAssignments() {
                 StringBuffer sb = new StringBuffer();
-                if (external && !pretendDriven) {
+                if (external) {
                     sb.append("assign " +                  name +"_r_ = " + name + "_r;\n");
-                    if (!noAssignData) {
-                        sb.append("assign " +                  name +"_ = " + name + ";\n");
-                    }
+                    sb.append("assign " +                  name +"_ = " + name + ";\n");
                 }
                 return sb.toString();
             }
@@ -207,6 +337,10 @@ public class Generator {
                 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());
@@ -219,18 +353,18 @@ public class Generator {
             for(Port p : ports.values()) {
                 if (p instanceof SourcePort) {
                     SourcePort ip = (SourcePort)p;
-                    if (ip.hasLatch && !ip.supress)
+                    if (ip.hasLatch)
                         pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
                 } else {
                     SinkPort op = (SinkPort)p;
-                    if (op.hasLatch && !op.supress)
+                    if (op.hasLatch)
                         pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
                                    op.getReq()+"<=0; "+
                                    op.getResetBehavior()+" end");
                 }
             }
 
-            for(Action a : actions) a.dump(pw);
+            for(Event a : events) a.dump(pw);
             pw.println(" begin end");
             pw.println("end");
 
@@ -238,49 +372,26 @@ public class Generator {
             pw.println("endmodule");
         }
 
-        private class Action {
-            private String[]  triggers;
-            private SourcePort[]  inports;
-            private SinkPort[] outports;
+        private class Event {
+            private Object[]  triggers;
             private Object[]  actions;
-            public Action(Object[] triggers, String action) { this(triggers, new Object[] { action }); }
-            public Action(Object[] triggers, Object[] actions) {
-                int numtriggers = 0;
-                int numinports = 0;
-                int numoutports = 0;
-                Module.this.actions.add(this);
+            public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
+            public Event(Object[] triggers, Object[] actions) {
+                Module.this.events.add(this);
+                this.triggers = triggers;
+                this.actions = actions;
                 for(int i=0; i<triggers.length; i++)
-                    if (triggers[i] instanceof String) numtriggers++;
-                    else if (triggers[i] instanceof SourcePort) {
-                        numinports++;
-                        ((Port)triggers[i]).hasLatch = true;
-                    } else if (triggers[i] instanceof SinkPort) {
-                        numoutports++;
+                    if (triggers[i] instanceof Port)
                         ((Port)triggers[i]).hasLatch = true;
-                    }
-                this.triggers = new String[numtriggers];
-                this.inports = new SourcePort[numinports];
-                this.outports = new SinkPort[numoutports];
-                for(int i=0; i<triggers.length; i++)
-                    if (triggers[i] instanceof String)       this.triggers[--numtriggers] = (String)triggers[i];
-                    else if (triggers[i] instanceof SourcePort)  this.inports[--numinports]  = (SourcePort)triggers[i];
-                    else if (triggers[i] instanceof SinkPort) this.outports[--numoutports] = (SinkPort)triggers[i];
-                this.actions = actions;
-                for(Object o : actions)
-                    if (o instanceof SourcePort) ((Port)o).hasLatch = true;
-                    else if (o instanceof SinkPort) ((Port)o).hasLatch = true;
             }
             public void dump(PrintWriter pw) {
                 pw.print("if (1");
-                for(String  s  : triggers)  pw.print(" && " + s);
-                for(SourcePort  ip : inports)   pw.print(" && " + ip.getReq() + " && !"+ip.getAck());
-                for(SinkPort op : outports)  pw.print(" && !" + op.getReq() + " && !"+op.getAck());
-                pw.println(") begin ");
-                for(Object s  : this.actions) {
-                    if (s instanceof String) pw.println(s);
-                    else if (s instanceof SourcePort) pw.println(((SourcePort)s).getAck() + " <= 1;");
-                    else if (s instanceof SinkPort) pw.println(((SinkPort)s).getReq() + " <= 1;");
+                for(Object o : triggers) {
+                    if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
+                    else                      pw.print(" && " + o);
                 }
+                pw.println(") begin ");
+                for(Object a : actions) pw.println(((Action)a).getVerilogAction());
                 pw.println("end else ");
             }
         }
@@ -288,6 +399,7 @@ public class Generator {
 
     public static final int WORD_WIDTH = 37;
     public static final int DESTINATION_WIDTH = 11;
+    public static final int COUNT_WIDTH = 7;
     public static final int PACKET_WIDTH = WORD_WIDTH + DESTINATION_WIDTH;
     public static final int INSTRUCTION_WIDTH = WORD_WIDTH;
 
@@ -302,217 +414,45 @@ public class Generator {
         Module fifostage = mkfifo("fifostage", 0, null,      prefix);
         Module fifo4     = mkfifo("fifo4",     4, fifostage, prefix);
         Module fifoship  = mkfifo("fifo",      4, fifo4,     prefix);
-        mkoutbox("outbox", false, prefix, fifo4);
-        mkoutbox("inbox", true, prefix, fifo4);
-
-        mkkill("kill", prefix);
-    }
-
-    private static Module mkkill(String name, String prefix) throws Exception {
-        Module killm = new Module(name);
-        Module.SourcePort  instr    = killm.getInputPort("instr",    INSTRUCTION_WIDTH);
-        Module.SinkPort    kill     = killm.getOutputPort("kill",    INSTRUCTION_WIDTH+1, "");
-        Module.SinkPort    notkill  = killm.getOutputPort("notkill", INSTRUCTION_WIDTH,   "");
-        killm.addPreCrap("  reg ifull;");
-        killm.addPreCrap("  initial ifull = 0;");
-        killm.new Action(new Object[] { "!ifull",           instr, notkill              },
-                         new Object[] { "notkill = instr;", instr,         "ifull = 1;" }
-                         );
-        killm.new Action(new Object[] { kill, "ifull",          "`instruction_is_kill(notkill)" },
-                         new Object[] { kill, "ifull=0;",
-                                        "kill = { `instruction_bit_kill_only_standing(notkill), `instruction_count(notkill) };" }
-                         );
-        killm.new Action(new Object[] { notkill, "ifull",          "!`instruction_is_kill(notkill)" },
-                         new Object[] { notkill, "ifull=0;" }
-                         );
-        PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
-        killm.dump(pw);
-        pw.flush();
-        return killm;
+        mkBox("outbox", false, prefix, fifo4);
+        mkBox("inbox", true, prefix, fifo4);
     }
 
     private static Module mkfunnel(String name, String prefix) throws Exception {
         Module funnel = new Module(name);
-        Module.SinkPort    out = funnel.getOutputPort("out", PACKET_WIDTH, "");
-        Module.SourcePort  in1 = funnel.getInputPort("in1", PACKET_WIDTH);
-        Module.SourcePort  in2 = funnel.getInputPort("in2", PACKET_WIDTH);
-        funnel.new Action(new Object[] { in1, out }, new Object[] { in1, out, "out  = in1;" });
-        funnel.new Action(new Object[] { in2, out }, new Object[] { in2, out, "out  = in2;" });
+        Module.SinkPort    out = funnel.createOutputPort("out", PACKET_WIDTH, "");
+        Module.SourcePort  in1 = funnel.createInputPort("in1", PACKET_WIDTH);
+        Module.SourcePort  in2 = funnel.createInputPort("in2", PACKET_WIDTH);
+        funnel.new Event(new Object[] { in1, out },
+                         new Action[] { in1, out,
+                                        new AssignAction(out, in1) });
+        funnel.new Event(new Object[] { in2, out },
+                         new Action[] { in2, out,
+                                        new AssignAction(out, in2) });
         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
         funnel.dump(pw);
         pw.flush();
         return funnel;
     }
 
-    private static Module mkoutbox(String name, boolean inbox, String prefix, Module fifo) throws Exception {
-        Module box = new Module(name);
-        Module.SourcePort instr         = box.getInputPort("instr",       INSTRUCTION_WIDTH);
-        //instr.hasLatch = true;
-        //instr.supress = true;
-        Module.SourcePort fabric_in     = box.getInputPort("fabric_in",   PACKET_WIDTH);
-        Module.SinkPort   fabric_out    = box.getOutputPort("fabric_out", PACKET_WIDTH, "");
-        fabric_out.hasLatch = true;
-        //fabric_out.supress = true;
-
-        Module.InstantiatedModule dfifo = box.new InstantiatedModule(fifo);
-        fabric_in.connect(dfifo.getInputPort("in", PACKET_WIDTH));
-        
-        Module.SourcePort dfifo_out = dfifo.getOutputPort("out", PACKET_WIDTH, "");
-        String fabric_in_d0 = dfifo_out.name;
-        String fabric_in_r0 = fabric_in_d0+"_r";
-        String fabric_in_a0 = fabric_in_d0+"_a";
-        dfifo_out.hasLatch = true;
-
-        Module.SourcePort   ship_out    = null;
-        if (!inbox) {
-            ship_out = box.getInputPort("ship",        WORD_WIDTH);
-            ship_out.hasLatch = true;
-        }
-
-        Module.SinkPort   ship_in     = null;
-        if (inbox) {
-            ship_in = box.getOutputPort("ship",        PACKET_WIDTH, "");
-            ship_in.hasLatch = true;
-        }
-
-            box.addPreCrap("  reg[(`INSTRUCTION_WIDTH-1):0] ondeck;");
-            box.addPreCrap("  reg[(`COUNT_WIDTH-1):0] repcount;");
-            box.addPreCrap("  initial ondeck=0;");
-            box.addPreCrap("  reg ondeck_full;    initial ondeck_full=0;");
-            box.addPreCrap("  reg newmayproceed;  initial newmayproceed=1;");
-            box.addPreCrap("  reg dorepeat;       initial dorepeat=0;");
-            box.addPreCrap("  reg dorepeatkill;   initial dorepeatkill=0;");
-            box.addPreCrap("  reg dokill;         initial dokill=0;");
-            box.addPreCrap("  reg clogged;        initial clogged=0;");
-
-            // FIXME: destination
-            Module.SinkPort   token_out = fabric_out;
-            Module.SourcePort token_in  = dfifo_out;
-            Module.SinkPort   data_out  = inbox ? ship_in   : fabric_out;
-            Module.SourcePort data_in   = inbox ? dfifo_out : ship_out;
-
-            Module.InstantiatedModule ififo = box.new InstantiatedModule(fifo);
-            Module.SinkPort ififo_in = ififo.getInputPort("in", PACKET_WIDTH);
-            ififo_in.hasLatch = true;
-            Module.SourcePort ififo_out = ififo.getOutputPort("out", PACKET_WIDTH, "");
-
-            // Clog (must be first)
-            box.new Action(
-                           new Object[] { ififo_out, "newmayproceed==1", "`instruction_is_clog("+ififo_out.getName()+")" },
-                           new Object[] { ififo_out, "clogged <= 1;", "newmayproceed<=0;" }
-                           );
-
-            // UnClog
-            box.new Action(
-                           new Object[] { instr, "clogged==1", "`instruction_is_unclog(instr)" },
-                           new Object[] { instr, "clogged <= 0;", "newmayproceed<=1;"  }
-                           );
-
-            // First Kill
-            box.new Action(
-                           new Object[] { instr, ififo_out, "`instruction_is_kill(instr)", "!`instruction_is_unclog(instr)", "newmayproceed==1" },
-                           new Object[] { instr, ififo_out,
-                                          "if (`instruction_count(instr)!=0)"+
-                                          "  begin repcount <= `instruction_count(instr)-1; newmayproceed <= 0; "+
-                                          "        dorepeatkill <= 1; end else begin newmayproceed<=1; end" }
-                           );
-
-            // Kill              
-            box.new Action(
-                           new Object[] { "dokill==1" },
-                           new Object[] { "dokill<=0;",
-                                          "if (`instruction_count(ondeck)!=0)"+
-                                          "  begin repcount <= `instruction_count(ondeck)-1;"+
-                                          "        dorepeatkill <= 1; end else begin newmayproceed<=1; end" }
-                           );
-
-            // RepKill
-            box.new Action(
-                           new Object[] { "dorepeatkill==1", ififo_out },
-                           new Object[] { "dorepeatkill<=0;", ififo_out, "dokill<=1;", "`instruction_count(ondeck)<=repcount;" }
-                           );
-
-            // Enqueue
-            box.new Action(
-                           new Object[] { instr, ififo_in, "!`instruction_is_kill(instr)" },
-                           new Object[] { instr, ififo_in, ififo_in.getName()+"<=instr;"  }
-                           );
-
-            // New
-            box.new Action(
-                           new Object[] { ififo_out, "ondeck_full==0", "newmayproceed==1" },
-                           new Object[] { ififo_out, "ondeck_full<=1;", "newmayproceed<=0;",
-                                          "ondeck<="+ififo_out.getName()+";"  }
-                           );
-
-            // RepeatExecute
-            box.new Action(
-                           new Object[] { "dorepeat==1", },
-                           new Object[] { "dorepeat<=0;", "ondeck_full<=1;", "`instruction_count(ondeck)<=repcount;" }
-                           );
-
-            for(int di=0; di<=1; di++)
-                for(int dout=0; dout<=1; dout++)
-                    for(int tout=0; tout<=1; tout++)
-                    for(int ti=0; ti<=1; ti++) {
-                        box.new Action(
-                                       new Object[] { "ondeck_full==1",
-                                                      data_out,
-                                                      token_out,
-                                                      ififo_in,
-                                                      (di==1 ? "" : "!")+"`instruction_bit_datain(ondeck)",
-                                                      (di==1 ? data_in : "1"),
-                                                      (ti==1 ? "" : "!")+"`instruction_bit_tokenin(ondeck)",
-                                                      (ti==1 ? token_in : "1"),
-                                                      (dout==1 ? "" : "!")+"`instruction_bit_dataout(ondeck)",
-                                                      (tout==1 ? "" : "!")+"`instruction_bit_tokenout(ondeck)"
-                                       },
-                                       new Object[] { "ondeck_full<=0;",
-                                                      "if (`instruction_count(ondeck)==1 || `instruction_bit_recycle(ondeck)) newmayproceed<=1;",
-                                                      "if (`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1) "+
-                                                      "    begin "+ififo_in.getName()+"<=ondeck; "+
-                                                      "          `instruction_count("+ififo_in.getName()+")<=(`instruction_count(ondeck)==0?0:`instruction_count(ondeck)-1);"+
-                                                      "          "+ififo_in.getReq()+"<=1; end",
-                                                      "if (!`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1) "+
-                                                      "    dorepeat <= 1;",
-                                                      "repcount <= (`instruction_count(ondeck)==0 ? 0 : (`instruction_count(ondeck)-1));",
-                                                      (di==1 ? data_in : ""),
-                                                      (dout==1 ? data_out : ""),
-                                                      (ti==1 ? token_in : ""),
-                                                      (tout==1 ? token_out : ""),
-                                                      ("if (`instruction_bit_latch(ondeck)) "+
-                                                       (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+
-                                                       "<="+
-                                                       (inbox ? "`packet_data("+data_in.getName()+")" : data_in.getName())+";"),
-                                                      (tout==1 ? "`packet_dest("+token_out.getName()+")<=`instruction_bit_dest(ondeck);" : ""),
-                                                      (dout==1 && !inbox ? "`packet_dest("+data_out.getName()+")<=`instruction_bit_dest(ondeck);" : "")
-                                       }
-                                       );
-                    }
-
-        PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
-        box.dump(pw);
-        pw.flush();
-        return box;
-    }
-
     private static Module mkfifo(String name, int len, Module instance, String prefix) throws Exception {
-        Module fifo4 = new Module(name);
-        Module.SourcePort  inx  = fifo4.getInputPort("in", PACKET_WIDTH);
-        Module.SinkPort    outx = fifo4.getOutputPort("out", PACKET_WIDTH, "");
+        Module fifo = new Module(name);
+        Module.SourcePort  in  = fifo.createInputPort("in", PACKET_WIDTH);
+        Module.SinkPort    out = fifo.createOutputPort("out", PACKET_WIDTH, "");
         Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len];
         if (len==0) {
-            fifo4.new Action(new Object[] { inx, outx }, new Object[] { inx, outx, "out  = in;" });
+            fifo.new Event(new Object[] { in, out },
+                            new Action[] { in, out, new AssignAction(out, in) });
         } else for(int i=0; i<=len; i++) {
-            if (i<len) stages[i] = fifo4.new InstantiatedModule(instance);
-            Module.SourcePort driver = i==0 ? inx : stages[i-1].getOutputPort("out", PACKET_WIDTH, "");
-            Module.SinkPort   driven = i==len ? outx : stages[i].getInputPort("in", PACKET_WIDTH);
+            if (i<len) stages[i] = fifo.new InstantiatedModule(instance);
+            Module.SourcePort driver = i==0 ? in : stages[i-1].getOutputPort("out");
+            Module.SinkPort   driven = i==len ? out : stages[i].getInputPort("in");
             driver.connect(driven);
         }
         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
-        fifo4.dump(pw);
+        fifo.dump(pw);
         pw.flush();
-        return fifo4;
+        return fifo;
     }
 
     public static void mkhorn(String name, 
@@ -522,25 +462,172 @@ public class Generator {
                               int bot_of_addr_field,
                               int bot) throws Exception {
         Module horn = new Module(name);
-        Module.SourcePort  in   = horn.getInputPort("in", PACKET_WIDTH);
-        Module.SinkPort out0 = horn.getOutputPort("out0", PACKET_WIDTH, "");
-        Module.SinkPort out1 = horn.getOutputPort("out1", PACKET_WIDTH, "");
+        Module.SourcePort in   = horn.createInputPort("in",    PACKET_WIDTH);
+        Module.SinkPort   out0 = horn.createOutputPort("out0", PACKET_WIDTH, "");
+        Module.SinkPort   out1 = horn.createOutputPort("out1", PACKET_WIDTH, "");
         String shifted_packet = "{ ";
         if (top_of_addr_field+1 < top) shifted_packet += " in["+top+":"+(top_of_addr_field+1)+"], ";
         shifted_packet += " (in["+(top_of_addr_field)+":"+bot_of_addr_field+"] >> 1) ";
         if (bot_of_addr_field > 0) shifted_packet += ",  in["+(bot_of_addr_field-1)+":0]  ";
         shifted_packet += " }";
         // same behavior as FLEET -- wait for both
-        horn.new Action(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==0)" },
-                        new Object[] { in, out0, "out0 = " + shifted_packet + ";" });
-        horn.new Action(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==1)" },
-                        new Object[] { in, out1, "out1 = " + shifted_packet + ";" });
-
+        horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==0)" },
+                       new Action[] { in, out0, new AssignAction(out0, shifted_packet) });
+        horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==1)" },
+                       new Action[] { in, out1, new AssignAction(out1, shifted_packet) });
         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
         horn.dump(pw);
         pw.flush();
     }
 
+    private static Module mkBox(String name, boolean inbox, String prefix, Module fifo) throws Exception {
+        Module box = new Module(name);
+        Module.SourcePort instr         = box.createInputPort("instr",       INSTRUCTION_WIDTH);
+        Module.SourcePort fabric_in     = box.createInputPort("fabric_in",   PACKET_WIDTH);
+        Module.SinkPort   fabric_out    = box.createOutputPort("fabric_out", PACKET_WIDTH, "");
+        Module.InstantiatedModule dfifo = box.new InstantiatedModule(fifo);
+        fabric_in.connect(dfifo.getInputPort("in"));
+        
+        Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
+        Module.SourcePort   ship_out    = null;
+        if (!inbox) {
+            ship_out = box.createInputPort("ship",        WORD_WIDTH);
+            ship_out.hasLatch = true;
+        }
+
+        Module.SinkPort   ship_in     = null;
+        if (inbox) {
+            ship_in = box.createOutputPort("ship",        PACKET_WIDTH, "");
+            ship_in.hasLatch = true;
+        }
+
+        Module.Latch     ondeck         = box.new Latch("ondeck", INSTRUCTION_WIDTH);
+        Module.Latch     repcount       = box.new Latch("repcount", COUNT_WIDTH);
+        Module.StateWire ondeckFull     = box.new StateWire("ondeck_full");
+        Module.StateWire newMayProceed  = box.new StateWire("newmayproceed", true);
+        Module.StateWire doRepeat       = box.new StateWire("dorepeat", false);
+        Module.StateWire doRepeatKill   = box.new StateWire("dorepeatkill", false);
+        Module.StateWire doKill         = box.new StateWire("dokill", false);
+        Module.StateWire isClogged      = box.new StateWire("clogged", false);
+        
+        Module.SinkPort   token_out     = fabric_out;
+        Module.SourcePort token_in      = dfifo_out;
+        Module.SinkPort   data_out      = inbox ? ship_in   : fabric_out;
+        Module.SourcePort data_in       = inbox ? dfifo_out : ship_out;
+
+        Module.InstantiatedModule ififo = box.new InstantiatedModule(fifo);
+        Module.SinkPort   ififo_in      = ififo.getInputPort("in");
+        Module.SourcePort ififo_out     = ififo.getOutputPort("out");
+
+        Value instruction_count_ondeck        = ondeck  .getBits(1+DESTINATION_WIDTH+COUNT_WIDTH-1, 1+DESTINATION_WIDTH);
+        Value instruction_count_instr         = instr   .getBits(1+DESTINATION_WIDTH+COUNT_WIDTH-1, 1+DESTINATION_WIDTH);
+        Assignable instruction_count_ififo_in = ififo_in.getAssignableBits(1+DESTINATION_WIDTH+COUNT_WIDTH-1, 1+DESTINATION_WIDTH);
+
+        // Clog (must be first)
+        box.new Event(
+                      new Object[] { ififo_out, newMayProceed.isFull(), "`instruction_is_clog("+ififo_out.getName()+")" },
+                      new Action[] { ififo_out, isClogged.doFill(), newMayProceed.doDrain() }
+                      );
+
+        // UnClog
+        box.new Event(
+                      new Object[] { instr, isClogged.isFull(), "`instruction_is_unclog(instr)" },
+                      new Action[] { instr, isClogged.doDrain(), newMayProceed.doFill()  }
+                      );
+
+        // First Kill
+        box.new Event(
+                      new Object[] { instr, ififo_out,
+                                     "`instruction_is_kill(instr)",
+                                     "!`instruction_is_unclog(instr)",
+                                     newMayProceed.isFull() },
+                      new Action[] { instr, ififo_out,
+                                     new ConditionalAction("`instruction_count(instr)!=0", new AssignAction(repcount, instruction_count_instr+"-1")),
+                                     new ConditionalAction("`instruction_count(instr)!=0", doRepeatKill.doFill()),
+                                     new ConditionalAction("`instruction_count(instr)!=0", newMayProceed.doDrain()),
+                                     new ConditionalAction("`instruction_count(instr)==0", newMayProceed.doFill())
+                      });
+
+        // Kill              
+        box.new Event(
+                      new Object[] { doKill.isFull() },
+                      new Action[] { doKill.doDrain(),
+                                     new ConditionalAction("`instruction_count(instr)!=0", new AssignAction(repcount, instruction_count_instr+"-1")),
+                                     new ConditionalAction("`instruction_count(instr)!=0", doRepeatKill.doFill()),
+                                     new ConditionalAction("`instruction_count(instr)==0", newMayProceed.doFill())
+                      });
+
+        // RepKill
+        box.new Event(
+                      new Object[] { doRepeatKill.isFull(), ififo_out },
+                      new Action[] { doRepeatKill.doDrain(), ififo_out, doKill.doFill(),
+                                     new AssignAction(instruction_count_ondeck, repcount) }
+                      );
+
+        // Enqueue
+        box.new Event(
+                      new Object[] { instr, ififo_in, "!`instruction_is_kill(instr)" },
+                      new Action[] { instr, ififo_in, new AssignAction(ififo_in, instr)  }
+                      );
+
+        // New
+        box.new Event(
+                      new Object[] { ififo_out, ondeckFull.isEmpty(), newMayProceed.isFull() },
+                      new Action[] { ififo_out, ondeckFull.doFill(), newMayProceed.doDrain(),
+                                     new AssignAction(ondeck, ififo_out)  }
+                      );
+
+        // RepeatExecute
+        box.new Event(
+                      new Object[] { doRepeat.isFull() },
+                      new Action[] { doRepeat.doDrain(),
+                                     ondeckFull.doFill(),
+                                     new AssignAction(instruction_count_ondeck, repcount) }
+                      );
+
+        Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")");
+        String data_latch_input = inbox ? "`packet_data("+data_in.getName()+")" : data_in.getName();
+        box.new Event(
+                      new Object[] { ondeckFull.isFull(),
+                                     data_out,
+                                     token_out,
+                                     ififo_in,
+                                     new ConditionalTrigger("`instruction_bit_datain(ondeck)", data_in),
+                                     new ConditionalTrigger("`instruction_bit_tokenin(ondeck)", token_in)
+                              },
+                              new Action[] { new SimpleAction("ondeck_full<=0;"),
+                                             new ConditionalAction("`instruction_count(ondeck)==1 || `instruction_bit_recycle(ondeck)", newMayProceed.doFill()),
+                                             new ConditionalAction("`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1",
+                                                                   new AssignAction(ififo_in, ondeck)),
+                                             new ConditionalAction("`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1 && `instruction_count(ondeck)==0",
+                                                                   new AssignAction(instruction_count_ififo_in, "0")),
+                                             new ConditionalAction("`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1 && `instruction_count(ondeck)!=0",
+                                                                   new AssignAction(instruction_count_ififo_in, instruction_count_ondeck+"-1")),
+                                             new ConditionalAction("`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1", ififo_in),
+                                             new ConditionalAction("!`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1", doRepeat.doFill()),
+                                             new ConditionalAction("`instruction_count(ondeck)==0", new AssignAction(repcount, "0")),
+                                             new ConditionalAction("`instruction_count(ondeck)!=0", new AssignAction(repcount, instruction_count_ondeck+"-1")),
+                                             new ConditionalAction("`instruction_bit_datain(ondeck)", data_in),
+                                             new ConditionalAction("`instruction_bit_dataout(ondeck)", data_out),
+                                             new ConditionalAction("`instruction_bit_tokenin(ondeck)", token_in),
+                                             new ConditionalAction("`instruction_bit_tokenout(ondeck)", token_out),
+                                             new ConditionalAction("`instruction_bit_latch(ondeck)", new AssignAction(data_latch, data_latch_input)),
+                                             new ConditionalAction("`instruction_bit_tokenout(ondeck)",
+                                                                   new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"),
+                                                                                    "`instruction_bit_dest(ondeck)")),
+                                             new ConditionalAction("`instruction_bit_dataout(ondeck)",
+                                                                   inbox ? new SimpleAction("")
+                                                                   : new AssignAction(new SimpleAssignable("`packet_dest("+data_out.getName()+")"),
+                                                                                      "`instruction_bit_dest(ondeck)"))
+                              }
+                              );
+
+        PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
+        box.dump(pw);
+        pw.flush();
+        return box;
+    }
+
 }
 
 
index cdad214..8f3da87 100644 (file)
@@ -43,7 +43,7 @@ public class Slipway extends Fleet {
 
         // above is the minimal ship set needed to run the regression suite
         // below are extra bonush ships
-
+        /*
         createShip("Alu2",    "alu2b");
         createShip("Alu2",    "alu2c");
         createShip("Alu2",    "alu2d");
@@ -52,6 +52,7 @@ public class Slipway extends Fleet {
         createShip("Choice",    "Choice");
         createShip("Choice",    "Choice");
         createShip("Choice",    "Choice");
+        */
         dumpFabric(true);
     }