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