final pass to update instruction encoding; should now match the spec
[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             InterpreterPump sourcePump = (InterpreterPump)(((Instruction.Executable)i).pump);
86             ((InstructionPump)sourcePump).addInstruction(((Instruction.Executable)i));
87
88         } else if (i instanceof Instruction.CodeBagDescriptor) {
89             Instruction.CodeBagDescriptor cbd = (Instruction.CodeBagDescriptor)i;
90             long absolute_cbd = ((cbd.offset+address) << 6) | cbd.size;
91             throw new RuntimeException();
92             //new Packet(this, null, (int)absolute_cbd, (InterpreterDestination)cbd.pump).send();
93             
94         } else if (i instanceof Instruction.UnClog) {
95             //FIXME
96         } else if (i instanceof Instruction.Kill) {
97             InterpreterPump pump = (InterpreterPump)(((Instruction.Kill)i).pump);
98             ((InstructionPump)pump).kill(((Instruction.Kill)i).count, false);
99                    
100
101         } else {
102             throw new Error("unsupported: " + i.getClass().getName());
103         }
104     }
105
106     public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)ships.values().iterator(); }
107
108     public Ship createShip(String shipType, String shipname) {
109         try {
110             Class c = Class.forName("edu.berkeley.fleet.interpreter."+shipType);
111             Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class });
112             InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname });
113             BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+shipType+".ship")));
114             ShipDescription sd = new ShipDescription(shipname, br);
115             ret.setShipDescription(sd);
116             ships.put(shipname, ret);
117             return ret;
118         } catch (Exception e) {
119             return null;
120         }
121     }
122
123     public void debug(long data) {
124         try {
125             if (debugStream != null) debugStream.put(data);
126             else Log.println(ANSI.invert("   DEBUG: got a datum: " +  data+ANSI.clreol()));
127         } catch (Exception e) {
128             throw new RuntimeException(e);
129         }
130     }
131
132     // Instruction Encoding /////////////////////////////////////////////////////////////////////////
133
134     public final InterpreterInstructionEncoder iie = new InterpreterInstructionEncoder();
135     public Instruction readInstruction(DataInputStream is) throws IOException { return iie.readInstruction(is); }
136     public Instruction readInstruction(long instr) { return iie.readInstruction(instr); }
137     public long writeInstruction(Instruction d) { return writeInstruction(d); }
138     public void writeInstruction(DataOutputStream os, Instruction d) throws IOException { iie.writeInstruction(os, d); }
139     public class InterpreterInstructionEncoder extends InstructionEncoder {
140         public long getDestAddr(Destination box) { return ((InterpreterDestination)box).getDestAddr(); }
141         public long getBoxInstAddr(Pump box) { return ((InterpreterPump)box).getDestAddr(); }
142         public Destination getDestByAddr(long dest) {
143             for(Ship ship : Interpreter.this)
144                 for(Pump bb : ship.getPumps())
145                     for(Destination d : bb.getDestinations())
146                         if (getDestAddr(d)==dest)
147                             return d;
148             return null;
149         }
150         public Pump getBoxByInstAddr(long dest) {
151             for(Ship ship : Interpreter.this)
152                 for(Pump bb : ship.getPumps())
153                     if (getBoxInstAddr(bb) == dest)
154                         return bb;
155             return null;
156         }
157     }
158
159     // ShipDescription //////////////////////////////////////////////////////////////////////////////
160
161     public void expand(ShipDescription sd) {
162         try {
163             String filename = sd.getName();
164             //String filename = (sd.getName().charAt(0)+"").toUpperCase() + sd.getName().substring(1).toLowerCase();
165             File outf = new File("build/java/edu/berkeley/fleet/interpreter/"+filename+".java");
166             new File(outf.getParent()).mkdirs();
167             System.err.println("writing to " + outf);
168             FileOutputStream out = new FileOutputStream(outf);
169             PrintWriter pw = new PrintWriter(out);
170
171             pw.println("package edu.berkeley.fleet.interpreter;");
172             pw.println("import edu.berkeley.sbp.util.ANSI;");
173             pw.println("import edu.berkeley.fleet.api.*;");
174             pw.println("import edu.berkeley.fleet.*;");
175             pw.println("import java.util.*;");
176             pw.println("import java.io.*;");
177             pw.println("");
178             pw.println("public class "+filename+" extends InterpreterShip {");
179             pw.println("");
180             for(PumpDescription b : sd) {
181                 String name = b.getName();
182                 pw.print("    ");
183                 if ( b.isInbox()) pw.print("Inbox");
184                 if (!b.isInbox()) pw.print("Outbox");
185                 pw.print(" box_");
186                 pw.print(name);
187                 pw.print(" = new ");
188                 if ( b.isInbox()) pw.print("Inbox");
189                 if (!b.isInbox()) pw.print("Outbox");
190                 pw.print("(this, \""+name+"\", new String[] { ");
191                 boolean first = true;
192                 for(String destination : b) {
193                     if (!first) pw.print(", ");
194                     first = false;
195                     pw.print("\""+destination+"\"");
196                 }
197                 pw.println("});");
198             }
199             pw.println("");
200             pw.println("    public "+filename+"(Interpreter fleet, String name) {");
201             pw.println("       super(fleet, name, \""+filename+"\");");
202             for(PumpDescription b : sd)
203                 pw.println("       addPump(\""+b.getName()+"\", box_"+b.getName()+");");
204             pw.println("    }");
205             pw.println("");
206             pw.println(sd.getSection("fleeterpreter"));
207             pw.println("}");
208             pw.flush();
209             pw.close();
210         } catch (Exception e) { throw new RuntimeException(e); }
211     }
212
213 }
214