77605ac2bf8181723a9b2c7b5c3dab0e0bb02f5a
[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.fleet.*;
7 import edu.berkeley.fleet.doc.*;
8 import edu.berkeley.fleet.api.*;
9 import edu.berkeley.fleet.ies44.*;
10 import edu.berkeley.fleet.ships.*;
11
12 public class Interpreter extends Fleet {
13
14     /** some "halt ship" can turn this on to stop the interpreter */
15     public boolean       halt         = false;
16     public ArrayList<InterpreterShip> shiplist   = new ArrayList<InterpreterShip>();
17     public HashMap<String,InterpreterShip> ships = new HashMap<String,InterpreterShip>();
18     private BlockingQueue<Long> debugStream = new LinkedBlockingQueue<Long>();
19     public int[] mem = new int[0];
20
21
22     public void debug(long data) {
23         try {
24             if (debugStream != null) {
25                 debugStream.put(data);
26             } else {
27                 Log.println(Log.invert("   DEBUG: got a datum: " +  data+Log.clreol()));
28             }
29         } catch (Exception e) {
30             throw new RuntimeException(e);
31         }
32     }
33
34     public static class DynamicInterpreter extends Interpreter implements Fleet.WithDynamicShips {
35     }
36
37     public void expand(ShipDescription sd) {
38         try {
39             String filename = (sd.name.charAt(0)+"").toUpperCase() + sd.name.substring(1).toLowerCase();
40             File outf = new File("build/java/edu/berkeley/fleet/ships/"+filename+".java");
41             new File(outf.getParent()).mkdirs();
42             System.err.println("writing to " + outf);
43             FileOutputStream out = new FileOutputStream(outf);
44             PrintWriter pw = new PrintWriter(out);
45
46             pw.println("package edu.berkeley.fleet.ships;");
47             pw.println("import edu.berkeley.fleet.interpreter.*;");
48             pw.println("import edu.berkeley.fleet.api.*;");
49             pw.println("import edu.berkeley.fleet.*;");
50             pw.println("import java.util.*;");
51             pw.println("import java.io.*;");
52             pw.println("");
53             pw.println("public class "+filename+" extends InterpreterShip {");
54             pw.println("");
55             for(ShipDescription.BenkoBox b : sd.benkoBoxes) {
56                 if (b.ports.length != 1)
57                     throw new RuntimeException("multiple ports not supported");
58                 String name = b.ports[0];
59                 pw.print("    ");
60                 if (!b.tokenOnly &&  b.inbox) pw.print("DataInbox");
61                 if ( b.tokenOnly &&  b.inbox) pw.print("TokenInbox");
62                 if (!b.tokenOnly && !b.inbox) pw.print("DataOutbox");
63                 if ( b.tokenOnly && !b.inbox) pw.print("TokenOutbox");
64                 pw.print(" box_");
65                 pw.print(name);
66                 pw.print(" = new ");
67                 if (!b.tokenOnly &&  b.inbox) pw.print("DataInbox");
68                 if ( b.tokenOnly &&  b.inbox) pw.print("TokenInbox");
69                 if (!b.tokenOnly && !b.inbox) pw.print("DataOutbox");
70                 if ( b.tokenOnly && !b.inbox) pw.print("TokenOutbox");
71                 pw.println("(this, \""+name+"\");");
72             }
73             pw.println("");
74             pw.println("    public "+filename+"(Interpreter fleet, String name) { super(fleet, name); }");
75             pw.println("");
76             //pw.println("    public void service() {");
77             pw.println(sd.sections.get("fleeterpreter"));
78             //pw.println("}");
79             pw.println("}");
80             pw.flush();
81             pw.close();
82         } catch (Exception e) { throw new RuntimeException(e); }
83     }
84
85     public FleetProcess run(final byte[] instructions) {
86         try {
87             final FleetProcess fp = new FleetProcess() {
88                     public void invokeInstruction(Instruction i) { throw new RuntimeException("not supported"); }
89                     public long readWord() {
90                         try {
91                             return debugStream.take();
92                         } catch (Exception e) {
93                             throw new RuntimeException(e);
94                         } }
95                     protected void _terminate() {
96                         shiplist   = new ArrayList<InterpreterShip>();
97                         ships = new HashMap<String,InterpreterShip>();
98                         debugStream = new LinkedBlockingQueue<Long>();
99                         mem = new int[0];
100                     }
101                 };
102             new Thread() {
103                 public void run() {
104                     try {
105                         go(fp, instructions);
106                     } catch (Exception e) {
107                         throw new RuntimeException(e);
108                     }
109                 }
110             }.start();
111             return fp;
112         } catch (Exception e) {
113             throw new RuntimeException(e);
114         }
115     }
116
117     public void go(FleetProcess fp, byte[] instructions) {
118         try {
119             // find the first icache
120             InterpreterShip iscratch = null;
121             for(Ship ship : this)
122                 if (ship.getClass().getSimpleName().equals("Iscratch")) {
123                     iscratch = (InterpreterShip)ship;
124                     break;
125                 }
126             if (iscratch==null)
127                 iscratch = (InterpreterShip)Class.forName("edu.berkeley.fleet.ships.Iscratch")
128                     .getConstructor(new Class[] { Interpreter.class, String.class })
129                     .newInstance(new Object[] { this, "iscratch" });
130             iscratch
131                 .getClass()
132                 .getMethod("boot", new Class[] { byte[].class })
133                 .invoke(iscratch, new Object[] { instructions });
134
135             while(!halt && !fp.isTerminated())
136                 for(InterpreterShip ship : ships.values())
137                     for(int j=0; j<10; j++)
138                         ship._service();
139
140             // run the ships a bit longer for good measure
141             for(int i=0; i<100; i++)
142                 for(InterpreterShip ship : ships.values())
143                     for(int j=0; j<10; j++)
144                         ship._service();
145
146             // check the state of the ships
147             for(InterpreterShip ship : ships.values())
148                 ship.shutdown();
149
150             Log.println(Log.yellow("    DONE: ====== FLEET is halted.  Have a nice day.  ======"));
151         } catch (Exception e) {
152             throw new RuntimeException(e);
153         }
154     }
155
156     public void dispatch(Instruction i, long address) {
157         Log.dispatch(i);
158         if (i instanceof Instruction.Executable) {
159             InterpreterBenkoBox sourceBenkoBox = (InterpreterBenkoBox)(((Instruction.Executable)i).benkoBox);
160             ((InstructionPort)sourceBenkoBox).addInstruction(((Instruction.Executable)i));
161
162         } else if (i instanceof Instruction.Literal.CodeBagDescriptor) {
163             Instruction.Literal.CodeBagDescriptor cbd = (Instruction.Literal.CodeBagDescriptor)i;
164             InterpreterBenkoBox destBenkoBox = (InterpreterBenkoBox)(cbd.dest);
165             long absolute_cbd = ((cbd.offset+address) << 6) | cbd.size;
166             destBenkoBox.addDataFromFabric((int)absolute_cbd);
167             
168         } else if (i instanceof Instruction.Literal.Absolute) {
169             InterpreterBenkoBox destBenkoBox = (InterpreterBenkoBox)(((Instruction.Literal.Absolute)i).dest);
170             Log.data(((Instruction.Literal.Absolute)i).value+"", null, destBenkoBox);
171             destBenkoBox.addDataFromFabric((int)((Instruction.Literal.Absolute)i).value);
172
173         } else if (i instanceof Instruction.Kill) {
174             InterpreterBenkoBox benkoBox = (InterpreterBenkoBox)(((Instruction.Kill)i).benkoBox);
175             ((InstructionPort)benkoBox).kill(((Instruction.Kill)i).count);
176
177         } else {
178             throw new Error("unsupported: " + i.getClass().getName());
179         }
180     }
181
182     public void sendToken(InterpreterBenkoBox source, InterpreterBenkoBox dest) {
183         Log.token(source, dest);
184         dest.addTokenFromFabric();
185     }
186
187     public void sendData(InterpreterBenkoBox source, int data, InterpreterBenkoBox dest) {
188         Log.data(data+"", source, dest);
189         dest.addDataFromFabric(data);
190     }
191
192
193     // Implementation of the Fleet class abstract methods /////////////////////////////////////////////////////////
194
195     public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)shiplist.iterator(); }
196
197     public int computeOffset(int origin, int target) { return (target - origin)/6; }
198     public int computeTarget(int origin, int offset) { return origin + (offset*6); }
199
200     private InterpreterInstructionEncoder iie = new InterpreterInstructionEncoder();
201     public Instruction readInstruction(DataInputStream is) throws IOException { return iie.readInstruction(is); }
202     public Instruction readInstruction(long instr) { return iie.readInstruction(instr); }
203     public long writeInstruction(Instruction d) { return writeInstruction(d); }
204     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException { iie.writeInstruction(os, d); }
205
206     private class InterpreterInstructionEncoder extends InstructionEncoder {
207         public long getBoxAddr(BenkoBox box) { return ((InterpreterBenkoBox)box).addr; }
208         public long getBoxInstAddr(BenkoBox box) { return ((InterpreterBenkoBox)box).instr_addr; }
209         public BenkoBox getBoxByAddr(long dest) {
210             for(Ship ship : Interpreter.this)
211                 for(BenkoBox bb : ship.getBenkoBoxes())
212                     if (((InterpreterBenkoBox)bb).addr == dest)
213                         return bb;
214             return null;
215         }
216         public BenkoBox getBoxByInstAddr(long dest) {
217             for(Ship ship : Interpreter.this)
218                 for(BenkoBox bb : ship.getBenkoBoxes())
219                     if (((InterpreterBenkoBox)bb).instr_addr == dest)
220                         return bb;
221             return null;
222         }
223     }
224
225     public Ship createShip(String shipType, String shipname) {
226         try {
227             Class c = Class.forName("edu.berkeley.fleet.ships."+shipType);
228             Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class });
229             InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname });
230             ships.put(shipname, ret);
231             shiplist.add(ret);
232             return ret;
233         } catch (Exception e) {
234             return null;
235         }
236     }
237
238
239     // Memory //////////////////////////////////////////////////////////////////////////////
240
241     public void dumpMem() {
242         Log.print(Log.cyan("  MEMORY: "));
243         for(int i=0; i<mem.length; i++) {
244             if ((i%10)==0 && i!=0) Log.print(Log.cyan("          "));
245             Log.print(Log.cyan(mem[i] + " "));
246             if ((i%10)==9 && i!=mem.length-1) Log.println("");
247         }
248         Log.println();
249     }
250
251     public int readMem(int addr) {
252         return addr >= mem.length ? 0 : mem[addr];
253     }
254     public void writeMem(int addr, int data) {
255         if (addr >= mem.length) {
256             int[] mem2 = new int[addr*2+1];
257             System.arraycopy(mem, 0, mem2, 0, mem2.length);
258             mem = mem2;
259         }
260         mem[addr] = data;
261     }
262
263
264 }
265