Break Fpga.java into separate subclasses for ML509.Large, ML509.Small, and Bee2
[fleet.git] / src / edu / berkeley / fleet / interpreter / Interpreter.java
index cff67db..311a0aa 100644 (file)
 package edu.berkeley.fleet.interpreter;
-import edu.berkeley.fleet.api.*;
-
-import edu.berkeley.fleet.api.*;
-import edu.berkeley.fleet.*;
-import java.lang.reflect.*;
-import edu.berkeley.sbp.chr.*;
-import edu.berkeley.sbp.misc.*;
-import edu.berkeley.sbp.meta.*;
-import edu.berkeley.sbp.bind.*;
-import edu.berkeley.sbp.util.*;
-import java.util.*;
 import java.io.*;
-import edu.berkeley.fleet.ships.*;
-
-public class Interpreter extends Fleet implements Iterable<Ship> {
-
-    public InterpreterBenkoBox resolve(edu.berkeley.fleet.api.BenkoBox bb) { return (InterpreterBenkoBox)bb; }
-
-    public void dispatch(Instruction i) {
-
-        if (i instanceof Instruction.Executable) {
-            InterpreterBenkoBox sourceBenkoBox = resolve(((Instruction.Executable)i).benkoBox);
-            if (!(sourceBenkoBox instanceof InstructionPort))
-                throw new RuntimeException(sourceBenkoBox + " is not an InstructionPort!");
-            ((InstructionPort)sourceBenkoBox).addInstruction(((Instruction.Executable)i));
-
-        } else if (i instanceof Instruction.Literal.Absolute) {
-            InterpreterBenkoBox destBenkoBox = resolve(((Instruction.Literal.Absolute)i).dest);
-            Log.data(((Instruction.Literal.Absolute)i).value+"", null, destBenkoBox);
-            destBenkoBox.addDataFromFabric((int)((Instruction.Literal.Absolute)i).value);
-
-        } else if (i instanceof Instruction.Kill) {
-            InterpreterBenkoBox benkoBox = resolve(((Instruction.Kill)i).benkoBox);
-            if (!(benkoBox instanceof InstructionPort))
-                throw new RuntimeException(benkoBox + " is not an InstructionPort!");
-            ((InstructionPort)benkoBox).kill(((Instruction.Kill)i).count);
-
-        } else {
-            throw new Error("unsupported!");
-        }
-    }
-
-    /** some "halt ship" can turn this on to stop the interpreter */
-    public boolean halt = false;
-
-    public int[] mem = new int[0];
-    public ArrayList<String> imports = new ArrayList<String>();
-
-    private static String getUniqueName(Ship ship) {
-        return ship.getType() + ship.getOrdinal();
-    }
-
-    public ArrayList<InterpreterShip> shiplist = new ArrayList<InterpreterShip>();
-    public HashMap<String,InterpreterShip> ships = new HashMap<String,InterpreterShip>();
-
-    /** read a machine-formatted instruction from a file (into a Java object) */
-    public Instruction readInstruction(DataInputStream is) throws IOException {
-        // FIXME
+import java.util.*;
+import java.util.concurrent.*;
+import java.lang.reflect.*;
+import edu.berkeley.sbp.util.ANSI;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.assembler.*;
+import edu.berkeley.fleet.util.*;
+
+public class Interpreter extends FleetTwoFleet {
+
+    /** used to allocate serial numbers; see InterpreterDestination for further detail */
+    int maxAllocatedDestinationSerialNumber = 0;
+
+    private InterpreterShip debugShip = null;
+    private BlockingQueue<BitVector> debugStream = new LinkedBlockingQueue<BitVector>();
+    private LinkedHashMap<String,InterpreterShip> ships = new LinkedHashMap<String,InterpreterShip>();
+    public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)ships.values().iterator(); }
+    public Ship getShip(String type, int ordinal) {
+        for(Ship s : this)
+            if (s.getType().equals(type))
+                if (ordinal-- <= 0)
+                    return s;
         return null;
     }
 
-    public void        writeInstruction(DataOutputStream os, Instruction d) throws IOException {
-            if (d instanceof Instruction.Executable) {
-                Instruction.Executable inst = (Instruction.Executable)d;
-
-                InterpreterBenkoBox dest = resolve(inst.dest);
-                long instr = dest==null ? 0 : (dest.addr << 1);
-
-                instr |= (((long)inst.count) << (11+1));
-                if (inst.tokenIn)  instr |= (1L << (11+1+7+0));
-                if (inst.dataOut)  instr |= (1L << (11+1+7+1));
-                if (inst.latch)    instr |= (1L << (11+1+7+2));
-                if (inst.dataIn)   instr |= (1L << (11+1+7+3));
-                if (inst.tokenOut) instr |= (1L << (11+1+7+4));
-                instr |= ((long)resolve(inst.benkoBox).instr_addr) << (11+5+7+1);
-                long out = 0;
-                out |= ((InterpreterBenkoBox)ships.get("command").getBenkoBox("data")).addr;
-                out |= instr << 11;
-                dump(os, (out >> (5*8)) & 0xff);
-                dump(os, (out >> (4*8)) & 0xff);
-                dump(os, (out >> (3*8)) & 0xff);
-                dump(os, (out >> (2*8)) & 0xff);
-                dump(os, (out >> (1*8)) & 0xff);
-                dump(os, (out >> (0*8)) & 0xff);
-            } else if (d instanceof Instruction.Literal.Absolute) {
-                Instruction.Literal.Absolute ld = (Instruction.Literal.Absolute)d;
-                long out = 0;
-                out |= resolve(ld.dest).addr;
-                out |= ((long)ld.value) << 11;
-                dump(os, (out >> (5*8)) & 0xff);
-                dump(os, (out >> (4*8)) & 0xff);
-                dump(os, (out >> (3*8)) & 0xff);
-                dump(os, (out >> (2*8)) & 0xff);
-                dump(os, (out >> (1*8)) & 0xff);
-                dump(os, (out >> (0*8)) & 0xff);
-            }
-    }
-    public void dump(OutputStream os, long data_) throws IOException {
-        int data = (int)data_;
-        os.write((byte)data);
-        System.out.println(data);
-    }
-
-    public Iterator<Ship> iterator() {
-        return (Iterator<Ship>)(Object)shiplist.iterator();
-    }
-
-    public void go() {
-        while(!halt)
-            for(InterpreterShip ship : ships.values())
-                for(int j=0; j<10; j++)
-                    ship._service();
-
-        // run the ships a bit longer for good measure
-        for(int i=0; i<100; i++)
-            for(InterpreterShip ship : ships.values())
-                for(int j=0; j<10; j++)
-                    ship._service();
-
-        // check the state of the ships
-        for(InterpreterShip ship : ships.values())
-            ship.shutdown();
-
-        Log.println(Log.yellow("    DONE: ====== FLEET is halted.  Have a nice day.  ======"));
-    }
-
-    public void dumpMem() {
-        Log.print(Log.cyan("  MEMORY: "));
-        for(int i=0; i<mem.length; i++) {
-            if ((i%10)==0 && i!=0) Log.print(Log.cyan("          "));
-            Log.print(Log.cyan(mem[i] + " "));
-            if ((i%10)==9 && i!=mem.length-1) Log.println("");
-        }
-        Log.println();
+    /** do not use this; it is going to go away */
+    public Interpreter() { this(true); }
+    public Interpreter(boolean logging) {
+        this(new String[] {
+                "Debug",
+                "Memory",
+                "Memory",
+                "Memory",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Alu",
+                "Fifo",
+                "Fifo",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Counter",
+                "Lut3",
+                "CarrySaveAdder",
+                "Rotator",
+                "Dvi",
+                "Button",
+                "Timer",
+            }, logging);
     }
 
-    public void writeMem(int addr, int data) {
-        if (addr >= mem.length) {
-            int[] mem2 = new int[addr*2+1];
-            System.arraycopy(mem, 0, mem2, 0, mem2.length);
-            mem = mem2;
+    public Interpreter(String[] ships, boolean logging) {
+        int i=0;
+        Log.quiet = !logging;
+        for(String s : ships) {
+            try {
+                createShip(ships[i], ships[i]+"_"+i);
+            } catch (Exception e) {
+                System.err.println(e);
+            }
+            i++;
         }
-        mem[addr] = data;
     }
 
-    public InterpreterShip getShip(String name) {
-        InterpreterShip s = ships.get(name);
-        if (s == null) throw new RuntimeException("unknown ship \""+name+"\"");
-        return s;
-    }
-
-    public InterpreterShip tryCreate(String classname, String shipname) {
+    private Ship createShip(String shipType, String shipname) {
         try {
-            Class c = Class.forName(classname);
-            Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class });
-            InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname });
+            if (ships.get(shipname)!=null) return ships.get(shipname);
+            Class c = Class.forName("edu.berkeley.fleet.interpreter."+shipType);
+            Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class, ShipDescription.class });
+            String src = "/ships/" + shipType + ".ship";
+            InputStream is = getClass().getResourceAsStream(src);
+            BufferedReader br = new BufferedReader(new InputStreamReader(is));
+            ShipDescription sd = new ShipDescription(this, shipType, br);
+            InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname, sd });
             ships.put(shipname, ret);
