major refactoring, added token inboxes/outboxes
authoradam <adam@megacz.com>
Thu, 23 Nov 2006 11:45:32 +0000 (12:45 +0100)
committeradam <adam@megacz.com>
Thu, 23 Nov 2006 11:45:32 +0000 (12:45 +0100)
29 files changed:
fleet.g
src/edu/berkeley/fleet/CodeBag.java
src/edu/berkeley/fleet/DataInbox.java [new file with mode: 0644]
src/edu/berkeley/fleet/DataOutbox.java [new file with mode: 0644]
src/edu/berkeley/fleet/Fleet.java
src/edu/berkeley/fleet/FleetParser.java
src/edu/berkeley/fleet/Inbox.java [new file with mode: 0644]
src/edu/berkeley/fleet/InboxPort.java [deleted file]
src/edu/berkeley/fleet/Instruction.java
src/edu/berkeley/fleet/InstructionPort.java
src/edu/berkeley/fleet/Literal.java
src/edu/berkeley/fleet/Log.java
src/edu/berkeley/fleet/Outbox.java [new file with mode: 0644]
src/edu/berkeley/fleet/OutboxPort.java [deleted file]
src/edu/berkeley/fleet/Port.java
src/edu/berkeley/fleet/Ship.java
src/edu/berkeley/fleet/TokenInPort.java [deleted file]
src/edu/berkeley/fleet/TokenInbox.java [new file with mode: 0644]
src/edu/berkeley/fleet/TokenOutPort.java [deleted file]
src/edu/berkeley/fleet/TokenOutbox.java [new file with mode: 0644]
src/edu/berkeley/fleet/ships/BitBucketShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/ships/DebugShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/ships/FetchShip.java
src/edu/berkeley/fleet/ships/FifoShip.java
src/edu/berkeley/fleet/ships/HaltShip.java
src/edu/berkeley/fleet/ships/HomeworkCounter.java [new file with mode: 0644]
src/edu/berkeley/fleet/ships/MemoryReadShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/ships/TokenFifo.java [new file with mode: 0644]
src/edu/berkeley/fleet/ships/TokenSourceShip.java

diff --git a/fleet.g b/fleet.g
index 85ce537..4ef8ab6 100644 (file)
--- a/fleet.g
+++ b/fleet.g
@@ -20,10 +20,11 @@ Statement       = Instruction:: (Opcode ws!)? Source ws! Arrow ws! Port
 Opcode          = Triggered::   "triggered" OpcodeBody /ws
                 | UnTriggered::             OpcodeBody
 
-OpcodeBody      = ^"nop"      | ^"wait"     | ^"discard"     
-                | ^"nop+ack"  | ^"wait+ack" | ^"discard+ack" 
-                | ^"copy"     | ^"move"     | ^"accept"
-                | ^"copy+ack" | ^"move+ack" | ^"accept+ack"
+OpcodeBody      = ^"nop"        | ^"wait"     | ^"discard"     
+                | ^"nop+ack"    | ^"wait+ack" | ^"discard+ack" 
+                | ^"copy"       | ^"move"     | ^"accept"
+                | ^"copy+ack"   | ^"move+ack" | ^"accept+ack"
+                | ^"synthesize" | ^"synthesize+ack"
 
 Arrow           = ^"->"
                 | ^"-[*]->"
index fc1a9af..64edd4b 100644 (file)
@@ -2,6 +2,7 @@ package edu.berkeley.fleet;
 
 import java.util.*;
 
