1 package edu.berkeley.fleet.assembler;
3 import edu.berkeley.fleet.api.*;
5 import edu.berkeley.sbp.*;
6 import edu.berkeley.sbp.chr.*;
7 import edu.berkeley.sbp.misc.*;
8 import edu.berkeley.sbp.meta.*;
9 import edu.berkeley.sbp.bind.*;
10 import edu.berkeley.sbp.util.*;
15 * @author Adam Megacz <megacz@cs.berkeley.edu>
20 expect = new ArrayList<Long>();
24 //////////////////////////////////////////////////////////////////////////////
27 private ArrayList<String> imports = new ArrayList<String>();
29 private HashMap<String,Ship> shipMap = new HashMap<String,Ship>();
31 // codebags in numerical order
32 private ArrayList<CodeBag> codeBags = new ArrayList<CodeBag>();
33 private HashMap<String,CodeBag> codeBagsByName = new HashMap<String,CodeBag>();
35 private CodeBag getCodeBag(String name) {
36 CodeBag cb = codeBagsByName.get(name);
37 if (cb!=null) return cb;
38 return new CodeBag(name);
41 Tree<String> parse(Reader r) throws Exception {
42 InputStream grammarStream =
43 Parser.class.getClassLoader().getResourceAsStream("edu/berkeley/fleet/assembler/fleet.g");
44 CharParser metaGrammarParser = new CharParser(MetaGrammar.newInstance());
45 Tree<String> parsedGrammar = metaGrammarParser.parse(new CharInput(grammarStream)).expand1();
46 Union grammar = Grammar.create(parsedGrammar, "s", new Grammar.Bindings() { });
47 CharParser parser = new CharParser(grammar);
48 Tree tree = parser.parse(new CharInput(r)).expand1();
52 public void parse(Reader r, OutputStream out) throws Exception {
54 // this needs to be "code bag zero"
55 CodeBag baseCodeBag = new CodeBag();
56 CodeBag rootCodeBag = new CodeBag();
57 baseCodeBag.add(new Instruction.Literal.CodeBagDescriptor(null, rootCodeBag.getFakeAddress(), 1));
58 walk((Tree<String>)parse(r), rootCodeBag);
59 if (fleet instanceof edu.berkeley.fleet.slipway.Slipway)
60 ((edu.berkeley.fleet.slipway.Slipway)fleet).dumpFabric(true);
62 // map from arbitrary identifiers to actual addresses
63 int[] codeBagMap = new int[codeBags.size()];
64 ByteArrayOutputStream baos = new ByteArrayOutputStream();
65 CountingOutputStream cos = new CountingOutputStream(baos);
66 DataOutputStream dos = new DataOutputStream(cos);
68 for(int i=0; i<codeBags.size(); i++) {
69 CodeBag c = codeBags.get(i);
71 codeBagMap[i] = count;//cos.getCount();
72 for(Instruction inst : c) {
73 fleet.writeInstruction(dos, inst);
79 cos = new CountingOutputStream(out);
80 dos = new DataOutputStream(cos);
82 for(int i=0; i<codeBags.size(); i++) {
83 CodeBag c = codeBags.get(i);
85 for(Instruction inst : c) {
86 if (inst instanceof Instruction.Literal.CodeBagDescriptor) {
89 Instruction.Literal.CodeBagDescriptor old = (Instruction.Literal.CodeBagDescriptor)inst;
90 int offset = codeBagMap[(int)old.offset] - count;
91 inst = new Instruction.Literal.CodeBagDescriptor(old.dest,
93 codeBags.get((int)old.offset).size());
95 fleet.writeInstruction(dos, inst);
105 /** in the first pass, codebags are assigned "addresses" in arbitrary order */
106 void walk(Tree<String> t, CodeBag cb) {
108 String head = t.head();
110 } else if (head.equals("Program")) {
111 for(Tree<String> tc : t.child(0))
114 for(Tree<String> statement : t.child(1))
115 fillCodeBag(statement, cb);
117 } else if (head.equals("Import")) {
120 } else if (head.equals("Ship")) {
121 String name = name(t.child(0));
122 String type = string(t.child(1));
125 if (fleet instanceof Fleet.WithDynamicShips) {
126 Fleet.WithDynamicShips dyn = ((Fleet.WithDynamicShips)fleet);
127 ship = dyn.createShip(type, name);
129 throw new RuntimeException("couldn't find a ship called \""+type+"\"");
131 ship = allocateShip(type);
133 shipMap.put(name, ship);
135 } else if (head.equals("Include")) {
137 walk(parse(new InputStreamReader(new FileInputStream(string(t.child(0))))), cb);
138 } catch (Exception e) {
139 throw new RuntimeException(e);
142 } else if (head.equals("Expect")) {
143 expect.add(Long.parseLong(string(t.child(0))));
145 } else if (head.equals("Memory")) {
146 if (((edu.berkeley.fleet.interpreter.Interpreter)fleet).mem.length != 0)
147 throw new RuntimeException("multiple memory directives found");
148 Tree<String> m = t.child(0);
149 int[] mem = new int[m.size()];
150 for(int i=0; i<mem.length; i++)
151 mem[i] = Integer.parseInt(string(m.child(i)));
152 ((edu.berkeley.fleet.interpreter.Interpreter)fleet).mem = mem;
156 String string(Tree<String> t) {
158 if (t.head() != null) ret += t.head();
159 for(Tree<String> c : t)
164 String name(Tree<String> t) {
165 return string(t.child(0))+string(t.child(1));
168 BenkoBox portReference(Tree<String> t) {
169 if (!"Port".equals(t.head())) return null;
170 String shipName = name(t.child(0));
171 String portName = name(t.child(1));
172 Ship ship = shipMap.get(shipName);
173 if (ship==null) throw new RuntimeException("no such ship \""+shipName+"\"");
174 for(BenkoBox b : ship.getBenkoBoxes())
175 if (b.getName().equals(portName))
177 throw new RuntimeException("no such benkobox \""+portName+"\" on ships of type \""+ship.getType()+"\"");
180 private HashMap<String,Integer> numAllocated = new HashMap<String,Integer>();
182 Ship allocateShip(String shipType) {
184 if (numAllocated.get(shipType) != null)
185 allocated = numAllocated.get(shipType);
186 numAllocated.put(shipType, allocated+1);
187 for(Iterator<Ship> it = fleet.iterator();
191 if (s.getType().equals(shipType)) {
192 if (allocated == 0) return s;
196 throw new RuntimeException("no more ships of type \""+shipType+"\"");
199 void fillCodeBag(Tree<String> t, CodeBag cb) {
200 if (t.head()==null) return;
201 else if (t.head().equals("NamedCodeBag")) {
202 CodeBag cb2 = getCodeBag(name(t.child(0)));
203 for(Tree<String> statement : t.child(1))
204 fillCodeBag(statement, cb2);
206 } else if (t.head().equals("Literal")) {
207 int literal = Integer.parseInt(string(t.child(0)));
208 BenkoBox benkobox = portReference(t.child(1));
209 cb.add(new Instruction.Literal.Absolute(benkobox, literal));
211 } else if (t.head().equals("CodeBagDescriptor")) {
212 String refname = name(t.child(0).child(0));
213 CodeBag cb2 = getCodeBag(refname);
214 BenkoBox benkobox = portReference(t.child(1));
215 cb.add(new Instruction.Literal.CodeBagDescriptor(benkobox, cb2.getFakeAddress(), 0));
217 } else if (t.head().equals("Fiber")) {
218 BenkoBox benkobox = portReference(t.child(0));
220 OUTER: for(Tree tt : t.child(1)) {
223 boolean recycle = false;
227 if (tt.size() > 0 && tt.child(0).size()>0) {
229 if (tt.child(0).size() == 0) count=1;
230 else if (tt.child(0).size() > 0 && "Star".equals(tt.child(0).child(0).head())) count=0;
231 else count = Integer.parseInt(string(tt.child(0)));
232 if (tt.size() > 1 && tt.child(1).size() > 0)
236 boolean tokenIn = false;
237 boolean dataIn = false;
238 boolean latch = false;
239 boolean dataOut = false;
240 boolean tokenOut = false;
241 BenkoBox dest = null;
242 for(int i=0; i<ttx.size(); i++) {
243 Tree ttt = ttx.child(i);
244 if ("Wait".equals(ttt.head())) { tokenIn = true; }
245 else if ("Nop".equals(ttt.head())) { }
246 else if ("KillStar".equals(ttt.head())) {
247 cb.add(new Instruction.Kill(benkobox, count, true));
249 } else if ("Kill".equals(ttt.head())) {
250 cb.add(new Instruction.Kill(benkobox, count, false));
253 else if ("Discard".equals(ttt.head())) { dataIn = true; latch = false; }
254 else if ("Take".equals(ttt.head())) { dataIn = true; latch = true; }
255 else if ("SendTo".equals(ttt.head())) { dataOut = true; dest = portReference(ttt.child(0)); }
256 else if ("Deliver".equals(ttt.head())) { dataOut = true; }
257 else if ("Ack".equals(ttt.head())) { tokenOut = true; dest = portReference(ttt.child(0)); }
259 cb.add(new Instruction.Executable(benkobox,
260 dest, count, tokenIn, dataIn,
261 latch, dataOut, tokenOut, recycle));
266 private static class CountingOutputStream extends FilterOutputStream {
267 public CountingOutputStream(OutputStream os) { super(os); }
269 public int getCount() { return count; }
270 public void write(int b) throws IOException {
274 public void write(byte[] b, int off, int len) throws IOException {
275 super.write(b, off, len);
280 private class CodeBag extends ArrayList<Instruction> {
281 public int address = -1;
282 public CodeBag() { codeBags.add(this); }
283 public CodeBag(String name) { this(); codeBagsByName.put(name, this); }
284 public long getFakeAddress() { return codeBags.indexOf(this); }
285 public boolean equals(Object o) { return this==o; }
289 public static ArrayList<Long> expect;