massive overhaul of FleetCode to support multiple destinations (and major cleanup)
[fleet.git] / src / edu / berkeley / fleet / slipway / Slipway.java
1 package edu.berkeley.fleet.slipway;
2 import edu.berkeley.fleet.slipway.*;
3 import edu.berkeley.fleet.doc.*;
4 import edu.berkeley.fleet.api.*;
5 import edu.berkeley.fleet.ies44.*;
6 import edu.berkeley.fleet.*;
7 import java.lang.reflect.*;
8 import edu.berkeley.sbp.chr.*;
9 import edu.berkeley.sbp.misc.*;
10 import edu.berkeley.sbp.meta.*;
11 import edu.berkeley.sbp.bind.*;
12 import edu.berkeley.sbp.util.*;
13 import java.util.*;
14 import java.io.*;
15
16 public class Slipway extends Fleet {
17
18     public ArrayList<SlipwayShip> shiplist   = new ArrayList<SlipwayShip>();
19     public HashMap<String,SlipwayShip> ships = new HashMap<String,SlipwayShip>();
20     public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)shiplist.iterator(); }
21
22     private String bitfile;
23
24     public static void main(String[] s) throws Exception {
25         new Slipway().dumpFabric(false);
26     }
27
28     public Slipway() { this("valentine.bit"); }
29     public Slipway(String bitfile) {
30         this.bitfile = bitfile;
31         createShip("Debug",   "debug");
32         createShip("Alu2",    "alu2a");
33         createShip("Alu2",    "alu2b");
34         createShip("Alu2",    "alu2c");
35         createShip("Alu2",    "alu2d");
36         createShip("Execute", "execute");
37         createShip("Fifo",    "fifo1");
38         createShip("Fifo",    "fifo2");
39         createShip("Fifo",    "fifo3");
40         createShip("Fifo",    "fifo4");
41         // FIXME cant have less than two feeding the instruction horn or BUG
42         createShip("Iscratch",  "iscratch1");
43         createShip("Iscratch",  "iscratch2");
44         createShip("Dscratch",  "dscratch1");
45         createShip("Dscratch",  "dscratch2");
46         createShip("Lut3",      "lut3");
47         createShip("Alu1",      "alu1");
48         dumpFabric(true);
49     }
50
51     public Ship createShip(String type, String name) {
52         try {
53             ShipDescription sd = new ShipDescription(new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship"))));
54             SlipwayShip ship = new SlipwayShip(this, name, type, sd);
55             ships.put(name, ship);
56             shiplist.add(ship);
57             return ship;
58         } catch (IOException e) { throw new RuntimeException(e); }
59     }
60
61     public FleetProcess run(final byte[] instructions) {
62         try {
63             return new Client(bitfile, instructions);
64         } catch (IOException e) { throw new RuntimeException(e); }
65     }
66
67     public void dumpFabric(boolean quiet) {
68         // FIXME: this is really ugly: the order of port declarations in
69         //        the XXXShip.java file must match the order in the .balsa file!
70
71         ArrayList instructionports = new ArrayList<SlipwayBenkoBox>();
72         for(SlipwayShip ship : shiplist)
73             for(BenkoBox port : ship.getBenkoBoxes())
74                 if (!((SlipwayBenkoBox)port).special())
75                     instructionports.add(port);
76         FabricTree instructions =
77             new FabricTree((SlipwayBenkoBox[])instructionports.toArray(new SlipwayBenkoBox[0]),
78                            "ihorn",
79                            "instruction");
80
81         ArrayList inputports = new ArrayList<SlipwayBenkoBox>();
82         for(SlipwayShip ship : shiplist)
83             for(BenkoBox port : ship.getBenkoBoxes())
84                 if (!((SlipwayBenkoBox)port).special())
85                     inputports.add(port);
86         FabricTree inputs =
87             new FabricTree((SlipwayBenkoBox[])inputports.toArray(new SlipwayBenkoBox[0]),
88                            "horn",
89                            "dest");
90
91         ArrayList outputports = new ArrayList<SlipwayBenkoBox>();
92         for(SlipwayShip ship : shiplist)
93             for(BenkoBox port : ship.getBenkoBoxes())
94                 if (!((SlipwayBenkoBox)port).special() || ((SlipwayBenkoBox)port).dhorn())
95                     outputports.add(port);
96         FabricTree outputs =
97             new FabricTree((SlipwayBenkoBox[])outputports.toArray(new SlipwayBenkoBox[0]),
98                            "funnel",
99                            "source");
100
101         ArrayList ihornports = new ArrayList<SlipwayBenkoBox>();
102         for(SlipwayShip ship : shiplist)
103             for(BenkoBox port : ship.getBenkoBoxes())
104                 if (((SlipwayBenkoBox)port).ihorn())
105                     ihornports.add(port);
106         FabricTree ihorns =
107             new FabricTree((SlipwayBenkoBox[])ihornports.toArray(new SlipwayBenkoBox[0]),
108                            "funnel",
109                            "ihorn");
110         
111         if (quiet) return;
112         System.out.println("`include \"macros.v\"");
113         System.out.println("module fabric(clk, data_Iscratch0_command_r, data_Iscratch0_command_a, data_Iscratch0_command,");
114         System.out.println("                   data_Debug0_out_r, data_Debug0_out_a, data_Debug0_out);");
115         System.out.println("  input  clk;");
116         System.out.println("  input  data_Iscratch0_command_r;");
117         System.out.println("  output data_Iscratch0_command_a;");
118         System.out.println("  output data_Debug0_out_r;");
119         System.out.println("  input  data_Debug0_out_a;");
120         System.out.println("  output [(`PACKET_WIDTH-1):0]      data_Debug0_out;");
121         System.out.println("  input  [(`PACKET_WIDTH-1):0]      data_Iscratch0_command;");
122         //System.out.println("  wire   [(`INSTRUCTION_WIDTH-1):0] data_Iscratch0_ihorn;");
123         //System.out.println("  wire   [(`PACKET_WIDTH-1):0]      data_Iscratch0_dhorn;");
124         System.out.println();
125         
126         System.out.println();
127
128         instructions.dumpChannels(true);
129         outputs.dumpChannels(true);
130         inputs.dumpChannels(true);
131         ihorns.dumpChannels(true);
132         for(SlipwayShip ship : shiplist)
133             for(BenkoBox port : ship.getBenkoBoxes())
134                 if (!((SlipwayBenkoBox)port).special() || ((SlipwayBenkoBox)port).dhorn())
135                     System.out.println("  wire [(`PACKET_WIDTH-1):0] data_"
136                                        +getUniqueName(ship)+"_"+port.getName()+";");
137
138         System.out.println("");
139         instructions.dumpChannels(false);
140         System.out.println("");
141         outputs.dumpChannels(false);
142         System.out.println("");
143         inputs.dumpChannels(false);
144         System.out.println("");
145         ihorns.dumpChannels(false);
146         System.out.println("");
147         for(SlipwayShip ship : shiplist) {
148             System.out.print(ship.getType().toLowerCase());
149             System.out.print(" ");
150             System.out.print("krunk"+(krunk++));
151             System.out.print("(clk, ");
152             boolean first = true;
153             for(BenkoBox port : ship.getBenkoBoxes()) {
154                 if (!first) System.out.print(", ");
155                 first = false;
156                 String prefix = "data_";
157                 if (((SlipwayBenkoBox)port).ihorn()) prefix = "ihorn_";
158                 if (((SlipwayBenkoBox)port).dhorn()) prefix = "source_";
159                 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
160                 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
161                 System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName());
162                 System.out.print(" ");
163             }
164             System.out.println(");");
165
166             for(BenkoBox port : ship.getBenkoBoxes()) {
167                 if (((SlipwayBenkoBox)port).special()) continue;
168                 if (((SlipwayBenkoBox)port).inbox) {
169                     System.out.print("inbox");
170                 } else {
171                     System.out.print("outbox");
172                 }
173                 System.out.print(" krunk"+(krunk++)+"(clk, ");
174                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
175                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
176                 System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
177                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
178                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
179                 System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
180                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
181                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
182                 System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
183                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
184                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
185                 System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
186                 System.out.print(");");
187                 System.out.println();
188             }
189
190         }
191         /*
192         System.out.println("funnel topfun(clk,"+
193                            "              dest_r, dest_a, dest,"+
194                            "              source_r, source_a, source,"+
195                            "              data_Iscratch0_dhorn_r, data_Iscratch0_dhorn_a, data_Iscratch0_dhorn);");
196         */
197         System.out.println("assign instruction_r = ihorn_r;");
198         System.out.println("assign ihorn_a = instruction_a;");
199         System.out.println("assign instruction = ihorn;");
200         System.out.println("assign dest_r = source_r;");
201         System.out.println("assign source_a = dest_a;");
202         System.out.println("assign dest = source;");
203         System.out.println("endmodule");
204     }
205
206     private static class FabricTree {
207         int master_idx = 1;
208         String prefix;
209         Node root;
210         public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); }
211         public FabricTree(SlipwayBenkoBox[] ports, String component, String prefix) {
212             this.prefix = prefix;
213             root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
214         }
215         private Object mkNode(String name, String component, SlipwayBenkoBox[] ports,
216                               int start, int end, int addr, int bits) {
217             if (end-start == 0) return null;
218             if (end-start == 1) {
219                 SlipwayBenkoBox p = ports[start];
220                 if (prefix.equals("instruction")) {
221                     p.instr_addr = addr;
222                     p.instr_bits = bits;
223                 } else if (prefix.equals("dest")) {
224                     p.addr = addr;
225                     p.bits = bits;
226                     int count = 1;
227                     for(Destination d : p.getDestinations()) {
228                         if (!(d instanceof SlipwayBenkoBox.VirtualPort)) continue;
229                         SlipwayBenkoBox.VirtualPort vp = (SlipwayBenkoBox.VirtualPort)d;
230                         vp.addr = p.addr | (count << (bits+1));
231                         count++;
232                     }
233                 }
234                 return p;
235             }
236             int len = end-start;
237             return new Node(name,
238                             component,
239                             mkNode(name+"_0", component, ports, start, start+len/2, addr, bits+1),
240                             mkNode(name+"_1", component, ports, start+len/2, end,   addr | (1 << bits), bits+1),
241                             addr,
242                             bits);
243         }
244         private String describe(String prefix, Object o) {
245             if (o==null) return null;
246             if (o instanceof SlipwayBenkoBox) {
247                 SlipwayBenkoBox p = (SlipwayBenkoBox)o;
248                 return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName();
249             }
250             if (o instanceof Node) {
251                 return ((Node)o).describe(prefix);
252             }
253             return null;
254         }
255         private class Node {
256             Object left;
257             Object right;
258             String name;
259             String component;
260             int addr;
261             int bits;
262             public Node(String name, String component, Object left, Object right, int addr, int bits) {
263                 this.left = left;
264                 this.right = right;
265                 this.name = name;
266                 this.component = component;
267                 this.addr = addr;
268                 this.bits = bits;
269             }
270             public void dumpChannels(int indentamount, boolean decl) {
271                 String indent = "";
272                 for(int i=0; i<indentamount; i++) indent += "  ";
273                 if (decl) {
274                     String n = describe(prefix).startsWith("instruction")
275                         ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
276                     System.out.println("  wire "+n+" "+indent+describe(prefix)+";");
277                 } else {
278                     System.out.println("     "+indent+
279                                        component+" "+
280                                        "krunk"+(krunk++)+"(clk, "+
281                                        describe(prefix)+"_r, "+
282                                        describe(prefix)+"_a, "+
283                                        describe(prefix)+", "+
284                                        FabricTree.this.describe(prefix, left)+"_r, "+
285                                        FabricTree.this.describe(prefix, left)+"_a, "+
286                                        FabricTree.this.describe(prefix, left)+", "+
287                                        FabricTree.this.describe(prefix, right)+"_r, "+
288                                        FabricTree.this.describe(prefix, right)+"_a, "+
289                                        FabricTree.this.describe(prefix, right)+
290                                        ");");
291                 }
292                 dumpChannels(left, indentamount+1, decl);
293                 dumpChannels(right, indentamount+1, decl);
294             }
295             public void dumpChannels(Object o, int indentamount, boolean decl) {
296                 if (o==null) return;
297                 if (o instanceof Node) {
298                     ((Node)o).dumpChannels(indentamount, decl);
299                 } else {
300                     String indent = "";
301                     for(int i=0; i<indentamount; i++) indent += "  ";
302                     if (decl) {
303                         String n = FabricTree.this.describe(prefix,o).startsWith("instruction")
304                             ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
305                         System.out.println("  wire "+n+" "+indent+FabricTree.this.describe(prefix,o)+";");
306                     }
307                 }
308             }
309             public String describe(String prefix) {
310                 return prefix+name;
311             }
312         }
313     }
314     public static int krunk=0;
315
316     private static String getUniqueName(Ship ship) {
317         return ship.getType() + ship.getOrdinal();
318     }
319
320     public void expand(ShipDescription sd) {
321         try {
322             String filename = sd.getName().toLowerCase();
323             File outf = new File("src/edu/berkeley/fleet/slipway/"+filename+".v");
324             new File(outf.getParent()).mkdirs();
325             System.err.println("writing to " + outf);
326             FileOutputStream out = new FileOutputStream(outf);
327             PrintWriter pw = new PrintWriter(out);
328
329             boolean auto = filename.equals("alu2") || filename.equals("alu1") || filename.equals("lut3");
330             if (auto) {
331                 pw.println("`include \"macros.v\"");
332                 pw.println();
333                 pw.println("module " + filename + "( clk");
334                 for(BenkoBoxDescription bb : sd) {
335                     String bb_name = bb.getName();
336                     pw.print("        ");
337                     if (bb.isInbox()) {
338                         pw.print(", " + bb_name+"_r");
339                         pw.print(", " + bb_name+"_a_");
340                         pw.print(", " + bb_name+"_d");
341                     } else {
342                         pw.print(", " + bb_name+"_r_");
343                         pw.print(", " + bb_name+"_a");
344                         pw.print(", " + bb_name+"_d_");
345                     }
346                     pw.println();
347                 }
348                 pw.println("        );");
349                 pw.println();
350                 pw.println("    input clk;");
351                 for(BenkoBoxDescription bb : sd) {
352                     String bb_name = bb.getName();
353                     pw.print("        ");
354                     if (bb.isInbox()) {
355                         pw.println("`input(" +
356                                    bb_name+"_r,  "+
357                                    bb_name+"_a,  "+
358                                    bb_name+"_a_, "+
359                                    "[(`DATAWIDTH-1):0],"+
360                                    bb_name+"_d)"
361                                    );
362                     } else {
363                         pw.println("`output(" +
364                                    bb_name+"_r,  "+
365                                    bb_name+"_r_, "+
366                                    bb_name+"_a,  "+
367                                    "[(`DATAWIDTH-1):0],"+
368                                    bb_name+"_d_)"
369                                    );
370                         pw.println("`defreg(" +
371                                    bb_name+"_d_,  "+
372                                    "[(`DATAWIDTH-1):0],"+
373                                    bb_name+"_d)"
374                                    );
375                     }
376                     pw.println();
377                 }
378             }
379
380             pw.println(sd.getSection("fpga"));
381
382             if (auto)
383                 pw.println("endmodule");
384
385             pw.flush();
386             pw.close();
387         } catch (Exception e) { throw new RuntimeException(e); }
388     }
389
390     public int computeOffset(int origin, int target) { return (target - origin)/6; }
391     public int computeTarget(int origin, int offset) { return origin + (offset*6); }
392
393     private SlipwayInstructionEncoder iie = new SlipwayInstructionEncoder();
394     public Instruction readInstruction(DataInputStream is) throws IOException { return iie.readInstruction(is); }
395     public Instruction readInstruction(long instr) { return iie.readInstruction(instr); }
396     public long writeInstruction(Instruction d) { return writeInstruction(d); }
397     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException { iie.writeInstruction(os, d); }
398
399     private class SlipwayInstructionEncoder extends InstructionEncoder {
400         public long getDestAddr(Destination box) {
401             long ret;
402             if (box instanceof SlipwayBenkoBox)
403                 ret = ((SlipwayBenkoBox)box).addr;
404             else
405                 ret = ((SlipwayBenkoBox.VirtualPort)box).addr;
406             return ret;
407         }
408         public long getBoxInstAddr(BenkoBox box) { return ((SlipwayBenkoBox)box).instr_addr; }
409         public Destination getDestByAddr(long dest) {
410             for(Ship ship : Slipway.this)
411                 for(BenkoBox bb : ship.getBenkoBoxes()) {
412                     if (((SlipwayBenkoBox)bb).addr == dest)
413                         return bb;
414                     for(Destination d : bb.getDestinations())
415                         if (getDestAddr(d)==dest)
416                             return d;
417                 }
418             return null;
419         }
420         public BenkoBox getBoxByInstAddr(long dest) {
421             for(Ship ship : Slipway.this)
422                 for(BenkoBox bb : ship.getBenkoBoxes())
423                     if (((SlipwayBenkoBox)bb).instr_addr == dest)
424                         return bb;
425             return null;
426         }
427     }
428
429 }