Break Fpga.java into separate subclasses for ML509.Large, ML509.Small, and Bee2
[fleet.git] / src / edu / berkeley / fleet / interpreter / Interpreter.java
1 package edu.berkeley.fleet.interpreter;
2 import java.io.*;
3 import java.util.*;
4 import java.util.concurrent.*;
5 import java.lang.reflect.*;
6 import edu.berkeley.sbp.util.ANSI;
7 import edu.berkeley.fleet.api.*;
8 import edu.berkeley.fleet.two.*;
9 import edu.berkeley.fleet.assembler.*;
10 import edu.berkeley.fleet.util.*;
11
12 public class Interpreter extends FleetTwoFleet {
13
14     /** used to allocate serial numbers; see InterpreterDestination for further detail */
15     int maxAllocatedDestinationSerialNumber = 0;
16
17     private InterpreterShip debugShip = null;
18     private BlockingQueue<BitVector> debugStream = new LinkedBlockingQueue<BitVector>();
19     private LinkedHashMap<String,InterpreterShip> ships = new LinkedHashMap<String,InterpreterShip>();
20     public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)ships.values().iterator(); }
21     public Ship getShip(String type, int ordinal) {
22         for(Ship s : this)
23             if (s.getType().equals(type))
24                 if (ordinal-- <= 0)
25                     return s;
26         return null;
27     }
28
29     /** do not use this; it is going to go away */
30     public Interpreter() { this(true); }
31     public Interpreter(boolean logging) {
32         this(new String[] {
33                 "Debug",
34                 "Memory",
35                 "Memory",
36                 "Memory",
37                 "Alu",
38                 "Alu",
39                 "Alu",
40                 "Alu",
41                 "Alu",
42                 "Alu",
43                 "Alu",
44                 "Fifo",
45                 "Fifo",
46                 "Counter",
47                 "Counter",
48                 "Counter",
49                 "Counter",
50                 "Counter",
51                 "Counter",
52                 "Counter",
53                 "Counter",
54                 "Counter",
55                 "Counter",
56                 "Counter",
57                 "Counter",
58                 "Counter",
59                 "Counter",
60                 "Lut3",
61                 "CarrySaveAdder",
62                 "Rotator",
63                 "Dvi",
64                 "Button",
65                 "Timer",
66             }, logging);
67     }
68
69     public Interpreter(String[] ships, boolean logging) {
70         int i=0;
71         Log.quiet = !logging;
72         for(String s : ships) {
73             try {
74                 createShip(ships[i], ships[i]+"_"+i);
75             } catch (Exception e) {
76                 System.err.println(e);
77             }
78             i++;
79         }
80     }
81
82     private Ship createShip(String shipType, String shipname) {
83         try {
84             if (ships.get(shipname)!=null) return ships.get(shipname);
85             Class c = Class.forName("edu.berkeley.fleet.interpreter."+shipType);
86             Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class, ShipDescription.class });
87             String src = "/ships/" + shipType + ".ship";
88             InputStream is = getClass().getResourceAsStream(src);
89             BufferedReader br = new BufferedReader(new InputStreamReader(is));
90             ShipDescription sd = new ShipDescription(this, shipType, br);
91             InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname, sd });
92             ships.put(shipname, ret);
93             if (shipType.equals("Debug") && debugShip == null)
94                 debugShip = ret;
95             return ret;
96         } catch (Exception e) {
97             throw new RuntimeException(e);
98         }
99     }
100
101     void debug(long d) { debug(new BitVector(getWordWidth()).set(d)); }
102     void debug(BitVector data) {
103         try {
104             if (debugStream != null) debugStream.put(data);
105             else Log.println(ANSI.invert("   DEBUG: got a datum: " +  data+ANSI.clreol()));
106         } catch (Exception e) {
107             throw new RuntimeException(e);
108         }
109     }
110
111     // Instruction Encoding /////////////////////////////////////////////////////////////////////////
112
113     public BitVector getDestAddr(Path path) {
114         long ret = ((InterpreterDestination)path.getDestination()).getSerialNumber();
115         BitVector sig = path.getSignal();
116         BitVector bv = new BitVector(DISPATCH_PATH.valmaskwidth+1);
117         bv.set(ret);
118         if (sig != null) {
119             if (sig.length() > 1) throw new RuntimeException("signal was " + sig.length() + " bits long!");
120             if (sig.length() > 0 && sig.get(0)) bv.set(bv.length()-1,true);
121         }
122         return bv;
123     }
124
125
126     // ShipDescription //////////////////////////////////////////////////////////////////////////////
127
128     public void expand(ShipDescription sd) {
129         try {
130             String filename = sd.getName();
131             //String filename = (sd.getName().charAt(0)+"").toUpperCase() + sd.getName().substring(1).toLowerCase();
132             File outf = new File("build/java/edu/berkeley/fleet/interpreter/"+filename+".java");
133             new File(outf.getParent()).mkdirs();
134             System.err.println("writing to " + outf);
135             FileOutputStream out = new FileOutputStream(outf);
136             PrintWriter pw = new PrintWriter(out);
137
138             pw.println("package edu.berkeley.fleet.interpreter;");
139             pw.println("import edu.berkeley.sbp.util.ANSI;");
140             pw.println("import edu.berkeley.fleet.api.*;");
141             pw.println("import edu.berkeley.fleet.two.*;");
142             pw.println("import edu.berkeley.fleet.*;");
143             pw.println("import java.util.*;");
144             pw.println("import java.io.*;");
145             pw.println("");
146             pw.println("public class "+filename+" extends InterpreterShip {");
147             pw.println("");
148             pw.println("    public "+filename+"(Interpreter fleet, String name, ShipDescription sd) {");
149             pw.println("       super(fleet, sd);");
150             pw.println("    }");
151             pw.println("");
152             for(DockDescription b : sd) {
153                 String name = b.getName();
154                 pw.print("    InterpreterDock box_");
155                 pw.print(name);
156                 pw.print(" = new InterpreterDock(this, shipDescription.getDockDescription(\""+name+"\"));");
157             }
158             pw.println("");
159             pw.println(sd.getSection("fleeterpreter"));
160             pw.println("}");
161             pw.flush();
162             pw.close();
163         } catch (Exception e) { throw new RuntimeException(e); }
164     }
165
166     // Run //////////////////////////////////////////////////////////////////////////////
167
168     public FleetProcess run(final Instruction[] instructions) {
169         InterpreterProcess ip = initialize(instructions);
170         Thread ipt = new Thread(ip);
171         ipt.setDaemon(true);
172         ipt.start();
173         return ip;
174     }
175
176     public InterpreterProcess initialize(Instruction[] instr) {
177         return new InterpreterProcess(instr);
178     }
179
180     public class InterpreterProcess extends FleetProcess implements Runnable {
181         private Instruction[] instructions;
182         public synchronized void sendWord(Destination d, BitVector word) { sendWord(d, word, null); }
183         public synchronized void sendWord(Destination d, BitVector word, BitVector signal) {
184             InterpreterPath path = (InterpreterPath)debugShip.getDock("in").getPath(d, signal==null?new BitVector(1):signal);
185             new Packet(path, word, false).send();
186         }
187         public synchronized void sendToken(Destination d) {
188             InterpreterPath path = (InterpreterPath)debugShip.getDock("in").getPath(d, new BitVector(1));
189             new Packet(path, new BitVector(getWordWidth()), true).send();
190         }
191         public InterpreterProcess(Instruction[] instructions) {
192             this.instructions = instructions;
193             for(Instruction i : instructions)
194                 sendInstruction(i);
195         }
196         public Fleet getFleet() { return Interpreter.this; }
197         public synchronized void sendInstruction(Instruction i) {
198             long il = writeInstruction(i, debugShip.getDock("in"));
199             Path path = debugShip.getDock("in").getPath(i.dock.getInstructionDestination(), null);
200             new Packet((InterpreterPath)path, new BitVector(getWordWidth()).set(il), false).send();
201         }
202         public Dock getDebugInputDock() { return debugShip.getDock("in"); }
203         public BitVector recvWord() {
204             try {
205                 return debugStream.take();
206             } catch (Exception e) { throw new RuntimeException(e); }
207         }
208         protected void _terminate() { }
209         public void run() {
210             try {
211                 long lastStatus = System.currentTimeMillis();
212                 while(!isTerminated()) {
213                     flush();
214                     long now = System.currentTimeMillis();
215                     if (now - lastStatus > 2000 && !Log.quiet &&
216                         !"false".equals(System.getProperty("fleet.log.state","false"))) {
217                         System.out.println("== State Dump ===================================================");
218                         for(InterpreterShip ship : ships.values())
219                             for(Dock d : ship)
220                                 synchronized(this) {
221                                     ((InterpreterDock)d).dumpState();
222                                 }
223                         lastStatus = now;
224                     }
225                 }
226                 for(InterpreterShip ship : ships.values())
227                     ship.reset();
228                 debugStream.clear();
229             } catch (Exception e) {
230                 if (isTerminated()) return;
231                 throw new RuntimeException(e);
232             }
233         }
234
235         public void flush() {
236             // FIXME: should this run until we detect some sort of "quiescence"?  OTOH that might never happen.
237             for(InterpreterShip ship : ships.values())
238                 for(int j=0; j<10; j++)
239                     if (!isTerminated())
240                         synchronized(this) {
241                             ship._service();
242                         }
243         }
244
245         public synchronized void step(Dock d) {
246             ((InterpreterDock)d).service();
247         }
248         
249         public synchronized void step(Ship s) {
250             ((InterpreterShip)s).service();
251         }
252
253     }
254 }