d4eff59b8147da032003e238acd7b195e4dd9420
[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.interpreter.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/interpreter/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.interpreter.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                         if (fp.isTerminated()) return;
108                         throw new RuntimeException(e);
109                     }
110                 }
111             }.start();
112             return fp;
113         } catch (Exception e) {
114             throw new RuntimeException(e);
115         }
116     }
117
118     public void go(FleetProcess fp, byte[] instructions) {
119         try {
120             // find the first icache
121             InterpreterShip iscratch = null;
122             for(Ship ship : this)
123                 if (ship.getClass().getSimpleName().equals("Iscratch")) {
124                     iscratch = (InterpreterShip)ship;
125                     break;
126                 }
127             if (iscratch==null)
128                 iscratch = (InterpreterShip)Class.forName("edu.berkeley.fleet.interpreter.ships.Iscratch")
129                     .getConstructor(new Class[] { Interpreter.class, String.class })
130                     .newInstance(new Object[] { this, "iscratch" });
131             iscratch
132                 .getClass()
133                 .getMethod("boot", new Class[] { byte[].class })
134                 .invoke(iscratch, new Object[] { instructions });
135
136             while(!halt && !fp.isTerminated())
137                 for(InterpreterShip ship : ships.values())
138                     for(int j=0; j<10; j++)
139                         ship._service();
140
141             // run the ships a bit longer for good measure
142             for(int i=0; i<100; i++)
143                 for(InterpreterShip ship : ships.values())
144                     for(int j=0; j<10; j++)
145                         ship._service();
146
147             // check the state of the ships
148             for(InterpreterShip ship : ships.values())
149                 ship.shutdown();
150
151             Log.println(Log.yellow("    DONE: ====== FLEET is halted.  Have a nice day.  ======"));
152         } catch (Exception e) {
153             throw new RuntimeException(e);
154         }
155     }
156
157     public void dispatch(Instruction i, long address) {
158         Log.dispatch(i);
159         if (i instanceof Instruction.Executable) {
160             InterpreterBenkoBox sourceBenkoBox = (InterpreterBenkoBox)(((Instruction.Executable)i).benkoBox);
161             ((InstructionPort)sourceBenkoBox).addInstruction(((Instruction.Executable)i));
162
163         } else if (i instanceof Instruction.Literal.CodeBagDescriptor) {
164             Instruction.Literal.CodeBagDescriptor cbd = (Instruction.Literal.CodeBagDescriptor)i;
165             InterpreterBenkoBox destBenkoBox = (InterpreterBenkoBox)(cbd.dest);
166             long absolute_cbd = ((cbd.offset+address) << 6) | cbd.size;
167             destBenkoBox.addDataFromFabric((int)absolute_cbd);
168             
169         } else if (i instanceof Instruction.Literal.Absolute) {
170             InterpreterBenkoBox destBenkoBox = (InterpreterBenkoBox)(((Instruction.Literal.Absolute)i).dest);
171             Log.data(((Instruction.Literal.Absolute)i).value+"", null, destBenkoBox);
172             destBenkoBox.addDataFromFabric((int)((Instruction.Literal.Absolute)i).value);
173
174         } else if (i instanceof Instruction.Kill) {
175             InterpreterBenkoBox benkoBox = (InterpreterBenkoBox)(((Instruction.Kill)i).benkoBox);
176             ((InstructionPort)benkoBox).kill(((Instruction.Kill)i).count);
177
178         } else {
179             throw new Error("unsupported: " + i.getClass().getName());
180         }
181     }
182
183     public void sendToken(InterpreterBenkoBox source, InterpreterBenkoBox dest) {
184         Log.token(source, dest);
185         dest.addTokenFromFabric();
186     }
187
188     public void sendData(InterpreterBenkoBox source, int data, InterpreterBenkoBox dest) {
189         Log.data(data+"", source, dest);
190         dest.addDataFromFabric(data);
191     }
192
193
194     // Implementation of the Fleet class abstract methods /////////////////////////////////////////////////////////
195
196     public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)shiplist.iterator(); }
197
198     public int computeOffset(int origin, int target) { return (target - origin)/6; }
199     public int computeTarget(int origin, int offset) { return origin + (offset*6); }
200
201     private InterpreterInstructionEncoder iie = new InterpreterInstructionEncoder();
202     public Instruction readInstruction(DataInputStream is) throws IOException { return iie.readInstruction(is); }
203     public Instruction readInstruction(long instr) { return iie.readInstruction(instr); }
204     public long writeInstruction(Instruction d) { return writeInstruction(d); }
205     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException { iie.writeInstruction(os, d); }
206
207     private class InterpreterInstructionEncoder extends InstructionEncoder {
208         public long getBoxAddr(BenkoBox box) { return ((InterpreterBenkoBox)box).addr; }
209         public long getBoxInstAddr(BenkoBox box) { return ((InterpreterBenkoBox)box).instr_addr; }
210         public BenkoBox getBoxByAddr(long dest) {
211             for(Ship ship : Interpreter.this)
212                 for(BenkoBox bb : ship.getBenkoBoxes())
213                     if (((InterpreterBenkoBox)bb).addr == dest)
214                         return bb;
215             return null;
216         }
217         public BenkoBox getBoxByInstAddr(long dest) {
218             for(Ship ship : Interpreter.this)
219                 for(BenkoBox bb : ship.getBenkoBoxes())
220                     if (((InterpreterBenkoBox)bb).instr_addr == dest)
221                         return bb;
222             return null;
223         }
224     }
225
226     public Ship createShip(String shipType, String shipname) {
227         try {
228             Class c = Class.forName("edu.berkeley.fleet.interpreter.ships."+shipType);
229             Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class });
230             InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname });
231             ships.put(shipname, ret);
232             shiplist.add(ret);
233             return ret;
234         } catch (Exception e) {
235             return null;
236         }
237     }
238
239
240     // Memory //////////////////////////////////////////////////////////////////////////////
241
242     public void dumpMem() {
243         Log.print(Log.cyan("  MEMORY: "));
244         for(int i=0; i<mem.length; i++) {
245             if ((i%10)==0 && i!=0) Log.print(Log.cyan("          "));
246             Log.print(Log.cyan(mem[i] + " "));
247             if ((i%10)==9 && i!=mem.length-1) Log.println("");
248         }
249         Log.println();
250     }
251
252     public int readMem(int addr) {
253         return addr >= mem.length ? 0 : mem[addr];
254     }
255     public void writeMem(int addr, int data) {
256         if (addr >= mem.length) {
257             int[] mem2 = new int[addr*2+1];
258             System.arraycopy(mem, 0, mem2, 0, mem2.length);
259             mem = mem2;
260         }
261         mem[addr] = data;
262     }
263
264
265 }
266