Interpreter.java: add a Button and Dvi to the default fleet
[fleet.git] / src / edu / berkeley / fleet / interpreter / Interpreter.java
index c3ec582..a12906e 100644 (file)
@@ -3,127 +3,91 @@ import java.io.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.lang.reflect.*;
-import edu.berkeley.fleet.*;
 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.two.*;
 import edu.berkeley.fleet.util.*;
 
-public class Interpreter extends FleetTwoFleet implements Parser.FleetWithDynamicShips {
+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)
+                if (ordinal-- <= 0)
                     return s;
         return null;
     }
 
-    public int getWordWidth() { return 37; }
-    /** some "halt ship" can turn this on to stop the interpreter */
-    private HashMap<String,InterpreterShip> ships       = new HashMap<String,InterpreterShip>();
-    private BlockingQueue<Long>             debugStream = new LinkedBlockingQueue<Long>();
-
-    public int getWordSize() { return 37; }
-
-    public FleetProcess run(final byte[] instructions) {
-        try {
-            final FleetProcess fp = new FleetProcess() {
-                    public void dispatchInstruction(Instruction i) { throw new RuntimeException(); }
-                    public void invokeInstruction(Instruction i) { throw new RuntimeException("not supported"); }
-                    public Dock getDebugInputDock() { return null; }
-                    public BitVector readWord() {
-                        /*
-                        try {
-                            return debugStream.take();
-                        } catch (Exception e) {
-                            throw new RuntimeException(e);
-                            }*/
-                        throw new RuntimeException();
-                        }
-                    protected void _terminate() {
-                        // FIXME: hack
-                        ships = new HashMap<String,InterpreterShip>();
-                        debugStream = new LinkedBlockingQueue<Long>();
-                    }
-                };
-            new Thread() {
-                public void run() {
-                    try {
-                        // find the first icache
-                        InterpreterShip iscratch = null;
-                        for(Ship ship : Interpreter.this)
-                            if (ship.getClass().getSimpleName().equals("Memory")) {
-                                iscratch = (InterpreterShip)ship;
-                                break;
-                            }
-                        if (iscratch==null) {
-                            BufferedReader br =
-                                new BufferedReader(new InputStreamReader(new FileInputStream("ships/Memory.ship")));
-                            ShipDescription sd = new ShipDescription("Memory", br);
-                            iscratch = (InterpreterShip)Class.forName("edu.berkeley.fleet.interpreter.Memory")
-                                .getConstructor(new Class[] { Interpreter.class, String.class, ShipDescription.class })
-                                .newInstance(new Object[] { Interpreter.this, "memory", sd });
-                        }
-                        iscratch
-                            .getClass()
-                            .getMethod("boot", new Class[] { byte[].class })
-                            .invoke(iscratch, new Object[] { instructions });
-                        
-                        while(!fp.isTerminated())
-                            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(ANSI.yellow("    DONE: ====== FLEET is halted.  Have a nice day.  ======"));
-                        
-                    } catch (Exception e) {
-                        if (fp.isTerminated()) return;
-                        throw new RuntimeException(e);
-                    }
-                }
-            }.start();
-            return fp;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+    /** 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 dispatch(Instruction i, long address) {
-        Log.dispatch(i);
-           
-        if (i instanceof Instruction.Tail) {
-            Instruction.Tail ic = (Instruction.Tail)i;
-            ((InstructionDock)(ic.dock)).tailged--;
-
-        } else {
-            InterpreterDock sourceDock = (InterpreterDock)(((Instruction)i).dock);
-            ((InstructionDock)sourceDock).addInstruction(((Instruction)i));
+    public Interpreter(String[] ships, boolean logging) {
+        int i=0;
+        Log.quiet = !logging;
+        for(String s : ships) {
+            createShip(ships[i], ships[i]+"_"+i);
+            i++;
         }
     }
 
-    public Iterator<Ship> iterator() { return (Iterator<Ship>)(Object)ships.values().iterator(); }
-
-    public Ship createShip(String shipType, String shipname) {
+    private Ship createShip(String shipType, String shipname) {
         try {
+            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 });
-            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+shipType+".ship")));
-            ShipDescription sd = new ShipDescription(shipType, br);
+            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);
+            if (shipType.equals("Debug") && debugShip == null)
+                debugShip = ret;
             return ret;
         } catch (Exception e) {
             e.printStackTrace();
@@ -131,7 +95,8 @@ public class Interpreter extends FleetTwoFleet implements Parser.FleetWithDynami
         }
     }
 
-    public void debug(long 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()));
@@ -142,27 +107,17 @@ public class Interpreter extends FleetTwoFleet implements Parser.FleetWithDynami
 
     // Instruction Encoding /////////////////////////////////////////////////////////////////////////
 
-    public Dock getUniversalSource() { return null; }
-
-        public long getDestAddr(Path path) { throw new RuntimeException(); }
-        public long getBoxInstAddr(Dock box) { return ((InterpreterDock)box).getDestAddr(); }
-        public Path getPathByAddr(Dock source, long dest) { throw new RuntimeException(); }
-        public Destination getDestByAddr(long dest) {
-            /*
-            for(Ship ship : Interpreter.this)
-                for(Dock bb : ship)
-                    if (getDestAddr(bb.getDataDestination())==dest)
-                        return bb.getDataDestination();
-            */
-            return null;
-        }
-        public Dock getBoxByInstAddr(long dest) {
-            for(Ship ship : Interpreter.this)
-                for(Dock bb : ship)
-                    if (getBoxInstAddr(bb) == dest)
-                        return bb;
-            return null;
+    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;
+    }
 
 
     // ShipDescription //////////////////////////////////////////////////////////////////////////////
@@ -187,28 +142,17 @@ public class Interpreter extends FleetTwoFleet implements Parser.FleetWithDynami
             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("    ");
-                if ( b.isInputDock()) pw.print("Inbox");
-                if (!b.isInputDock()) pw.print("Outbox");
-                pw.print(" box_");
+                pw.print("    InterpreterDock box_");
                 pw.print(name);
-                pw.print(" = new ");
-                if ( b.isInputDock()) pw.print("Inbox");
-                if (!b.isInputDock()) pw.print("Outbox");
-                pw.print("(this, new String[] { ");
-                boolean first = true;
-                pw.print("\"\"");
-                pw.println("}, shipDescription.getDockDescription(\""+name+"\"));");
+                pw.print(" = new InterpreterDock(this, shipDescription.getDockDescription(\""+name+"\"));");
             }
             pw.println("");