-            shiplist.add(ret);
+            if (shipType.equals("Debug") && debugShip == null)
+                debugShip = ret;
             return ret;
         } catch (Exception e) {
-            return null;
+            throw new RuntimeException(e);
         }
     }
 
-    public void sendToken(InterpreterBenkoBox source, InterpreterBenkoBox dest) {
-        Log.token(source, dest);
-        dest.addTokenFromFabric();
-    }
-
-    public void sendData(InterpreterBenkoBox source, int data, InterpreterBenkoBox dest) {
-        Log.data(data+"", source, dest);
-        dest.addDataFromFabric(data);
+    void debug(long d) { debug(new BitVector(getWordWidth()).set(d)); }
+    void debug(BitVector data) {
+        try {
+            if (debugStream != null) debugStream.put(data);
+            else Log.println(ANSI.invert("   DEBUG: got a datum: " +  data+ANSI.clreol()));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
-    public void dumpFabric(boolean quiet) {
-        // FIXME: this is really ugly: the order of port declarations in
-        //        the XXXShip.java file must match the order in the .balsa file!
-
-        ArrayList instructionports = new ArrayList<InterpreterBenkoBox>();
-        for(InterpreterShip ship : shiplist)
-            for(BenkoBox port : ship.getBenkoBoxes())
-                if (!((InterpreterBenkoBox)port).special())
-                    instructionports.add(port);
-        FabricTree instructions =
-            new FabricTree((InterpreterBenkoBox[])instructionports.toArray(new InterpreterBenkoBox[0]),
-                           "ihorn",
-                           "instruction");
+    // Instruction Encoding /////////////////////////////////////////////////////////////////////////
 
-        ArrayList inputports = new ArrayList<InterpreterBenkoBox>();
-        for(InterpreterShip ship : shiplist)
-            for(BenkoBox port : ship.getBenkoBoxes())
-                if (!((InterpreterBenkoBox)port).special())
-                    inputports.add(port);
-        FabricTree inputs =
-            new FabricTree((InterpreterBenkoBox[])inputports.toArray(new InterpreterBenkoBox[0]),
-                           "horn",
-                           "dest");
+    public BitVector getDestAddr(Path path) {
+        long ret = ((InterpreterDestination)path.getDestination()).getSerialNumber();
+        BitVector sig = path.getSignal();
+        BitVector bv = new BitVector(DISPATCH_PATH.valmaskwidth+1);
+        bv.set(ret);
+        if (sig != null) {
+            if (sig.length() > 1) throw new RuntimeException("signal was " + sig.length() + " bits long!");
+            if (sig.length() > 0 && sig.get(0)) bv.set(bv.length()-1,true);
+        }
+        return bv;
+    }
 
-        ArrayList outputports = new ArrayList<InterpreterBenkoBox>();
-        for(InterpreterShip ship : shiplist)
-            for(BenkoBox port : ship.getBenkoBoxes())
-                if (!((InterpreterBenkoBox)port).special())
-                    outputports.add(port);
-        FabricTree outputs =
-            new FabricTree((InterpreterBenkoBox[])outputports.toArray(new InterpreterBenkoBox[0]),
-                           "funnel",
-                           "source");
 
-        if (quiet) return;
-        System.out.println("`include \"macros.v\"");
-        /*
-        HashSet<Class> added = new HashSet<Class>();
-        for(Ship ship : shiplist)
-            if (!added.contains(ship.getClass())) {
-                added.add(ship.getClass());
-                System.out.println("import ["+ship.getBalsaName()+"]");
-            }
-        */
-        System.out.println("module fabric(clk, top_r, top_a, top,");
-        System.out.println("                   data_Debug0_out_r, data_Debug0_out_a, data_Debug0_out);");
-        System.out.println("  input  clk;");
-        System.out.println("  input  top_r;");
-        System.out.println("  output top_a;");
-        System.out.println("  input  [(`PACKET_WIDTH-1):0] top;");
-        System.out.println("  output data_Debug0_out_r;");
-        System.out.println("  input  data_Debug0_out_a;");
-        System.out.println("  output [(`PACKET_WIDTH-1):0] data_Debug0_out;");
-        System.out.println("  wire   [(`INSTRUCTION_WIDTH-1):0] data_Command0_out;");
-        System.out.println();
-        
-        System.out.println();
+    // ShipDescription //////////////////////////////////////////////////////////////////////////////
 
-        instructions.dumpChannels(true);
-        outputs.dumpChannels(true);
-        inputs.dumpChannels(true);
-        for(InterpreterShip ship : shiplist)
-            for(BenkoBox port : ship.getBenkoBoxes()) {
-                if (ship instanceof Command && port instanceof Outbox) continue;
-                System.out.println("  wire [(`PACKET_WIDTH-1):0] data_"+getUniqueName(ship)+"_"+port.getName()+";");
+    public void expand(ShipDescription sd) {
+        try {
+            String filename = sd.getName();
+            //String filename = (sd.getName().charAt(0)+"").toUpperCase() + sd.getName().substring(1).toLowerCase();
+            File outf = new File("build/java/edu/berkeley/fleet/interpreter/"+filename+".java");
+            new File(outf.getParent()).mkdirs();
+            System.err.println("writing to " + outf);
+            FileOutputStream out = new FileOutputStream(outf);
+            PrintWriter pw = new PrintWriter(out);
+
+            pw.println("package edu.berkeley.fleet.interpreter;");
+            pw.println("import edu.berkeley.sbp.util.ANSI;");
+            pw.println("import edu.berkeley.fleet.api.*;");
+            pw.println("import edu.berkeley.fleet.two.*;");
+            pw.println("import edu.berkeley.fleet.*;");
+            pw.println("import java.util.*;");
+            pw.println("import java.io.*;");
+            pw.println("");
+            pw.println("public class "+filename+" extends InterpreterShip {");
+            pw.println("");
+            pw.println("    public "+filename+"(Interpreter fleet, String name, ShipDescription sd) {");
+            pw.println("       super(fleet, sd);");
+            pw.println("    }");
+            pw.println("");
+            for(DockDescription b : sd) {
+                String name = b.getName();
+                pw.print("    InterpreterDock box_");
+                pw.print(name);
+                pw.print(" = new InterpreterDock(this, shipDescription.getDockDescription(\""+name+"\"));");
             }
+            pw.println("");
+            pw.println(sd.getSection("fleeterpreter"));
+            pw.println("}");
+            pw.flush();
+            pw.close();
+        } catch (Exception e) { throw new RuntimeException(e); }
+    }
 
-        System.out.println("");
-        instructions.dumpChannels(false);
-        System.out.println("");
-        outputs.dumpChannels(false);
-        System.out.println("");
-        inputs.dumpChannels(false);
-        System.out.println("");
-        for(InterpreterShip ship : shiplist) {
-            System.out.print(ship.getClass().getSimpleName().toLowerCase());
-            System.out.print(" ");
-            System.out.print("krunk"+(krunk++));
-            System.out.print("(clk, ");
-            boolean first = true;
-            for(BenkoBox port : ship.getBenkoBoxes()) {
-                if (!first) System.out.print(", ");
-                first = false;
-                System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
-                System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
-                System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
-                System.out.print(" ");
-            }
-            System.out.println(");");
+    // Run //////////////////////////////////////////////////////////////////////////////
 
-            for(BenkoBox port : ship.getBenkoBoxes()) {
-                if (((InterpreterBenkoBox)port).special()) continue;
-                if (port instanceof Inbox) {
-                    if (((InterpreterBenkoBox)port).noInbox())
-                        System.out.print("stupidinbox");
-                    else
-                        System.out.print("inbox");
-                } else {
-                    System.out.print("outbox");
-                }
-                System.out.print(" krunk"+(krunk++)+"(clk, ");
-                System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
-                System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
-                System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
-                System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
-                System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
-                System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
-                System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
-                System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
-                System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+", ");
-                System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, ");
-                System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, ");
-                System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName());
-                System.out.print(");");
-                System.out.println();
-            }
+    public FleetProcess run(final Instruction[] instructions) {
+        InterpreterProcess ip = initialize(instructions);
+        Thread ipt = new Thread(ip);
+        ipt.setDaemon(true);
+        ipt.start();
+        return ip;
+    }
 
-        }
-        System.out.println("funnel topfun(clk, dest_r, dest_a, dest, source_r, source_a, source, top_r, top_a, top);");
-        System.out.println("");
-        System.out.println("  assign instruction_r      = data_Command0_out_r;");
-        System.out.println("  assign data_Command0_out_a = instruction_a;");
-        System.out.println("  assign instruction        = data_Command0_out;");
-        System.out.println("endmodule");
+    public InterpreterProcess initialize(Instruction[] instr) {
+        return new InterpreterProcess(instr);
     }
 
-    private static class FabricTree {
-        int master_idx = 1;
-        String prefix;
-        Node root;
-        public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); }
-        public FabricTree(InterpreterBenkoBox[] ports, String component, String prefix) {
-            this.prefix = prefix;
-            root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
+    public class InterpreterProcess extends FleetProcess implements Runnable {
+        private Instruction[] instructions;
+        public synchronized void sendWord(Destination d, BitVector word) { sendWord(d, word, null); }
+        public synchronized void sendWord(Destination d, BitVector word, BitVector signal) {
+            InterpreterPath path = (InterpreterPath)debugShip.getDock("in").getPath(d, signal==null?new BitVector(1):signal);
+            new Packet(path, word, false).send();
         }
-        private Object mkNode(String name, String component, InterpreterBenkoBox[] ports, int start, int end, int addr, int bits) {
-            if (end-start == 0) return null;
-            if (end-start == 1) {
-                InterpreterBenkoBox p = ports[start];
-                if (prefix.equals("instruction")) {
-                    p.instr_addr = addr;
-                    p.instr_bits = bits;
-                } else {
-                    p.addr = addr;
-                    p.bits = bits;
-                }
-                return p;
-            }
-            int len = end-start;
-            return new Node(name,
-                            component,
-                            mkNode(name+"_0", component, ports, start, start+len/2, addr, bits+1),
-                            mkNode(name+"_1", component, ports, start+len/2, end,   addr | (1 << bits), bits+1),
-                            addr,
-                            bits);
+        public synchronized void sendToken(Destination d) {
+            InterpreterPath path = (InterpreterPath)debugShip.getDock("in").getPath(d, new BitVector(1));
+            new Packet(path, new BitVector(getWordWidth()), true).send();
         }
-        private String describe(String prefix, Object o) {
-            if (o==null) return null;
-            if (o instanceof InterpreterBenkoBox) {
-                InterpreterBenkoBox p = (InterpreterBenkoBox)o;
-                return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName();
-            }
-            if (o instanceof Node) {
-                return ((Node)o).describe(prefix);
-            }
-            return null;
+        public InterpreterProcess(Instruction[] instructions) {
+            this.instructions = instructions;
+            for(Instruction i : instructions)
+                sendInstruction(i);
         }
-        private class Node {
-            Object left;
-            Object right;
-            String name;
-            String component;
-        int addr;
-        int bits;
-            public Node(String name, String component, Object left, Object right, int addr, int bits) {
-                this.left = left;
-                this.right = right;
-                this.name = name;
-                this.component = component;
-                this.addr = addr;
-                this.bits = bits;
-            }
-            public void dumpChannels(int indentamount, boolean decl) {
-                String indent = "";
-                for(int i=0; i<indentamount; i++) indent += "  ";
-                if (decl) {
-                    String n = describe(prefix).startsWith("instruction") ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
-                    System.out.println("  wire "+n+" "+indent+describe(prefix)+";");
-                } else {
-                    System.out.println("     "+indent+
-                                       component+" "+
-                                       "krunk"+(krunk++)+"(clk, "+
-                                       describe(prefix)+"_r, "+
-                                       describe(prefix)+"_a, "+
-                                       describe(prefix)+", "+
-                                       FabricTree.this.describe(prefix, left)+"_r, "+
-                                       FabricTree.this.describe(prefix, left)+"_a, "+
-                                       FabricTree.this.describe(prefix, left)+", "+
-                                       FabricTree.this.describe(prefix, right)+"_r, "+
-                                       FabricTree.this.describe(prefix, right)+"_a, "+
-                                       FabricTree.this.describe(prefix, right)+
-                                       ");");
-                }
-                dumpChannels(left, indentamount+1, decl);
-                dumpChannels(right, indentamount+1, decl);
-            }
-            public void dumpChannels(Object o, int indentamount, boolean decl) {
-                if (o==null) return;
-                if (o instanceof Node) {
-                    ((Node)o).dumpChannels(indentamount, decl);
-                } else {
-                    String indent = "";
-                    for(int i=0; i<indentamount; i++) indent += "  ";
-                    if (decl) {
-                        String n = FabricTree.this.describe(prefix,o).startsWith("instruction")
-                            ? "[(`INSTRUCTION_WIDTH-1):0]" : "[(`PACKET_WIDTH-1):0]";
-                        System.out.println("  wire "+n+" "+indent+FabricTree.this.describe(prefix,o)+";");
+        public Fleet getFleet() { return Interpreter.this; }
+        public synchronized void sendInstruction(Instruction i) {
+            long il = writeInstruction(i, debugShip.getDock("in"));
+            Path path = debugShip.getDock("in").getPath(i.dock.getInstructionDestination(), null);
+            new Packet((InterpreterPath)path, new BitVector(getWordWidth()).set(il), false).send();
+        }
+        public Dock getDebugInputDock() { return debugShip.getDock("in"); }
+        public BitVector recvWord() {
+            try {
+                return debugStream.take();
+            } catch (Exception e) { throw new RuntimeException(e); }
+        }
+        protected void _terminate() { }
+        public void run() {
+            try {
+                long lastStatus = System.currentTimeMillis();
+                while(!isTerminated()) {
+                    flush();
+                    long now = System.currentTimeMillis();
+                    if (now - lastStatus > 2000 && !Log.quiet &&
+                        !"false".equals(System.getProperty("fleet.log.state","false"))) {
+                        System.out.println("== State Dump ===================================================");
+                        for(InterpreterShip ship : ships.values())
+                            for(Dock d : ship)
+                                synchronized(this) {
+                                    ((InterpreterDock)d).dumpState();
+                                }
+                        lastStatus = now;
                     }
                 }
+                for(InterpreterShip ship : ships.values())
+                    ship.reset();
+                debugStream.clear();
+            } catch (Exception e) {
+                if (isTerminated()) return;
+                throw new RuntimeException(e);
             }
-            public String describe(String prefix) {
-                return prefix+name;
-            }
         }
+
+        public void flush() {
+            // FIXME: should this run until we detect some sort of "quiescence"?  OTOH that might never happen.
+            for(InterpreterShip ship : ships.values())
+                for(int j=0; j<10; j++)
+                    if (!isTerminated())
+                        synchronized(this) {
+                            ship._service();
+                        }
+        }
+
+        public synchronized void step(Dock d) {
+            ((InterpreterDock)d).service();
+        }
+        
+        public synchronized void step(Ship s) {
+            ((InterpreterShip)s).service();
+        }
+
     }
-    public static int krunk=0;
 }