run: fleeterpreter.jar
$(java) -cp $(cp) $(interpreter_class) < contrib/demo.fleet
-fleeterpreter.jar: $(shell find src -name \*.java) src/edu/berkeley/fleet/parser/fleet.g
- mkdir -p bin/edu/berkeley/fleet/parser/
- cp src/edu/berkeley/fleet/parser/fleet.g bin/edu/berkeley/fleet/parser/
+fleeterpreter.jar: $(shell find src -name \*.java) src/edu/berkeley/fleet/assembler/fleet.g
+ mkdir -p bin/edu/berkeley/fleet/assembler/
+ cp src/edu/berkeley/fleet/assembler/fleet.g bin/edu/berkeley/fleet/assembler/
javac -cp lib/edu.berkeley.sbp.jar -d bin $(shell find src -name \*.java)
cd bin; jar xvf ../lib/edu.berkeley.sbp.jar
echo 'Main-Class: $(interpreter_class)' > bin/manifest
-noqualifier all \
-d doc/api \
edu.berkeley.fleet.api \
- edu.berkeley.fleet.parser
+ edu.berkeley.fleet.assembler
## Misc ####################################################################################
--- /dev/null
+== Fleet Code Distribution =======================================================================
+
+Directories
+
+ Makefile
+ README -- this file
+ doc/
+ api/ -- javadoc goes here
+ src/
+ edu/berkeley/fleet/
+ api/ -- api classes
+ interpreter/ -- fleet interpreter
+ assembler/ -- assembler code
+ fleet.g -- fleet grammar
+ slipway/ -- code for Fleet-on-RAMP simulator
+ contrib/ -- sample code
+ lib/ -- jar libraries
+
/** ships must be returned in the same order every time -- ordering may be significant */
public abstract Iterator<Ship> iterator();
+ /**
+ * Compute the value that should go in the MACHINE-addressed
+ * "offset" field of a literal given BYTE-addressed origin and
+ * target
+ */
+ public abstract int computeOffset(int origin, int target);
+
+ /**
+ * Compute the value that should go in the "offset" field of a
+ * literal given BYTE-addressed origin and MACHINE-addressed
+ * target
+ */
+ public abstract int computeTarget(int origin, int offset);
+
}
\ No newline at end of file
--- /dev/null
+package edu.berkeley.fleet.assembler;
+
+import edu.berkeley.fleet.api.*;
+import java.io.*;
+import java.util.*;
+
+/** main entry point to the assembler */
+public class Main {
+
+ /** parse the assembly code on <tt>r</tt>, encode it for <tt>fleet</tt>, and write a binary on <tt>out</tt> */
+ public static void assemble(Fleet fleet, Reader r, OutputStream out) throws Exception {
+ new Parser(fleet).parse(r, out);
+ }
+
+ /** parse the assembly code on <tt>r</tt>, encode it for <tt>fleet</tt>, and insert
+ * <tt>Instruction</tt>s into <tt>out</tt> */
+ public static void assemble(Fleet fleet, Reader r, ArrayList<Instruction> out) throws Exception {
+ new Parser(fleet).parse(r, out);
+ }
+
+}
\ No newline at end of file
-package edu.berkeley.fleet.parser;
+package edu.berkeley.fleet.assembler;
import edu.berkeley.fleet.api.*;
-// used only for special interpreter parsing extensions
-import edu.berkeley.fleet.interpreter.Interpreter;
-import edu.berkeley.fleet.interpreter.CodeBag;
-
import edu.berkeley.sbp.*;
import edu.berkeley.sbp.chr.*;
import edu.berkeley.sbp.misc.*;
import java.util.*;
import java.io.*;
-// FIXME: eliminate use of CodeBag class
-
/**
* @author Adam Megacz <megacz@cs.berkeley.edu>
- * @author Thomas Kho <tkho@eecs.berkeley.edu>
*/
-public class Parser {
+class Parser {
- public Parser(Fleet fleet) {
+ Parser(Fleet fleet) {
this.fleet = fleet;
}
//////////////////////////////////////////////////////////////////////////////
- private HashMap<String,Ship> shipMap =
- new HashMap<String,Ship>();
+ private Fleet fleet;
+ private ArrayList<String> imports = new ArrayList<String>();
- static Tree<String> parse(Reader r) throws Exception {
+ private HashMap<String,Ship> shipMap = new HashMap<String,Ship>();
+
+ // codebags in numerical order
+ private ArrayList<CodeBag> codeBags = new ArrayList<CodeBag>();
+ private HashMap<String,CodeBag> codeBagsByName = new HashMap<String,CodeBag>();
+
+ Tree<String> parse(Reader r) throws Exception {
InputStream grammarStream =
Parser.class.getClassLoader().getResourceAsStream("edu/berkeley/fleet/parser/fleet.g");
CharParser metaGrammarParser = new CharParser(MetaGrammar.newInstance());
return tree;
}
- private Fleet fleet;
- private ArrayList<String> imports = new ArrayList<String>();
+ public void parse(Reader r, OutputStream out) throws Exception {
+
+ // this needs to be "code bag zero"
+ CodeBag baseCodeBag = new CodeBag();
+ CodeBag rootCodeBag = new CodeBag();
+ baseCodeBag.add(new Instruction.Literal.CodeBagDescriptor(null, rootCodeBag.getFakeAddress(), 1));
+ walk((Tree<String>)parse(r), rootCodeBag);
+
+ // map from arbitrary identifiers to actual addresses
+ int[] codeBagMap = new int[codeBags.size()];
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ CountingOutputStream cos = new CountingOutputStream(baos);
+ DataOutputStream dos = new DataOutputStream(cos);
+ for(int i=0; i<codeBags.size(); i++) {
+ CodeBag c = codeBags.get(i);
+ dos.flush();
+ codeBagMap[i] = cos.getCount();
+ for(Instruction inst : c)
+ fleet.writeInstruction(dos, inst);
+ }
+
+ // now write for real
+ dos = new DataOutputStream(out);
+ cos = new CountingOutputStream(dos);
+ for(int i=0; i<codeBags.size(); i++) {
+ CodeBag c = codeBags.get(i);
+ dos.flush();
+ for(Instruction inst : c) {
+ if (inst instanceof Instruction.Literal.CodeBagDescriptor) {
+ dos.flush();
+ cos.getCount();
+ Instruction.Literal.CodeBagDescriptor old = (Instruction.Literal.CodeBagDescriptor)inst;
+ int offset = fleet.computeOffset(cos.getCount(), codeBagMap[(int)old.offset]);
+ inst = new Instruction.Literal.CodeBagDescriptor(old.dest,
+ offset,
+ codeBags.get((int)old.offset).size());
+ }
+ fleet.writeInstruction(dos, inst);
+ }
+ }
+ dos.flush();
+ }
+
+ public void parse(Reader r, ArrayList<Instruction> out) throws Exception {
+ // this needs to be "code bag zero"
+ CodeBag baseCodeBag = new CodeBag();
+ CodeBag rootCodeBag = new CodeBag();
+ Instruction inst0 = new Instruction.Literal.CodeBagDescriptor(null, rootCodeBag.getFakeAddress(), 1);
+ baseCodeBag.add(inst0);
+ walk((Tree<String>)parse(r), rootCodeBag);
+ // map from arbitrary identifiers to actual addresses
+ int[] codeBagMap = new int[codeBags.size()];
+ ArrayList<Instruction> temp = new ArrayList<Instruction>();
+ for(int i=0; i<codeBags.size(); i++) {
+ codeBagMap[i] = temp.size();
+ for(Instruction inst : codeBags.get(i))
+ temp.add(inst);
+ }
- public CodeBag walk(Reader r) throws Exception {
- return walk((Tree<String>)parse(r));
+ // now write for real
+ for(int i=0; i<codeBags.size(); i++) {
+ CodeBag c = codeBags.get(i);
+ for(Instruction inst : c) {
+ if (inst instanceof Instruction.Literal.CodeBagDescriptor) {
+ Instruction.Literal.CodeBagDescriptor old = (Instruction.Literal.CodeBagDescriptor)inst;
+ int offset = fleet.computeOffset(out.size(), codeBagMap[(int)old.offset]);
+ inst = new Instruction.Literal.CodeBagDescriptor(old.dest,
+ offset,
+ codeBags.get((int)old.offset).size());
+ }
+ out.add(inst);
+ }
+ }
}
- CodeBag walk(Tree<String> t) {
- CodeBag rootCodeBag = null;
+ /** in the first pass, codebags are assigned "addresses" in arbitrary order */
+ void walk(Tree<String> t, CodeBag cb) {
+
String head = t.head();
if (head==null) {
} else if (head.equals("Program")) {
for(Tree<String> tc : t.child(0))
- walk(tc);
- CodeBag cb = new CodeBag(null, null);
+ walk(tc, cb);
if (t.size()>1)
for(Tree<String> statement : t.child(1))
fillCodeBag(statement, cb);
- rootCodeBag = cb;
} else if (head.equals("Import")) {
imports.add(string(t.child(0)));
String name = name(t.child(0));
String type = string(t.child(1));
Ship ship = null;
- if (fleet instanceof Fleet) {
+ if (fleet instanceof edu.berkeley.fleet.interpreter.Interpreter) {
+ edu.berkeley.fleet.interpreter.Interpreter interpreter =
+ ((edu.berkeley.fleet.interpreter.Interpreter)fleet);
String classname = type;
boolean good = false;
for(String s : imports)
- if ((ship = ((Interpreter)fleet).tryCreate(s+"."+classname, name)) != null)
+ if ((ship = interpreter.tryCreate(s+"."+classname, name)) != null)
break;
if (ship==null)
throw new RuntimeException("couldn't find a ship called \""+classname+"\"");
} else if (head.equals("Include")) {
try {
- walk(parse(new InputStreamReader(new FileInputStream(string(t.child(0))))));
+ walk(parse(new InputStreamReader(new FileInputStream(string(t.child(0))))), cb);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else if (head.equals("Memory")) {
- if (((Interpreter)fleet).mem.length != 0)
+ if (((edu.berkeley.fleet.interpreter.Interpreter)fleet).mem.length != 0)
throw new RuntimeException("multiple memory directives found");
Tree<String> m = t.child(0);
int[] mem = new int[m.size()];
for(int i=0; i<mem.length; i++)
mem[i] = Integer.parseInt(string(m.child(i)));
- ((Interpreter)fleet).mem = mem;
+ ((edu.berkeley.fleet.interpreter.Interpreter)fleet).mem = mem;
}
- return rootCodeBag;
}
String string(Tree<String> t) {
void fillCodeBag(Tree<String> t, CodeBag cb) {
if (t.head()==null) return;
else if (t.head().equals("NamedCodeBag")) {
- CodeBag cb2 = new CodeBag(cb, name(t.child(0)));
+ CodeBag cb2 = new CodeBag(name(t.child(0)));
for(Tree<String> statement : t.child(1))
fillCodeBag(statement, cb2);
else if ("Ack".equals(ttt.head())) { tokenOut = true; dest = portReference(ttt.child(0)); }
}
cb.add(new Instruction.Executable(benkobox,
- dest, count, tokenIn, dataIn, latch, dataOut, tokenOut, recycle));
+ dest, count, tokenIn, dataIn,
+ latch, dataOut, tokenOut, recycle));
}
}
}
+
+ private static class CountingOutputStream extends FilterOutputStream {
+ public CountingOutputStream(OutputStream os) { super(os); }
+ int count = 0;
+ public int getCount() { return count; }
+ public void write(int b) throws IOException {
+ super.write(b);
+ count++;
+ }
+ public void write(byte[] b, int off, int len) throws IOException {
+ super.write(b, off, len);
+ count += len;
+ }
+ }
+
+ private class CodeBag extends ArrayList<Instruction> {
+ public int address = -1;
+ public CodeBag() { codeBags.add(this); }
+ public CodeBag(String name) { this(); codeBagsByName.put(name, this); }
+ public long getFakeAddress() { return codeBags.indexOf(this); }
+ public boolean equals(Object o) { return this==o; }
+ }
+
}
}
public void dispatch(Fleet fleet) {
+ /*
for(Instruction d : dispatchables) {
Log.dispatch(d);
((Interpreter)fleet).dispatch(d);
}
+ */
+ throw new RuntimeException();
}
public void add(Instruction instr) {
public InterpreterBenkoBox resolve(edu.berkeley.fleet.api.BenkoBox bb) { return (InterpreterBenkoBox)bb; }
- public void dispatch(Instruction i) {
+ public void dumpCode() {
+ throw new RuntimeException("not implemented");
+ }
+
+ public void dispatch(Instruction i, long address) {
if (i instanceof Instruction.Executable) {
InterpreterBenkoBox sourceBenkoBox = resolve(((Instruction.Executable)i).benkoBox);
throw new RuntimeException(sourceBenkoBox + " is not an InstructionPort!");
((InstructionPort)sourceBenkoBox).addInstruction(((Instruction.Executable)i));
+ } else if (i instanceof Instruction.Literal.CodeBagDescriptor) {
+ Log.dispatch(i);
+ Instruction.Literal.CodeBagDescriptor cbd = (Instruction.Literal.CodeBagDescriptor)i;
+ dispatchCodeBag(cbd.offset+address, cbd.size);
+
} else if (i instanceof Instruction.Literal.Absolute) {
InterpreterBenkoBox destBenkoBox = resolve(((Instruction.Literal.Absolute)i).dest);
Log.data(((Instruction.Literal.Absolute)i).value+"", null, destBenkoBox);
((InstructionPort)benkoBox).kill(((Instruction.Kill)i).count);
} else {
- throw new Error("unsupported!");
+ throw new Error("unsupported: " + i.getClass().getName());
}
}
public boolean halt = false;
public int[] mem = new int[0];
+
+ public Instruction[] instructions = null;
public ArrayList<String> imports = new ArrayList<String>();
private static String getUniqueName(Ship ship) {
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 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_;
return (Iterator<Ship>)(Object)shiplist.iterator();
}
+ public void dispatchCodeBag(long base, long size) {
+ for(long i=base; i<base+size; i++)
+ dispatch(instructions[(int)i], i);
+ }
+
public void go() {
+ Instruction.Literal.CodeBagDescriptor cbl =
+ (Instruction.Literal.CodeBagDescriptor)instructions[0];
+ dispatchCodeBag(cbl.offset+0, cbl.size);
+
while(!halt)
for(InterpreterShip ship : ships.values())
for(int j=0; j<10; j++)
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()+"]");
- }
+ 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);");
this.prefix = prefix;
root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0);
}
- private Object mkNode(String name, String component, InterpreterBenkoBox[] ports, int start, int end, int addr, int bits) {
+ 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];
Object right;
String name;
String component;
- int addr;
- int bits;
+ int addr;
+ int bits;
public Node(String name, String component, Object left, Object right, int addr, int bits) {
this.left = left;
this.right = right;
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]";
+ 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+
}
}
public static int krunk=0;
+
+ public int computeOffset(int origin, int target) { return target - origin; }
+ public int computeTarget(int origin, int offset) { return origin + offset; }
}
import edu.berkeley.fleet.api.Instruction;
import edu.berkeley.fleet.api.BenkoBox;
import edu.berkeley.fleet.*;
-import edu.berkeley.fleet.parser.*;
+import edu.berkeley.fleet.interpreter.*;
public class Main {
- private static boolean debugMemory = true;
- public static boolean dump_fabric = false;
- public static boolean dump_code = false;
+ static boolean debugMemory = true;
+ static boolean dump_fabric = false;
+ static boolean dump_code = false;
public static void main(String[] s) throws Exception {
for(int i=0; i<s.length; i++) {
public void go(Reader r) throws Exception {
Interpreter fleet = new Interpreter();
- CodeBag rootCodeBag = new Parser(fleet).walk(r);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ArrayList<Instruction> arr = new ArrayList<Instruction>();
+ edu.berkeley.fleet.assembler.Main.assemble(fleet, r, arr);
+ fleet.instructions = (Instruction[])arr.toArray(new Instruction[0]);
+
if (dump_fabric) {
fleet.dumpFabric(false);
} else if (dump_code) {
- fleet.dumpFabric(true);
- try {
- rootCodeBag.dump(fleet);
- } catch (Exception e) { throw new RuntimeException(e); }
+ fleet.dumpCode();
- } else if (rootCodeBag != null) {
+ } else {
if (debugMemory) { fleet.dumpMem(); }
- System.out.println(rootCodeBag);
- rootCodeBag.dispatch(fleet);
fleet.go();
if (debugMemory) { fleet.dumpMem(); }
}