1 package edu.berkeley.fleet.interpreter;
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.*;
12 public class Interpreter extends Fleet {
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];
22 public void debug(long data) {
24 if (debugStream != null) {
25 debugStream.put(data);
27 Log.println(Log.invert(" DEBUG: got a datum: " + data+Log.clreol()));
29 } catch (Exception e) {
30 throw new RuntimeException(e);
34 public static class DynamicInterpreter extends Interpreter implements Fleet.WithDynamicShips {
37 public void expand(ShipDescription sd) {
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);
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.*;");
53 pw.println("public class "+filename+" extends InterpreterShip {");
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];
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");
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+"\");");
74 pw.println(" public "+filename+"(Interpreter fleet, String name) { super(fleet, name); }");
76 //pw.println(" public void service() {");
77 pw.println(sd.sections.get("fleeterpreter"));
82 } catch (Exception e) { throw new RuntimeException(e); }
85 public FleetProcess run(final byte[] instructions) {
87 final FleetProcess fp = new FleetProcess() {
88 public void invokeInstruction(Instruction i) { throw new RuntimeException("not supported"); }
89 public long readWord() {
91 return debugStream.take();
92 } catch (Exception e) {
93 throw new RuntimeException(e);
95 protected void _terminate() {
96 shiplist = new ArrayList<InterpreterShip>();
97 ships = new HashMap<String,InterpreterShip>();
98 debugStream = new LinkedBlockingQueue<Long>();
105 go(fp, instructions);
106 } catch (Exception e) {
107 throw new RuntimeException(e);
112 } catch (Exception e) {
113 throw new RuntimeException(e);
117 public void go(FleetProcess fp, byte[] instructions) {
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;
127 iscratch = (InterpreterShip)Class.forName("edu.berkeley.fleet.ships.Iscratch")
128 .getConstructor(new Class[] { Interpreter.class, String.class })
129 .newInstance(new Object[] { this, "iscratch" });
132 .getMethod("boot", new Class[] { byte[].class })
133 .invoke(iscratch, new Object[] { instructions });
135 while(!halt && !fp.isTerminated())
136 for(InterpreterShip ship : ships.values())
137 for(int j=0; j<10; j++)
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++)
146 // check the state of the ships
147 for(InterpreterShip ship : ships.values())
150 Log.println(Log.yellow(" DONE: ====== FLEET is halted. Have a nice day. ======"));
151 } catch (Exception e) {
152 throw new RuntimeException(e);
156 public void dispatch(Instruction i, long address) {
158 if (i instanceof Instruction.Executable) {
159 InterpreterBenkoBox sourceBenkoBox = (InterpreterBenkoBox)(((Instruction.Executable)i).benkoBox);
160 ((InstructionPort)sourceBenkoBox).addInstruction(((Instruction.Executable)i));
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);
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);
173 } else if (i instanceof Instruction.Kill) {
174 InterpreterBenkoBox benkoBox = (InterpreterBenkoBox)(((Instruction.Kill)i).benkoBox);
175 ((InstructionPort)benkoBox).kill(((Instruction.Kill)i).count);
178 throw new Error("unsupported: " + i.getClass().getName());
182 public void sendToken(InterpreterBenkoBox source, InterpreterBenkoBox dest) {
183 Log.token(source, dest);
184 dest.addTokenFromFabric();
187 public void sendData(InterpreterBenkoBox source, int data, InterpreterBenkoBox dest) {
188 Log.data(data+"", source, dest);
189 dest.addDataFromFabric(data);
193 // Implementation of the Fleet class abstract methods /////////////////////////////////////////////////////////
195 public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)shiplist.iterator(); }
197 public int computeOffset(int origin, int target) { return (target - origin)/6; }
198 public int computeTarget(int origin, int offset) { return origin + (offset*6); }
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); }
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)
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)
225 public Ship createShip(String shipType, String shipname) {
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);
233 } catch (Exception e) {
239 // Memory //////////////////////////////////////////////////////////////////////////////
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("");
251 public int readMem(int addr) {
252 return addr >= mem.length ? 0 : mem[addr];
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);