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