-            pw.println("    public "+filename+"(Interpreter fleet, String name, ShipDescription sd) {");
-            pw.println("       super(fleet, name, sd);");
-            for(DockDescription b : sd)
-                pw.println("       addDock(\""+b.getName()+"\", box_"+b.getName()+");");
-            pw.println("    }");
-            pw.println("");
             pw.println(sd.getSection("fleeterpreter"));
             pw.println("}");
             pw.flush();
@@ -216,5 +160,80 @@ public class Interpreter extends FleetTwoFleet implements Parser.FleetWithDynami
         } catch (Exception e) { throw new RuntimeException(e); }
     }
 
-}
+    // Run //////////////////////////////////////////////////////////////////////////////
+
+    public FleetProcess run(final Instruction[] instructions) {
+        InterpreterProcess ip = initialize(instructions);
+        Thread ipt = new Thread(ip);
+        ipt.setDaemon(true);
+        ipt.start();
+        return ip;
+    }
+
+    public InterpreterProcess initialize(Instruction[] instr) {
+        return new InterpreterProcess(instr);
+    }
 
+    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();
+        }
+        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();
+        }
+        public InterpreterProcess(Instruction[] instructions) {
+            this.instructions = instructions;
+            for(Instruction i : instructions)
+                sendInstruction(i);
+        }
+        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 {
+                while(!isTerminated()) {
+                    flush();
+                }
+                for(InterpreterShip ship : ships.values())
+                    ship.reset();
+                debugStream.clear();
+            } catch (Exception e) {
+                if (isTerminated()) return;
+                throw new RuntimeException(e);
+            }
+        }
+
+        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();
+        }
+
+    }
+}