performance improvements in Verilog.java
[fleet.git] / src / edu / berkeley / fleet / fpga / verilog / Verilog.java
index 1393c55..de2bfba 100644 (file)
@@ -42,6 +42,9 @@ import static edu.berkeley.fleet.two.FleetTwoFleet.*;
  */
 public class Verilog {
 
+    public static final int FORWARD_LATENCY = 6;  // must be >=1
+    public static final int REVERSE_LATENCY = 4;  // must be >=3
+
     public static interface Value {
         public String  getVerilog();
         public Value   getBits(int high, int low);
@@ -319,25 +322,6 @@ public class Verilog {
         public String getVerilog() { return s; }
     }
 
-    // Percolated Ports //////////////////////////////////////////////////////////////////////////////
-    
-    /**
-     *  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 {
@@ -345,7 +329,7 @@ public class Verilog {
             PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
             dump(pw, true);
             pw.flush();
-            for(InstantiatedModule m : instantiatedModules)
+            for(InstantiatedModule m : instantiatedModules.values())
                 m.module.dump(prefix);
         }
         public int id = 0;
@@ -354,7 +338,7 @@ public class Verilog {
         public Port getPort(String name) { return ports.get(name); }
 
         // order matters here
-        public LinkedList<InstantiatedModule> instantiatedModules = new LinkedList<InstantiatedModule>();
+        public LinkedHashMap<String,InstantiatedModule> instantiatedModules = new LinkedHashMap<String,InstantiatedModule>();
 
         // order matters here
         public LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
@@ -504,8 +488,25 @@ public class Verilog {
             public String getResetCode() { return driven==null ? name+"_a<=1;" : ""; }
             public String getAssignments() {
                 StringBuffer sb = new StringBuffer();
-                if (external)
-                    sb.append("assign " +                 name +"_a_ = " + name + "_a;\n");
+                if (external) {
+                    int a = REVERSE_LATENCY - 3;
+                    if (a<0 || a>16) {
+                        throw new RuntimeException("cannot offer latency of " + REVERSE_LATENCY +"-3");
+                    } else if (a==0) {
+                        sb.append("assign " +                 name +"_a_ = " + name + "_a;\n");
+                    } else {
+                        a = a-1;  // CLK-to-Q gives us one cycle of latency anyways
+                        sb.append("SRL16E srl16_"+name+"_a\n");
+                        sb.append("              (.Q ("+name+"_a_),\n");
+                        sb.append("               .A0 ("+((a & (1<<0)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A1 ("+((a & (1<<1)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A2 ("+((a & (1<<2)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A3 ("+((a & (1<<3)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .CE (1),\n");
+                        sb.append("               .CLK (clk),\n");
+                        sb.append("               .D ("+name+"_a));\n");
+                    }
+                }
                 return sb.toString();
             }
             public void connect(SinkPort driven) {
@@ -566,7 +567,23 @@ public class Verilog {
             public String getAssignments() {
                 StringBuffer sb = new StringBuffer();
                 if (external) {
-                    sb.append("assign " +                  name +"_r_ = " + name + "_r;\n");
+                    int a = FORWARD_LATENCY - 1;
+                    if (a<0 || a>16) {
+                        throw new RuntimeException("cannot offer latency of " + FORWARD_LATENCY +"-1");
+                    } else if (a==0) {
+                        sb.append("assign " +                  name +"_r_ = " + name + "_r;\n");
+                    } else {
+                        a = a-1;  // CLK-to-Q gives us one cycle of latency anyways
+                        sb.append("SRL16E srl16_"+name+"_r\n");
+                        sb.append("              (.Q ("+name+"_r_),\n");
+                        sb.append("               .A0 ("+((a & (1<<0)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A1 ("+((a & (1<<1)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A2 ("+((a & (1<<2)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .A3 ("+((a & (1<<3)) == 0 ? 0 : 1)+"),\n");
+                        sb.append("               .CE (1),\n");
+                        sb.append("               .CLK (clk),\n");
+                        sb.append("               .D ("+name+"_r));\n");
+                    }
                     sb.append("assign " +                  name +"_ = " + name + ";\n");
                 }
                 if (controlDriver != null) {
@@ -588,12 +605,17 @@ public class Verilog {
             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; }
+            private final String name;
+            public String getName() { return name; }
             public InstantiatedModule(Module thisModule, Module module) {
                 this.thisModule = thisModule;
                 this.module = module;
-                this.id = thisModule.id++;
-                thisModule.instantiatedModules.add(this);
+                // CRUDE
+                int id = 0;
+                while(thisModule.instantiatedModules.get(module.getName()+"_"+id)!=null) id++;
+                this.id = id;
+                this.name = module.getName()+"_"+id;
+                thisModule.instantiatedModules.put(this.name, this);
                 for(String s : module.portorder)
                     getPort(s);
             }
@@ -634,7 +656,7 @@ public class Verilog {
             pw.print("module "+name);
             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 (InstantiatedModule im : this.instantiatedModules.values())
                 for(PercolatedPort pp : im.module.percolatedPorts)
                     if (!isRoot || (!pp.name.startsWith("root_in_") && !pp.name.startsWith("rst_")))
                         pw.println("    , "+pp.name);
@@ -670,7 +692,7 @@ public class Verilog {
                 pw.println("    input rst;");
             }
 
-            for (InstantiatedModule im : this.instantiatedModules)
+            for (InstantiatedModule im : this.instantiatedModules.values())
                 for(PercolatedPort pp : im.module.percolatedPorts) {
                     if (isRoot && (pp.name.startsWith("root_in_") || pp.name.startsWith("rst_")))
                         pw.print("wire");
@@ -698,7 +720,7 @@ public class Verilog {
             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);
+            for(InstantiatedModule m : instantiatedModules.values()) m.dump(pw);
             pw.println("always @(posedge clk) begin");
             pw.println("  if (rst) begin");
             for(Latch l : latches.values()) pw.println(l.getResetCode());