initial commit
authoradam <adam@megacz.com>
Fri, 15 Sep 2006 11:44:34 +0000 (12:44 +0100)
committeradam <adam@megacz.com>
Fri, 15 Sep 2006 11:44:34 +0000 (12:44 +0100)
12 files changed:
Makefile [new file with mode: 0644]
fleet.g [new file with mode: 0644]
src/edu/berkeley/fleet/AdderShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/Fleet.java [new file with mode: 0644]
src/edu/berkeley/fleet/FleetParser.java [new file with mode: 0644]
src/edu/berkeley/fleet/HaltShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/MemReadShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/MemWriteShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/OneProducerShip.java [new file with mode: 0644]
src/edu/berkeley/fleet/Program.java [new file with mode: 0644]
src/edu/berkeley/fleet/Ship.java [new file with mode: 0644]
test.fleet [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..3626bcd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+
+run: fleet.jar
+       java -cp lib/edu.berkeley.sbp.jar:fleet.jar edu.berkeley.fleet.FleetParser < test.fleet
+
+fleet.jar: $(shell find src -name \*.java) fleet.g
+       mkdir -p bin
+       cp fleet.g bin
+       javac -cp lib/edu.berkeley.sbp.jar -d bin $(shell find src -name \*.java)
+       cd bin; jar cvf ../$@ .
diff --git a/fleet.g b/fleet.g
new file mode 100644 (file)
index 0000000..965a712
--- /dev/null
+++ b/fleet.g
@@ -0,0 +1,55 @@
+// The FLEET Assembly Language Grammar
+// As specified in document 2005-ucies06
+
+// comments are included where the grammar had to go beyond the strict
+// "letter of the law" in ies06
+
+// Note that this is the *entire, complete* formal specification of
+// the grammar.  An equivalent lex+yacc grammar and support code would
+// be several times as long.
+
+Comment        = "//" ~[\n]* "\n"
+               | "/*" ~[\n]* "*/"
+
+w             = [\r\n ]*
+ws            = (w | Comment)* -> ~[\r\n ]
+
+s              = ws! Program ws!
+Program        = Program::
+                    (Directive ws!)*
+                    CodeBagBody
+
+Directive      = Memory::  "#memory" "{" (int +/ (ws! "," ws!)) "}" /ws
+               | Import::  "#import" [A-Za-z_.]++ /ws
+               | Ship::    "#ship" shipname ":" [A-Za-z_\.]++ /ws
+
+
+Statement      = Move ((ws ";")?)!
+               | CodeBag
+//             | ^"#define" Port Port                  /ws
+
+Move           = Source       ^"->"  Destination        /ws
+               | Source       ^"->*" Destination        /ws
+               | Port         ^":="  Source             /ws
+
+Destination    = Port +/ (ws! "," ws!)
+Source         = Port
+               | CodeBag
+CodeBagBody    = CodeBag:: (Statement +/ ws)
+CodeBag        = NamedCodeBag::
+                     name:(name ws! ":" ws!)?
+                     "{"
+                           ws! statements:(Statement +/ ws) ws!
+                     "}"
+                     (ws! ";")?!
+
+//Port           = Port::     shipname ("." portname)*
+Port           = Port::     shipname "." portname
+               | Port::     shipname
+shipname       = ShipName:: name (index?)
+portname       = PortName:: name (index?)
+name           = [A-Za-z0-9\[\]]**
+index          = "[" [0-9]+ "]"
+               | [0-9]+
+int            = [0-9]++
+
diff --git a/src/edu/berkeley/fleet/AdderShip.java b/src/edu/berkeley/fleet/AdderShip.java
new file mode 100644 (file)
index 0000000..8e203aa
--- /dev/null
@@ -0,0 +1,21 @@
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class AdderShip extends Ship {
+
+    Inbox in1  = new Inbox("in1");
+    Inbox in2  = new Inbox("in2");
+    Outbox out = new Outbox("out");
+
+    public AdderShip(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (!in1.empty() && !in2.empty())
+            out.add(in1.remove() + in2.remove());
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/Fleet.java b/src/edu/berkeley/fleet/Fleet.java
new file mode 100644 (file)
index 0000000..323f321
--- /dev/null
@@ -0,0 +1,45 @@
+package edu.berkeley.fleet;
+
+import edu.berkeley.sbp.*;
+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.*;
+
+public class Fleet {
+
+    /** 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>();
+
+    public HashMap<String,Ship> ships = new HashMap<String,Ship>();
+
+    public void go() {
+        while(!halt)
+            for(Ship ship : ships.values())
+                ship._service();
+    }
+
+    public Ship.Inbox getInbox(String ship, String port) {
+        Ship s = ships.get(ship);
+        if (s == null) throw new RuntimeException("unknown ship \""+ship+"\"");
+        Ship.Inbox ret = s.inboxes.get(port);
+        if (ret == null) throw new RuntimeException("unknown port \""+ship+"."+port+"\"");
+        return ret;
+    }
+
+    public Ship.Outbox getOutbox(String ship, String port) {
+        Ship s = ships.get(ship);
+        if (s == null) throw new RuntimeException("unknown ship \""+ship+"\"");
+        Ship.Outbox ret = s.outboxes.get(port);
+        if (ret == null) throw new RuntimeException("unknown port \""+ship+"."+port+"\"");
+        return ret;
+    }
+
+
+}
diff --git a/src/edu/berkeley/fleet/FleetParser.java b/src/edu/berkeley/fleet/FleetParser.java
new file mode 100644 (file)
index 0000000..7cd3dee
--- /dev/null
@@ -0,0 +1,59 @@
+package edu.berkeley.fleet;
+
+import edu.berkeley.sbp.*;
+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.*;
+
+public class FleetParser {
+
+    public static void main(String[] s) throws Exception {
+
+        InputStream grammarStream =
+            FleetParser.class.getClassLoader().getResourceAsStream("fleet.g");
+
+        Parser metaGrammarParser   = new CharParser(MetaGrammar.newInstance());
+        Tree<String> parsedGrammar = metaGrammarParser.parse(new CharInput(grammarStream)).expand1();
+        Grammar.Bindings gbr       = new AnnotationGrammarBindings(Program.class);
+        Union   mathGrammar        = Grammar.create(parsedGrammar, "s", gbr);
+        Parser  mathParser         = new CharParser(mathGrammar);
+
+        System.out.println("about to parse: tests/test.fleet");
+        Tree tree = mathParser.parse(new CharInput(System.in)).expand1();
+
+        // below is ugly voodoo which will go away very soon.  ignore it.
+        TreeFunctor tf = (TreeFunctor)tree.head();
+        Program program = (Program)tf.invoke(tree);
+        // above is ugly voodoo which will go away very soon.  ignore it.
+
+        System.out.println();
+        System.out.println("dispatching root codebag:");
+        System.out.println(program.root);
+
+        Fleet fleet = new Fleet();
+        program.configure(fleet);
+
+        System.out.println("memory before execution:");
+        System.out.print("  ");
+        for(int i=0; i<fleet.mem.length; i++)
+            System.out.print(fleet.mem[i] + " ");
+        System.out.println();
+
+        System.out.println();
+        System.out.println("enabling execution...");
+        fleet.go();
+        System.out.println("execution halted.");
+
+        System.out.println();
+        System.out.println("memory after execution:");
+        System.out.print("  ");
+        for(int i=0; i<fleet.mem.length; i++)
+            System.out.print(fleet.mem[i] + " ");
+        System.out.println();
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/HaltShip.java b/src/edu/berkeley/fleet/HaltShip.java
new file mode 100644 (file)
index 0000000..c28e2b5
--- /dev/null
@@ -0,0 +1,19 @@
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class HaltShip extends Ship {
+
+    Inbox in = new Inbox("in");
+
+    public HaltShip(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (!in.empty())
+            fleet.halt = true;
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/MemReadShip.java b/src/edu/berkeley/fleet/MemReadShip.java
new file mode 100644 (file)
index 0000000..96060fc
--- /dev/null
@@ -0,0 +1,21 @@
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class MemReadShip extends Ship {
+
+    Inbox addr  = new Inbox("addr");
+    Outbox data = new Outbox("data");
+
+    public MemReadShip(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        // note that the memory interface is pipelined (buffered)
+        if (!addr.empty())
+            data.add(fleet.mem[addr.remove()]);
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/MemWriteShip.java b/src/edu/berkeley/fleet/MemWriteShip.java
new file mode 100644 (file)
index 0000000..7c02b4b
--- /dev/null
@@ -0,0 +1,24 @@
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class MemWriteShip extends Ship {
+
+    Inbox addr  = new Inbox("addr");
+    Inbox data  = new Inbox("data");
+    Outbox done = new Outbox("done");
+
+    public MemWriteShip(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        // note that the memory interface is pipelined (buffered)
+        if (!addr.empty() && !data.empty()) {
+            fleet.mem[addr.remove()] = data.remove();
+            done.add(0);
+        }
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/OneProducerShip.java b/src/edu/berkeley/fleet/OneProducerShip.java
new file mode 100644 (file)
index 0000000..cdb149e
--- /dev/null
@@ -0,0 +1,19 @@
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class OneProducerShip extends Ship {
+
+    Outbox out = new Outbox("out");
+
+    public OneProducerShip(Fleet fleet, String name) {
+        super(fleet, name);
+    }
+
+    public void service() {
+        if (out.empty())
+            out.add(1);
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/Program.java b/src/edu/berkeley/fleet/Program.java
new file mode 100644 (file)
index 0000000..ff19413
--- /dev/null
@@ -0,0 +1,184 @@
+package edu.berkeley.fleet;
+
+import edu.berkeley.sbp.*;
+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 java.lang.reflect.*;
+
+public class Program {
+
+        Directive[] directives;
+        CodeBag root;
+        public Program(Directive[] directives, CodeBag root) {
+            this.root = root;
+            this.directives = directives;
+        }
+        public void configure(Fleet fleet) {
+            for(Directive directive : directives)
+                directive.configure(fleet);
+            root.dispatch(fleet);
+        }
+
+    // inner classes //////////////////////////////////////////////////////////////////////////////
+
+    public static @bind.as("NamedCodeBag") CodeBag codeBag(String name, Object[] statements) {
+        return codeBag(statements);
+    }
+
+    public static @bind.as("CodeBag") CodeBag codeBag(Object[] statements) {
+        CodeBag ret = new CodeBag();
+        for(Object s : statements) ret.add((Statement)s);
+        return ret;
+    }
+
+    public static @bind.as("->")       Statement move(Port source, Port[] dest) {
+        return new Move(source, dest);
+    }
+
+    public static @bind.as("->*")      Statement smove(Port source, Port[] dest) {
+        //return new SMove(source, dest);
+        return null;
+    }
+
+    public static @bind.as(":=")       Statement gets(Port dest, Port source) {
+        return new Move(source, new Port[] { dest });
+    }
+
+    public static @bind.as("Port") Port port(String ship, String port) {
+        return new Port(ship, port);
+    }
+    public static @bind.as("Port") Port port(String ship) {
+        return new Port(ship, null);
+    }
+
+    public static @bind.as("ShipName") String    shipname(String name, String index) { return index==null?name:name+index; }
+    public static @bind.as("PortName") String    portname(String name, String index) { return index==null?name:name+index; }
+
+    public static interface Source { }
+    public static interface Destination { }
+    public static interface Statement {
+        public void dispatch(Fleet fleet);
+    }
+
+    public static @bind.as("Program") Program program(Directive[] directives, CodeBag rootCodeBag) {
+        return new Program(directives, rootCodeBag);
+    }
+
+    public static abstract class Directive {
+        public void configure(Fleet fleet) {
+        }
+    }
+
+    public static @bind.as("Memory") MemoryDirective memory(String[] values) {
+        return new MemoryDirective(values);
+    }
+
+    public static class MemoryDirective extends Directive{
+        private int[] mem;
+        public MemoryDirective(String[] values) {
+            this.mem = new int[values.length];
+            for(int i=0; i<mem.length; i++)
+                mem[i] = Integer.parseInt(values[i]);
+        }
+        public void configure(Fleet fleet) {
+            fleet.mem = mem;
+        }
+    }
+
+    public static class ShipDirective extends Directive {
+        String shipname;
+        String classname;
+        public @bind.as("Ship") ShipDirective(String shipname, String classname) {
+            this.shipname = shipname;
+            this.classname = classname;
+        }
+        public void configure(Fleet fleet) {
+            for(String s : fleet.imports)
+                if (tryCreate(fleet, s))
+                    return;
+            throw new RuntimeException("unable to instantiate class " + classname);
+        }
+        private boolean tryCreate(Fleet fleet, String packagename) {
+            try {
+                Class c = Class.forName(packagename+"."+classname);
+                Constructor con = c.getConstructor(new Class[] { Fleet.class, String.class });
+                con.newInstance(new Object[] { fleet, shipname });
+                return true;
+            } catch (Exception e) {
+                return false;
+            }
+        }
+    }
+
+    public static class ImportDirective extends Directive {
+        String packagename;
+        public @bind.as("Import") ImportDirective(String packagename) {
+            this.packagename = packagename;
+        }
+        public void configure(Fleet fleet) {
+            fleet.imports.add(packagename);
+        }
+    }
+
+    public static class Move implements Statement {
+        Port source;
+        Port[] dest;
+        public Move(Port source, Port[] dest) { this.source = source; this.dest = dest; }
+        public void dispatch(Fleet fleet) {
+            Ship.Outbox ob = fleet.getOutbox(source.ship, source.port);
+            for(Port d : dest) {
+                Ship.Inbox ib = fleet.getInbox(d.ship, d.port);
+                ob.addDestination(ib);
+                System.out.println("instr: " + ob + " -> " + ib);
+            }
+        }
+        public String toString() {
+            StringBuffer sb = new StringBuffer();
+            sb.append(source + " -> ");
+            sb.append(dest[0]);
+            for(int i=1; i<dest.length; i++) {
+                sb.append(", " + dest[i]);
+            }
+            return sb.toString();
+        }
+    }
+
+    public static class Port implements Source, Destination {
+        String ship;
+        String port;
+        public Port(String ship, String port) {
+            this.ship = ship;
+            this.port = port;
+        }
+        public String toString() { return port==null?ship:ship+"."+port; }
+    }
+
+    public static class CodeBag extends ArrayList<Statement> implements Statement {
+        public void dispatch(Fleet fleet) {
+            for(Statement s : this)
+                s.dispatch(fleet);
+        }
+        public String toString() {
+            StringBuffer s = new StringBuffer();
+            for(Statement stmt : this) s.append("\n"+stmt);
+            return "{"+indentify(s.toString())+"\n}";
+        }
+    }
+
+    private static String indentify(String s) {
+        StringBuffer s2 = new StringBuffer();
+        for(int i=0; i<s.length(); i++) {
+            char c = s.charAt(i);
+            s2.append(c);
+            if (c == '\n')
+                s2.append("  ");
+        }
+        return s2.toString();
+    }
+
+}
diff --git a/src/edu/berkeley/fleet/Ship.java b/src/edu/berkeley/fleet/Ship.java
new file mode 100644 (file)
index 0000000..97c832a
--- /dev/null
@@ -0,0 +1,73 @@
+package edu.berkeley.fleet;
+
+import edu.berkeley.sbp.*;
+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.*;
+
+public abstract class Ship {
+
+    HashMap<String,Inbox> inboxes = new HashMap<String,Inbox>();
+    HashMap<String,Outbox> outboxes = new HashMap<String,Outbox>();
+    private String name;
+    protected Fleet fleet;
+
+    /** You should instantiate a bunch of Inboxes and Outboxes in your constructor */
+    public Ship(Fleet fleet, String name) {
+        this.name = name;
+        this.fleet = fleet;
+        fleet.ships.put(name, this);
+    }
+
+    public String toString() { return name; }
+
+    /**
+     *  Override this method, check inboxes for the data you need, and
+     *  if you find it, deposit results in an outbox; we'll take care
+     *  of the rest.
+     */
+    public abstract void service();
+
+    public final void _service() {
+        for(Outbox ob : outboxes.values()) {
+            if (!ob.data.isEmpty() && !ob.destination.isEmpty()) {
+                int data = ob.data.remove();
+                Inbox destination = ob.destination.remove();
+                destination.add(data);
+                System.out.println("data:  " + ob + " ----("+data+")----> " + destination);
+            }
+        }
+        service();
+    }
+
+    public class Inbox {
+        private String name;
+        private Queue<Integer> queue = new LinkedList<Integer>();
+        public boolean empty() { return queue.isEmpty(); }
+        public void add(int data) { queue.add(data); }
+        public int remove() { return queue.remove(); }
+        public String toString() { return Ship.this.name+"."+name; }
+        public Inbox(String name) {
+            this.name = name;
+            Ship.this.inboxes.put(name, this);
+        }
+    }
+
+    public class Outbox {
+        private String name;
+        public Queue<Integer> data = new LinkedList<Integer>();
+        public Queue<Inbox> destination = new LinkedList<Inbox>();
+        public void add(int data) { this.data.add(data); }
+        public void addDestination(Inbox destination) { this.destination.add(destination); }
+        public boolean empty() { return data.isEmpty(); }
+        public String toString() { return Ship.this.name+"."+name; }
+        public Outbox(String name) {
+            this.name = name;
+            Ship.this.outboxes.put(name, this);
+        }
+    }
+}
diff --git a/test.fleet b/test.fleet
new file mode 100644 (file)
index 0000000..20de475
--- /dev/null
@@ -0,0 +1,17 @@
+
+#import edu.berkeley.fleet
+
+#ship adder : AdderShip
+#ship memread : MemReadShip
+#ship memwrite : MemWriteShip
+#ship one : OneProducerShip
+#ship halt : HaltShip
+
+#memory { 000, 100, 200, 300, 400, 500 }
+
+one.out      -> adder.in1
+one.out      -> adder.in2
+adder.out    -> memread.addr
+memread.data -> adder.in1
+one.out      -> adder.in2
+adder.out    -> halt.in