+/** a codebag */
 public class CodeBag {
 
     private static int max_allocated_descriptor = 1;
diff --git a/src/edu/berkeley/fleet/DataInbox.java b/src/edu/berkeley/fleet/DataInbox.java
new file mode 100644 (file)
index 0000000..b0afd28
--- /dev/null
@@ -0,0 +1,24 @@
+package edu.berkeley.fleet;
+
+import static edu.berkeley.fleet.Instruction.IgnoreCopyTake.*;
+import java.util.*;
+
+public class DataInbox extends Inbox {
+
+    public DataInbox(Ship ship, String name) {
+        super(ship, name);
+    }
+
+    void addDataFromFabric(int data) {
+        addItemFromFabric(data);
+    }
+
+    public boolean dataReadyForShip() {
+        return super.itemReadyForShip();
+    }
+
+    public int removeDataForShip() {
+        return super.accept();
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/DataOutbox.java b/src/edu/berkeley/fleet/DataOutbox.java
new file mode 100644 (file)
index 0000000..8e2f828
--- /dev/null
@@ -0,0 +1,21 @@
+package edu.berkeley.fleet;
+import static edu.berkeley.fleet.Instruction.IgnoreCopyTake.*;
+
+public class DataOutbox extends Outbox {
+
+    public DataOutbox(Ship ship, String name) {
+        super(ship, name);
+    }
+
+    public void addDataFromShip(int data) {
+        addItemFromShip(data);
+    }
+
+    public boolean readyForDataFromShip() {
+        return super.readyForItemFromShip();
+    }
+
+    protected void send(Port port, int data) {
+        getFleet().sendData(this, data, port);
+    }
+}
index b1e2ac9..7a9cc9e 100644 (file)
@@ -62,4 +62,14 @@ public class Fleet {
             return false;
         }
     }
+
+    public void sendToken(Port source, Port dest) {
+        Log.token(source, dest);
+        dest.addTokenFromFabric();
+    }
+
+    public void sendData(Port source, int data, Port dest) {
+        Log.data(data+"", source, dest);
+        dest.addDataFromFabric(data);
+    }
 }
index 7130f7e..85fc297 100644 (file)
@@ -13,6 +13,33 @@ import static edu.berkeley.fleet.Instruction.IgnoreCopyTake.*;
 public class FleetParser {
 
     public static void main(String[] s) throws Exception {
+        for(int i=0; i<s.length; i++) {
+            if (s[i].startsWith("--color=")) {
+                String val = s[i].substring(s[i].indexOf('=')+1);
+                if (val.equals("on")) {
+                    Log.ansi_color = true;
+                    continue;
+                } else if (val.equals("off")) {
+                    Log.ansi_color = false;
+                    continue;
+                }
+            } else if (s[i].startsWith("--inboxes=")) {
+                String val = s[i].substring(s[i].indexOf('=')+1);
+                if (val.equals("configured")) {
+                    DataInbox.defaultInstruction =
+                        new Instruction(null, null, Integer.MAX_VALUE, TAKE, false, false, true);
+                    continue;
+                } else if (val.equals("unconfigured")) {
+                    DataInbox.defaultInstruction = null;
+                    continue;
+                }
+            }
+            System.out.println("Fleeterpreter usage:");
+            System.out.println("");
+            System.out.println("  --color={on|off}");
+            System.out.println("  --inboxes={configured|unconfigured}");
+            System.exit(-1);
+        }
         go(new InputStreamReader(System.in));
     }
 
@@ -131,16 +158,18 @@ public class FleetParser {
                 PortReference s = portReference(t.child(1));
                 Instruction inst = null;
                 if (opcodebody==null)         inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
-                else if (opcodebody.head().equals("nop"))          inst = new Instruction(s, d, count, IGNORE, false,  trigger, false);
-                else if (opcodebody.head().equals("wait"))         inst = new Instruction(s, d, count, COPY,   false,  trigger, false);
-                else if (opcodebody.head().equals("discard"))      inst = new Instruction(s, d, count, TAKE,   false,  trigger, false);
-                else if (opcodebody.head().equals("nop+ack"))      inst = new Instruction(s, d, count, IGNORE, true,   trigger, false);
-                else if (opcodebody.head().equals("wait+ack"))     inst = new Instruction(s, d, count, COPY,   true,   trigger, false);
-                else if (opcodebody.head().equals("discard+ack"))  inst = new Instruction(s, d, count, TAKE,   true,   trigger, false);
-                else if (opcodebody.head().equals("copy"))         inst = new Instruction(s, d, count, COPY,   false,  trigger, true);
-                else if (opcodebody.head().equals("copy+ack"))     inst = new Instruction(s, d, count, COPY,   true,   trigger, true);
-                else if (opcodebody.head().equals("move"))         inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
-                else if (opcodebody.head().equals("move+ack"))     inst = new Instruction(s, d, count, TAKE,   true,   trigger, true);
+                else if (opcodebody.head().equals("nop"))            inst = new Instruction(s, d, count, IGNORE, false,  trigger, false);
+                else if (opcodebody.head().equals("synthesize"))     inst = new Instruction(s, d, count, IGNORE, false,  trigger, true);
+                else if (opcodebody.head().equals("synthesize+ack")) inst = new Instruction(s, d, count, IGNORE, true,   trigger, true);
+                else if (opcodebody.head().equals("wait"))           inst = new Instruction(s, d, count, COPY,   false,  trigger, false);
+                else if (opcodebody.head().equals("discard"))        inst = new Instruction(s, d, count, TAKE,   false,  trigger, false);
+                else if (opcodebody.head().equals("nop+ack"))        inst = new Instruction(s, d, count, IGNORE, true,   trigger, false);
+                else if (opcodebody.head().equals("wait+ack"))       inst = new Instruction(s, d, count, COPY,   true,   trigger, false);
+                else if (opcodebody.head().equals("discard+ack"))    inst = new Instruction(s, d, count, TAKE,   true,   trigger, false);
+                else if (opcodebody.head().equals("copy"))           inst = new Instruction(s, d, count, COPY,   false,  trigger, true);
+                else if (opcodebody.head().equals("copy+ack"))       inst = new Instruction(s, d, count, COPY,   true,   trigger, true);
+                else if (opcodebody.head().equals("move"))           inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
+                else if (opcodebody.head().equals("move+ack"))       inst = new Instruction(s, d, count, TAKE,   true,   trigger, true);
                 else if (opcodebody.head().equals("accept"))         inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
                 else if (opcodebody.head().equals("accept+ack"))     inst = new Instruction(s, d, count, TAKE,   true,   trigger, true);
                 cb.add(inst);
diff --git a/src/edu/berkeley/fleet/Inbox.java b/src/edu/berkeley/fleet/Inbox.java
new file mode 100644 (file)
index 0000000..795fa06
--- /dev/null
@@ -0,0 +1,114 @@
+package edu.berkeley.fleet;
+
+import static edu.berkeley.fleet.Instruction.IgnoreCopyTake.*;
+import java.util.*;
+
+/** this is a generic inbox which stores <32-bit items (tokens or data) */
+public class Inbox extends InstructionPort {
+
+    static Instruction defaultInstruction =
+        new Instruction(null, null, Integer.MAX_VALUE, TAKE, false, false, true);
+
+
+    // private data //////////////////////////////////////////////////////////////////////////////
+
+    /** data which has arrived from the switch fabric but not been acted on */
+    private Queue<Integer> itemsFromFabric = new LinkedList<Integer>();
+
+    /** a datum which has been presented to the ship */
+    private int itemPresentedToShip;
+
+    /** true iff data is currently being presented to the ship */
+    private boolean itemReadyForShip = false;
+
+    /** if an ack token is pending, this is where it should be sent once the item is accepted */
+    private Port ackDestinationUponAccept;
+
+
+    // protected methods /////////////////////////////////////////////////////////////////////////
+
+    Inbox(Ship ship, String name) {
+        super(ship, name);
+
+        // default standing move
+        if (defaultInstruction != null)
+            addInstruction(defaultInstruction);
+    }
+
+    /** subclasses invoke this when items arrive from the fabric */
+    protected final void addItemFromFabric(int data) {
+        itemsFromFabric.add(data);
+    }
+
+    /** true iff data is ready for the ship to accept */
+    protected final boolean itemReadyForShip() {
+        return itemReadyForShip;
+    }
+
+    /** accpets (removes) an item -- invoked by the ship */
+    protected final int accept() {
+        if (!itemReadyForShip)
+            throw new RuntimeException("invoked accept() on an inbox which does not have items ready; your ship is buggy");
+        itemReadyForShip = false;
+        if (ackDestinationUponAccept != null) {
+            getFleet().sendToken(this, ackDestinationUponAccept);
+            ackDestinationUponAccept = null;
+        }
+        return itemPresentedToShip;
+    }
+
+    /** invoked by superclass */
+    protected final boolean service(Instruction instruction) {
+
+        // if data is stuck on itemPresentedToShip, wait for it to go somewhere before
+        // considering additional instructions
+        if (itemReadyForShip) return false;
+
+        // if no instruction waiting, do nothing
+        if (instruction == null) return false;
+
+        // check firing conditions
+        if (instruction.trigger)
+            throw new RuntimeException("invalid instruction: " + instruction +
+                                       " (attempts to use trigger on an inbox)");
+        if (instruction.dataIn != IGNORE && itemsFromFabric.size()==0) return false;
+
+        // consume inbound data+token
+        switch(instruction.dataIn) {
+            case COPY:
+                itemPresentedToShip = itemsFromFabric.peek();
+                break;
+            case TAKE:
+                itemPresentedToShip = itemsFromFabric.remove();
+                break;
+        }
+
+        // if dataOut, present data to the ship
+        if (instruction.dataOut) {
+            itemReadyForShip = true;
+
+            // and make note of the fact that we need to send an ack (if requested)
+            if (instruction.ack)
+                ackDestinationUponAccept = instruction.destination.resolve(getShip().getFleet());
+
+        } else if (instruction.ack) {
+
+            // if dataOut is not set, we can send the data immediately
+            getFleet().sendToken(this, instruction.destination.resolve(getShip().getFleet()));
+        }
+        return true;
+    }
+
+    protected void shutdown() {
+        if (itemReadyForShip)
+            Log.println(Log.red(" WARNING: a datum ("+itemPresentedToShip+") was left in inbox " +
+                                this + " -- the ship has not consumed it"));
+                        
+        if (itemsFromFabric.size() > 0) {
+            Log.println(Log.red(" WARNING: you left data on the input to inbox " + this + ":"));
+            for(int i : itemsFromFabric)
+                Log.println("  " + i);
+        }
+        super.shutdown(true);
+    }
+}
diff --git a/src/edu/berkeley/fleet/InboxPort.java b/src/edu/berkeley/fleet/InboxPort.java
deleted file mode 100644 (file)
index bae09b2..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-package edu.berkeley.fleet;
-
-import static edu.berkeley.fleet.Instruction.IgnoreCopyTake.*;
-import java.util.*;
-
-public class InboxPort extends InstructionPort {
-
-    public static final Instruction defaultInstruction =
-        new Instruction(null, null, Integer.MAX_VALUE, TAKE, false, false, true);
-
-    public InboxPort(Ship ship, String name) {
-        super(ship, name);
-
-        // default standing move
-        addInstruction(defaultInstruction);
-    }
-
-    // data in from the switch fabric
-    private Queue<Integer> dataIn = new LinkedList<Integer>();
-    public void addData(int data) { dataIn.add(data); }
-    public void addToken() { throw new RuntimeException("inboxes do not accept tokens!"); }
-
-    // data out to the ship
-    private boolean empty = true;
-    private int dataOut;
-    private Port tokenDestination;
-
-    public boolean empty() { return empty; }
-    public int remove() {
-        if (empty)
-            throw new RuntimeException("called remove() on an empty() inbox");
-        empty = true;
-        if (tokenDestination != null) {
-            Log.token(this, tokenDestination);
-            tokenDestination.addToken();
-            tokenDestination = null;
-        }
-        return dataOut;
-    }
-
-    public boolean service(Instruction instruction) {
-
-        // if data is stuck on dataOut, wait for it to go somewhere
-        if (!empty) return false;
-
-        // if no instruction waiting, do nothing
-        if (instruction == null) return false;
-
-        // check firing conditions
-        if (instruction.trigger)
-            throw new RuntimeException("you cannot send a triggered instruction to an inbox!");
-        if (instruction.dataIn != IGNORE && dataIn.size()==0) return false;
-
-        // consume inbound data+token
-        int data = 0;
-        switch(instruction.dataIn) {
-            case COPY:
-                dataOut = dataIn.peek();
-                break;
-            case TAKE:
-                dataOut = dataIn.remove();
-                break;
-
-        }
-
-        if (instruction.dataOut) {
-            empty = false;
-            if (instruction.ack)
-                tokenDestination = instruction.destination.resolve(getShip().getFleet());
-
-        } else if (instruction.ack) {
-            Port p = instruction.destination.resolve(getShip().getFleet());
-            Log.token(this, p);
-            p.addToken();
-        }
-        return true;
-    }
-
-    public void shutdown() {
-        if (!empty)
-            Log.println(Log.red(" WARNING: a datum ("+dataOut+") was left in inbox " + this + " -- the ship has not consumed it"));
-                        
-        if (dataIn.size() > 0) {
-            Log.println(Log.red(" WARNING: you left data on the input to inbox " + this + ":"));
-            for(int i : dataIn)
-                Log.println("  " + i);
-        }
-        super.shutdown(true);
-    }
-}
index b4485f5..369c37e 100644 (file)
@@ -1,6 +1,6 @@
 package edu.berkeley.fleet;
 
-/** an instruction within a codebag, as specified in am10 */
+/** an instruction within a codebag, as specified in am10; this class is immutable */
 public class Instruction extends Dispatchable {
 
     public final PortReference source;
@@ -43,7 +43,7 @@ public class Instruction extends Dispatchable {
         if (trigger) ret.append("triggered ");
         switch(dataIn) {
             case IGNORE:
-                ret.append("nop");
+                ret.append(dataOut ? "synthesize" : "nop");
                 break;
             case COPY:
                 ret.append(dataOut ? "copy" : "wait");
index 415ad1c..14638ce 100644 (file)
@@ -2,15 +2,24 @@ package edu.berkeley.fleet;
 
 import java.util.*;
 
-/** common superclass for any port which can take an instruction: inbox/outbox/tokenoutbox */
+/** anything that has a source (instruction horn) address on the switch fabric */
 public abstract class InstructionPort extends Port {
 
-    public InstructionPort(Ship ship, String name) {
+    /** the currently executing instruction */
+    Instruction currentlyExecuting = null;
+
+    /** all instructions waiting to be executed (excludes currentlyExecuting) */
+    Queue<Instruction> instructions = new LinkedList<Instruction>();
+
+    /** the count field of currentlyExecuting, taking into account actions already performed */
+    int currentlyExecutingCount;
+
+    InstructionPort(Ship ship, String name) {
         super(ship, name);
     }
 
-    /** add an instruction to the box */
-    public void addInstruction(Instruction instr) {
+    /** an instruction arrives from the instruction horn */
+    void addInstruction(Instruction instr) {
         if (currentlyExecuting != null && currentlyExecuting.count == Integer.MAX_VALUE) {
             currentlyExecuting = null;
             currentlyExecutingCount = 0;
@@ -23,35 +32,27 @@ public abstract class InstructionPort extends Port {
         }
     }
 
-    // inherited from Port
-    public abstract void addData(int data);
-
-    Instruction currentlyExecuting = null;
-    Queue<Instruction> instructions = new LinkedList<Instruction>();
-    int currentlyExecutingCount;
-
-
     protected void shutdown(boolean leaveAsInbox) {
-        if (leaveAsInbox) {
+        if (leaveAsInbox && DataInbox.defaultInstruction != null) {
             if (currentlyExecuting == null) {
                 Log.println(Log.red(" WARNING: you did not leave a standing move on inbox-port " + this));
                 return;
-            } else {
-                if (currentlyExecuting.count != Integer.MAX_VALUE
-                    || currentlyExecuting.dataIn != Instruction.IgnoreCopyTake.TAKE
-                    || currentlyExecuting.ack
-                    || currentlyExecuting.trigger
-                    || !currentlyExecuting.dataOut) {
-                    Log.println(Log.red(" WARNING: you did not leave the correct standing move on inbox-port " + this)+
-                                "\n            found:    " + currentlyExecuting
-                                );
-                    return;
-                }
+            }
+            if (currentlyExecuting.count != Integer.MAX_VALUE
+                || currentlyExecuting.dataIn != Instruction.IgnoreCopyTake.TAKE
+                || currentlyExecuting.ack
+                || currentlyExecuting.trigger
+                || !currentlyExecuting.dataOut) {
+                Log.println(Log.red(" WARNING: you did not leave the correct standing move on inbox-port " + this)+
+                            "\n            found:    " + currentlyExecuting
+                            );
+                return;
             }
             currentlyExecuting = null;
         }
         if (currentlyExecuting != null || instructions.size() > 0) {
-            Log.println(Log.red(" WARNING: you left instructions on the instruction queue of port " + this + "; they are:"));
+            Log.println(Log.red(" WARNING: you left instructions on the instruction queue of port " +
+                                this + "; they are:"));
             if (currentlyExecuting != null)
                 Log.println("   " + currentlyExecuting);
             for(Instruction i : instructions)
@@ -61,10 +62,10 @@ public abstract class InstructionPort extends Port {
 
     // interface to subclass ///////////////////////////////////////////////////////////////////////
 
-    /** this will be invoked periodically; should return true to "consume" an instruction */
+    /** this will be invoked periodically; should return true to "consume" an instruction, false to leave it executing */
     protected abstract boolean service(Instruction instr);
 
-    public void service() {
+    protected final void service() {
         if (currentlyExecutingCount <= 0)
             currentlyExecuting = null;
         if (currentlyExecuting == null && instructions.size() > 0) {
index e9e9a9c..a4c0b77 100644 (file)
@@ -1,5 +1,6 @@
 package edu.berkeley.fleet;
 
+/** represents a literal; currently handled in an extremely hoakey fashion */
 public class Literal {
 
     public static class LiteralDatum extends Dispatchable {
@@ -19,7 +20,7 @@ public class Literal {
             for(int i=0; i<count; i++) {
                 Port port = destination.resolve(fleet);
                 Log.data((isCodeBag?(CodeBag.getCodeBagByDescriptor(getData())+""):(getData()+"")), null, port);
-                port.addData(getData());
+                port.addDataFromFabric(getData());
             }
         }
         public String toString() {
@@ -48,7 +49,7 @@ public class Literal {
             this.destination = destination;
         }
         public void dispatch(Fleet fleet) {
-            destination.resolve(fleet).addToken();
+            destination.resolve(fleet).addTokenFromFabric();
         }
         public String toString() {
             return "token -> "+destination;
index 0deb246..fec2893 100644 (file)
@@ -3,6 +3,8 @@ import java.io.*;
 
 public class Log {
 
+    public static boolean ansi_color = true;
+
     public static PrintWriter log = new PrintWriter(new OutputStreamWriter(System.out));
 
     public static void print(Object o) {
@@ -34,24 +36,17 @@ public class Log {
         println(purple("   token: ") + (source + " -> " + purple(dest+"")));
     }
 
-    //public static String black(Object o) { return "\033[30m"+o+"\033[0m"; }
-    public static String black(Object o) { return o+""; }
-    //public static String clreol() { return "\033[0K"; }
     public static String clreol() { return ""; }
-    public static String red(Object o) { return "\033[31m"+o+"\033[0m"; }
-    //public static String red(Object o) { return o+""; }
-    public static String green(Object o) { return "\033[32m"+o+"\033[0m"; }
-    //public static String green(Object o) { return o+""; }
-    public static String yellow(Object o) { return "\033[33m"+o+"\033[0m"; }
-    //public static String yellow(Object o) { return o+""; }
-    //public static String blue(Object o) { return "\033[34m"+o+"\033[0m"; }
-    public static String blue(Object o) { return o+""; }
-    public static String purple(Object o) { return "\033[35m"+o+"\033[0m"; }
-    //public static String purple(Object o) { return o+""; }
-    public static String cyan(Object o) { return "\033[36m"+o+"\033[0m"; }
-    //public static String cyan(Object o) { return o+""; }
-    public static String invert(Object o) { return "\033[7m"+o+"\033[0m"; }
-    public static String bold(Object o) { return "\033[1m"+o+"\033[0m"; }
+
+    public static String black(Object o) { if (!ansi_color) return o+""; return o+""; }
+    public static String red(Object o) { if (!ansi_color) return o+""; return "\033[31m"+o+"\033[0m"; }
+    public static String green(Object o) { if (!ansi_color) return o+""; return "\033[32m"+o+"\033[0m"; }
+    public static String yellow(Object o) { if (!ansi_color) return o+""; return "\033[33m"+o+"\033[0m"; }
+    public static String blue(Object o) { if (!ansi_color) return o+""; return o+""; }
+    public static String purple(Object o) { if (!ansi_color) return o+""; return "\033[35m"+o+"\033[0m"; }
+    public static String cyan(Object o) { if (!ansi_color) return o+""; return "\033[36m"+o+"\033[0m"; }
+    public static String invert(Object o) { if (!ansi_color) return o+""; return "\033[7m"+o+"\033[0m"; }
+    public static String bold(Object o) { if (!ansi_color) return o+""; return "\033[1m"+o+"\033[0m"; }
 
     public static String indent(String s, String indent) {
         StringBuffer ret = new StringBuffer();
diff --git a/src/edu/berkeley/fleet/Outbox.java b/src/edu/berkeley/fleet/Outbox.java
new file mode 100644 (file)
index 0000000..ba089bb
--- /dev/null
@@ -0,0 +1,85 @@
+package edu.berkeley.fleet;
+import static edu.berkeley.fleet.Instruction.IgnoreCopyTake.*;
+
+public abstract class Outbox extends InstructionPort {
+
+    /** are we ready to accept another item from the ship? */
+    private boolean readyForItemFromShip = true;
+
+    /** data which has been presented by the ship and is waiting to depart */
+    private int     itemPresentedByShip;
+
+    /** number of tokens queued on the trigger input */
+    private int     triggersReceived = 0;
+
+    protected Outbox(Ship ship, String name) {
+        super(ship, name);
+    }
+
+    protected final boolean readyForItemFromShip() {
+        return readyForItemFromShip;
+    }
+
+    final void addTokenFromFabric() {
+        triggersReceived++;
+    }
+
+    protected final boolean service(Instruction instruction) {
+
+        // if no instruction waiting, do nothing
+        if (instruction == null) return false;
+
+        // check firing conditions
+        if (instruction.trigger && triggersReceived <= 0) return false;
+        if (instruction.dataIn != IGNORE && readyForItemFromShip) return false;
+        
+        // consume trigger
+        if (instruction.trigger) triggersReceived--;
+
+        // consume item
+        int data = 0;
+        switch(instruction.dataIn) {
+            case COPY:
+                data = itemPresentedByShip;
+                break;
+            case TAKE:
+                data = itemPresentedByShip;
+                readyForItemFromShip = true;
+                break;
+        }
+
+        if (instruction.dataOut) {
+
+            // if item to be transmitted, send it
+            send(instruction.destination.resolve(getShip().getFleet()), data);
+            if (instruction.ack)
+                throw new RuntimeException("outboxes may not send acks!");
+
+        } else if (instruction.ack) {
+
+            // if no item was sent, we might still send an ack
+            getFleet().sendToken(this, instruction.destination.resolve(getShip().getFleet()));
+        }
+
+        return true;
+    }
+
+    /** this is invoked to transmit data; the subclass decides if it is a token or not */
+    protected abstract void send(Port port, int data);
+
+    /** subclass invokes this to add an item from the ship */
+    protected final void addItemFromShip(int data) {
+        if (!readyForItemFromShip)
+            throw new RuntimeException("tried to add an item to an outbox which was not ready!  you have a buggy ship!");
+        readyForItemFromShip = false;
+        itemPresentedByShip = data;
+    }
+
+    void shutdown() {
+        if (!readyForItemFromShip)
+            Log.println(Log.red(" WARNING: you left a value ("+itemPresentedByShip+") on outbox port " + this));
+        if (triggersReceived > 0)
+            Log.println(Log.red(" WARNING: you left a token on the trigger input to port " + this));
+        super.shutdown(false);
+    }
+}
diff --git a/src/edu/berkeley/fleet/OutboxPort.java b/src/edu/berkeley/fleet/OutboxPort.java
deleted file mode 100644 (file)
index b79a74f..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-package edu.berkeley.fleet;
-import static edu.berkeley.fleet.Instruction.IgnoreCopyTake.*;
-
-public class OutboxPort extends InstructionPort {
-
-    public OutboxPort(Ship ship, String name) {
-        super(ship, name);
-    }
-
-    // data in from the ship
-    private boolean empty = true;
-    private int     dataIn;
-
-    public boolean empty() { return empty; }
-
-    /** number of tokens queued on the trigger input */
-    private int trigger = 0;
-    public void addToken() { trigger++; }
-
-    public void addData(int data) {
-        if (!empty)
-            throw new RuntimeException("tried to add data to a non-empty outbox!  you have a buggy ship!");
-        empty = false;
-        dataIn = data;
-    }
-
-    public boolean service(Instruction instruction) {
-
-        // if no instruction waiting, do nothing
-        if (instruction == null) return false;
-
-        // check firing conditions
-        if (instruction.trigger && trigger <= 0) return false;
-        if (instruction.dataIn != IGNORE && empty) return false;
-        
-        // consume inbound data+token
-        if (instruction.trigger) trigger--;
-        int data = 0;
-        switch(instruction.dataIn) {
-            case COPY:
-                data = dataIn;
-                break;
-            case TAKE:
-                data = dataIn;
-                empty = true;
-                break;
-        }
-
-        if (instruction.dataOut) {
-            Port port = instruction.destination.resolve(getShip().getFleet());
-            Log.data(data+"", this, port);
-            port.addData(data);
-            if (instruction.ack)
-                throw new RuntimeException("outboxes may not send acks!");
-
-        } else if (instruction.ack) {
-            Port p = instruction.destination.resolve(getShip().getFleet());
-            Log.token(this, p);
-            p.addToken();
-        }
-
-        return true;
-    }
-
-    public void shutdown() {
-        if (!empty)
-            Log.println(Log.red(" WARNING: you left a value ("+dataIn+") on outbox port " + this));
-        if (trigger > 0)
-            Log.println(Log.red(" WARNING: you left a token on the trigger input to port " + this));
-        super.shutdown(false);
-    }
-}
index ca049b0..0d865cb 100644 (file)
@@ -1,10 +1,10 @@
 package edu.berkeley.fleet;
 
-/** a destination on the switch fabric */
+/** anything that has a destination address on the switch fabric */
 public abstract class Port {
         
-    public final String name;
-    public final Ship ship;
+    private final String name;
+    private final Ship ship;
         
     public Port(Ship ship, String name) {
         this.ship = ship;
@@ -12,19 +12,25 @@ public abstract class Port {
         ship.addPort(name, this);
     }
 
-    public void service() { }
+    void service() { }
         
-    /** adds one token to the port */
-    public abstract void addToken();
+    /** adds one token to the port from the switch fabric side */
+    void addTokenFromFabric() { throw new RuntimeException("this should never happen!"); }
         
-    /** adds the included datum to the port */
-    public abstract void addData(int datum);
+    /** adds the included datum to the port from the switch fabric  side */
+    void addDataFromFabric(int datum)  { throw new RuntimeException("this should never happen!"); }
 
-    public Ship getShip() {
-        return ship;
-    }
+    /** adds one token to the port from the ship side */
+    public void addTokenFromShip() { throw new RuntimeException("this should never happen!"); }
+        
+    /** adds the included datum to the port from the switch fabric side */
+    public void addDataFromShip(int datum) { throw new RuntimeException("this should never happen!"); }
+
+    public Ship getShip() { return ship; }
+
+    public Fleet getFleet() { return getShip().getFleet(); }
 
     public String toString() { return ship+"."+name; }
 
-    public abstract void shutdown();
+    abstract void shutdown();
 }
index 8eb93b4..c85d7d0 100644 (file)
@@ -8,12 +8,13 @@ import edu.berkeley.sbp.util.*;
 import java.util.*;
 import java.io.*;
 
+/** a ship, which belongs to a fleet and which may have many ports */
 public abstract class Ship {
         
-    HashMap<String,Port> ports = new HashMap<String,Port>();
+    private HashMap<String,Port> ports = new HashMap<String,Port>();
 
     private String name;
-    protected Fleet fleet;
+    private Fleet fleet;
 
     /** You should instantiate a bunch of Inboxes and Outboxes in your constructor */
     public Ship(Fleet fleet, String name) {
@@ -44,7 +45,7 @@ public abstract class Ship {
         service();
     }
 
-    public void addPort(String name, Port port) {
+    void addPort(String name, Port port) {
         ports.put(name, port);
     }
 
diff --git a/src/edu/berkeley/fleet/TokenInPort.java b/src/edu/berkeley/fleet/TokenInPort.java
deleted file mode 100644 (file)
index 990ba89..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-package edu.berkeley.fleet;
-
-public class TokenInPort extends Port {
-
-    private int tokens = 0;
-
-    public TokenInPort(Ship ship, String name) {
-        super(ship, name);
-    }
-
-    public void addToken() {
-        tokens++;
-    }
-
-    public void addData(int data) {
-        throw new RuntimeException("invalid!");
-    }
-
-    public boolean empty() {
-        return tokens==0;
-    }
-    
-    public void remove() {
-        tokens--;
-    }
-
-    public void shutdown() {
-        if (tokens > 0)
-            Log.println(Log.red(" WARNING: tokens were left on the input to " + this));
-    }
-}
diff --git a/src/edu/berkeley/fleet/TokenInbox.java b/src/edu/berkeley/fleet/TokenInbox.java
new file mode 100644 (file)
index 0000000..c18d690
--- /dev/null
@@ -0,0 +1,20 @@
+package edu.berkeley.fleet;
+
+public class TokenInbox extends Inbox {
+
+    public TokenInbox(Ship ship, String name) {
+        super(ship, name);
+    }
+
+    void addTokenFromFabric() {
+        addItemFromFabric(0);
+    }
+
+    public boolean tokenReadyForShip() {
+        return super.itemReadyForShip();
+    }
+
+    public void removeTokenForShip() {
+        super.accept();
+    }
+}
diff --git a/src/edu/berkeley/fleet/TokenOutPort.java b/src/edu/berkeley/fleet/TokenOutPort.java
deleted file mode 100644 (file)
index 790cc0f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-package edu.berkeley.fleet;
-
-/** a port which outputs only tokens */
-public class TokenOutPort extends InstructionPort {
-
-    private boolean empty = true;
-
-    public TokenOutPort(Ship ship, String name) {
-        super(ship, name);
-    }
-
-    public boolean empty() {
-        return empty;
-    }
-
-    public void addToken() {
-        if (!empty)
-            throw new RuntimeException("tried to add data to a non-empty tokenoutbox!  you have a buggy ship!");
-        empty = false;
-    }
-
-    public boolean service(Instruction instruction) {
-
-        // if no instruction waiting, do nothing
-        if (instruction == null) return false;
-
-        // check firing conditions
-        if (instruction.trigger)
-            throw new RuntimeException("you cannot send triggered instructions to token-output ports");
-
-        switch(instruction.dataIn) {
-            case COPY:
-                if (empty) return false;
-                break;
-            case TAKE:
-                if (empty) return false;
-                empty = true;
-                break;
-            case IGNORE:
-                if (!instruction.ack) return true;
-                // fall through
-        }
-        
-        Port port = instruction.destination.resolve(getShip().getFleet());
-        Log.token(this, port);
-        port.addToken();
-        return true;
-    }
-
-    public void addData(int data) {
-        throw new RuntimeException("invalid!");
-    }
-
-    public void shutdown() {
-        if (!empty)
-            Log.println(Log.red(" WARNING: you left a token on token-output port " + this));
-        super.shutdown(false);
-    }
-}
diff --git a/src/edu/berkeley/fleet/TokenOutbox.java b/src/edu/berkeley/fleet/TokenOutbox.java
new file mode 100644 (file)
index 0000000..d690c23
--- /dev/null
@@ -0,0 +1,25 @@
+package edu.berkeley.fleet;
+
+/** a port which outputs only tokens */
+public class TokenOutbox extends Outbox {
+
+    public TokenOutbox(Ship ship, String name) {
+        super(ship, name);
+    }
+
+    protected void send(Port port, int data) {
+        getFleet().sendToken(this, port);
+    }
+
+    public boolean readyForDataFromShip() {
+        return super.readyForItemFromShip();
+    }
+
+    public void addTokenFromShip() {
+        addItemFromShip(0);
+    }
+
+    public boolean readyForToken() {
+        return readyForDataFromShip();
+    }
+}
diff --git a/src/edu/berkeley/fleet/ships/BitBucketShip.java b/src/edu/berkeley/fleet/ships/BitBucketShip.java
new file mode 100644 (file)
index 0000000..36e61e3
--- /dev/null
@@ -0,0 +1,21 @@
+package edu.berkeley.fleet.ships;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class BitBucketShip extends Ship {
+
+    TokenInbox token = new TokenInbox(this, "token");
+    DataInbox   data  = new DataInbox(this, "data");
+
+    public BitBucketShip(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (token.tokenReadyForShip()) token.removeTokenForShip();
+        if (data.dataReadyForShip()) data.removeDataForShip();
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/ships/DebugShip.java b/src/edu/berkeley/fleet/ships/DebugShip.java
new file mode 100644 (file)
index 0000000..dc14450
--- /dev/null
@@ -0,0 +1,25 @@
+package edu.berkeley.fleet.ships;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class DebugShip extends Ship {
+
+    TokenInbox token = new TokenInbox(this, "token");
+    DataInbox   data  = new DataInbox(this, "data");
+
+    public DebugShip(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (token.tokenReadyForShip()) {
+            Log.println(Log.invert("   DEBUG: got a token"+Log.clreol()));
+            token.removeTokenForShip();
+        }
+        if (data.dataReadyForShip())
+            Log.println(Log.invert("   DEBUG: got a datum: " +  data.removeDataForShip()+Log.clreol()));
+    }
+
+}
index 2aa9f37..080f1a7 100644 (file)
@@ -6,33 +6,33 @@ import java.io.*;
 
 public class FetchShip extends Ship {
 
-    InboxPort    codebag = new InboxPort(this,  "codebag");
-    TokenInPort  release = new TokenInPort(this, "release");
-    TokenInPort  revoke  = new TokenInPort(this, "revoke");
-    TokenOutPort done    = new TokenOutPort(this, "done");
+    DataInbox    codebag = new DataInbox(this,  "codebag");
+    TokenInbox  release = new TokenInbox(this, "release");
+    TokenInbox  revoke  = new TokenInbox(this, "revoke");
+    TokenOutbox done    = new TokenOutbox(this, "done");
 
     public FetchShip(Fleet fleet, String name) {
         super(fleet, name);
     }
 
     public void service() {
-        if (codebag.empty()) return;
-        if (release.empty() && revoke.empty()) return;
-        if (!done.empty()) return;
-        int cbd = codebag.remove();
+        if (!codebag.dataReadyForShip()) return;
+        if (!release.tokenReadyForShip() && !revoke.tokenReadyForShip()) return;
+        if (!done.readyForToken()) return;
+        int cbd = codebag.removeDataForShip();
 
         CodeBag cb = CodeBag.getCodeBagByDescriptor(cbd);
-        if (!revoke.empty()) {
-            revoke.remove();
+        if (revoke.tokenReadyForShip()) {
+            revoke.removeTokenForShip();
             Log.print("revoking codebag: " + cb);
         } else {
-            release.remove();
+            release.removeTokenForShip();
             if (cb==null)
                 throw new RuntimeException("bogus codebag -- this should not happen");
             cb.dispatch(getFleet());
         }
 
-        done.addToken();
+        done.addTokenFromShip();
     }
 
 }
index 8cff71c..44195e9 100644 (file)
@@ -6,8 +6,8 @@ import java.io.*;
 
 public class FifoShip extends Ship {
 
-    InboxPort   in  = new InboxPort(this, "in");
-    OutboxPort  out = new OutboxPort(this, "out");
+    DataInbox   in  = new DataInbox(this, "in");
+    DataOutbox  out = new DataOutbox(this, "out");
 
     private Queue<Integer> fifo = new LinkedList<Integer>();
 
@@ -16,12 +16,12 @@ public class FifoShip extends Ship {
     }
 
     public void service() {
-        if (!in.empty()) {
-            fifo.add(in.remove());
+        if (in.dataReadyForShip()) {
+            fifo.add(in.removeDataForShip());
             //Log.println(name + ": fifo occupancy is now " + fifo.size() + " items");
         }
-        if (out.empty() && fifo.size() > 0) {
-            out.addData(fifo.remove());
+        if (out.readyForDataFromShip() && fifo.size() > 0) {
+            out.addDataFromShip(fifo.remove());
             //Log.println(name + ": fifo occupancy is now " + fifo.size() + " items");
         }
     }
index 3cd7746..d10e43f 100644 (file)
@@ -6,15 +6,15 @@ import java.io.*;
 
 public class HaltShip extends Ship {
 
-    TokenInPort in = new TokenInPort(this, "in");
+    TokenInbox in = new TokenInbox(this, "in");
 
     public HaltShip(Fleet fleet, String name) {
         super(fleet, name);
     }
 
     public void service() {
-        if (in.empty()) return;
-        in.remove();
+        if (!in.tokenReadyForShip()) return;
+        in.removeTokenForShip();
         getFleet().halt = true;
         Log.println(Log.yellow("    HALT: ====== halt ship got a token; halting the fleet ======"));
     }
diff --git a/src/edu/berkeley/fleet/ships/HomeworkCounter.java b/src/edu/berkeley/fleet/ships/HomeworkCounter.java
new file mode 100644 (file)
index 0000000..ee265ec
--- /dev/null
@@ -0,0 +1,38 @@
+package edu.berkeley.fleet.ships;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class HomeworkCounter extends Ship {
+
+    private int count = -1;
+
+    TokenOutbox zero     = new TokenOutbox(this, "zero");
+    TokenOutbox positive = new TokenOutbox(this, "positive");
+    DataInbox    load     = new DataInbox(this, "load");
+    TokenInbox  ask      = new TokenInbox(this, "ask");
+
+    public HomeworkCounter(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (!zero.readyForToken()) return;
+        if (!positive.readyForToken()) return;
+        if (load.dataReadyForShip()) {
+            count = load.removeDataForShip();
+            return;
+        }
+        if (ask.tokenReadyForShip()) {
+            ask.removeTokenForShip();
+            if (count > 0) {
+                count--;
+                positive.addTokenFromShip();
+            } else if (count<=0) {
+                zero.addTokenFromShip();
+            }
+        }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/ships/MemoryReadShip.java b/src/edu/berkeley/fleet/ships/MemoryReadShip.java
new file mode 100644 (file)
index 0000000..515351a
--- /dev/null
@@ -0,0 +1,46 @@
+package edu.berkeley.fleet.ships;
+
+import edu.berkeley.fleet.*;
+import java.util.*;
+import java.io.*;
+
+public class MemoryReadShip extends Ship {
+
+    boolean _loaded = false;
+    int _count = 0;
+    int _stride = 0;
+    int _addr = 0;
+
+    DataInbox  addr   = new DataInbox(this, "addr");
+    DataInbox  stride = new DataInbox(this, "stride");
+    DataInbox  count  = new DataInbox(this, "count");
+    DataOutbox data   = new DataOutbox(this, "data");
+    TokenOutbox done  = new TokenOutbox(this, "done");
+
+    public MemoryReadShip(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (_count > 0) {
+            if (!data.readyForDataFromShip()) return;
+            data.addDataFromShip(_addr>=fleet.mem.length ? 0 : fleet.mem[_addr]);
+            _count--;
+            _addr += _stride;
+            if (_count==0)
+                done.addTokenFromShip();
+        } else {
+            if (count.dataReadyForShip() &&
+                addr.dataReadyForShip() &&
+                stride.dataReadyForShip() &&
+                done.readyForToken() &&
+                data.readyForDataFromShip()) {
+
+                _count  = count.removeDataForShip();
+                _addr   = addr.removeDataForShip();
+                _stride = stride.removeDataForShip();
+            }
+        }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/ships/TokenFifo.java b/src/edu/berkeley/fleet/ships/TokenFifo.java
new file mode 100644 (file)
index 0000000..6ab4a86
--- /dev/null
@@ -0,0 +1,30 @@
+package edu.berkeley.fleet.ships;
+import edu.berkeley.fleet.*;
+
+import java.util.*;
+import java.io.*;
+
+public class TokenFifo extends Ship {
+
+    private int count = 0;
+
+    TokenOutbox out     = new TokenOutbox(this, "out");
+    TokenInbox  in      = new TokenInbox(this, "in");
+
+    public TokenFifo(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (in.tokenReadyForShip()) {
+            count++;
+            in.removeTokenForShip();
+            return;
+        }
+        if (count > 0 && out.readyForToken()) {
+            count--;
+            out.addTokenFromShip();
+        }
+    }
+
+}
index bd59010..8de78b2 100644 (file)
@@ -6,15 +6,15 @@ import java.io.*;
 
 public class TokenSourceShip extends Ship {
 
-    TokenOutPort out    = new TokenOutPort(this, "out");
+    TokenOutbox out    = new TokenOutbox(this, "out");
 
     public TokenSourceShip(Fleet fleet, String name) {
         super(fleet, name);
     }
 
     public void service() {
-        if (out.empty())
-            out.addToken();
+        if (out.readyForToken())
+            out.addTokenFromShip();
     }
 
     public void shutdown() {