implement support (fpga+interp+test) for massacre instruction
[fleet.git] / src / edu / berkeley / fleet / assembler / Parser.java
index 21f870b..e4b7105 100644 (file)
@@ -40,9 +40,11 @@ public class Parser {
         if (grammar != null) return grammar;
         InputStream grammarStream =
             Parser.class.getClassLoader().getResourceAsStream("edu/berkeley/fleet/assembler/fleet.g");
-        CharParser metaGrammarParser   = new CharParser(MetaGrammar.newInstance());
+        CharParser metaGrammarParser   = new CharParser(GrammarAST.getMetaGrammar());
         Tree<String> parsedGrammar     = metaGrammarParser.parse(new CharInput(grammarStream)).expand1();
-        grammar                        = GrammarAST.buildFromAST(parsedGrammar, "s", new File[0]);
+        grammar                        = GrammarAST.buildFromAST(parsedGrammar, "s", new GrammarAST.ImportResolver() {
+                public InputStream getImportStream(String importname) { return null; }
+            });
         return grammar;
     }
 
@@ -55,7 +57,7 @@ public class Parser {
         CodeBag baseCodeBag = new CodeBag();
         CodeBag rootCodeBag = new CodeBag();
         skip = false;
-        baseCodeBag.add(new Instruction.Literal.CodeBagDescriptor(null, rootCodeBag.getFakeAddress(), 1));
+        baseCodeBag.add(new Instruction.CodeBagDescriptor(null, rootCodeBag.getFakeAddress(), 1));
         walk((Tree<String>)parse(r), rootCodeBag);
         if (fleet instanceof edu.berkeley.fleet.fpga.Fpga)
             ((edu.berkeley.fleet.fpga.Fpga)fleet).dumpFabric(true);
@@ -82,11 +84,11 @@ public class Parser {
             CodeBag c = codeBags.get(i);
             dos.flush();
             for(Instruction inst : c) {
-                if (inst instanceof Instruction.Literal.CodeBagDescriptor) {
+                if (inst instanceof Instruction.CodeBagDescriptor) {
                     dos.flush();
-                    Instruction.Literal.CodeBagDescriptor old = (Instruction.Literal.CodeBagDescriptor)inst;
-                    int offset = codeBagMap[(int)old.offset] - count;
-                    inst = new Instruction.Literal.CodeBagDescriptor(old.dest,
+                    Instruction.CodeBagDescriptor old = (Instruction.CodeBagDescriptor)inst;
+                    int offset = codeBagMap[(int)old.offset];// - count;
+                    inst = new Instruction.CodeBagDescriptor(old.pump,
                                                                      offset,
                                                                      codeBags.get((int)old.offset).size());
                 }
@@ -111,10 +113,10 @@ public class Parser {
                 for(Tree<String> statement : t.child(1))
                     fillCodeBag(statement, cb);
    
-        } else if (head.equals("Import")) {
+        } else if (head.equals("#import")) {
             // ignored
 
-        } else if (head.equals("Ship")) {
+        } else if (head.equals("#ship")) {
             String name = name(t.child(0));
             String type = string(t.child(1));
             Ship ship = null;
@@ -129,16 +131,16 @@ public class Parser {
             }
             shipMap.put(name, ship);
 
-        } else if (head.equals("Include")) {
+        } else if (head.equals("#include")) {
             try {
                 walk(parse(new InputStreamReader(new FileInputStream(string(t.child(0))))), cb);
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
             
-        } else if (head.equals("Expect")) {
-            expect.add(Long.parseLong(string(t.child(0))));
-        } else if (head.equals("Skip")) {
+        } else if (head.equals("#expect")) {
+            expect.add(number(t.child(0)));
+        } else if (head.equals("#skip")) {
             skip = true;
 
         }
@@ -152,45 +154,53 @@ public class Parser {
         return ret;
     }
 
+    String stringBody(Tree<String> t) {
+        String ret = "";
+        for(Tree<String> c : t)
+            ret += string(c);
+        return ret;
+    }
+
     String name(Tree<String> t) {
         return string(t.child(0))+string(t.child(1));
     }
 
     Destination portReference(Tree<String> t) {
-        if (!"Port".equals(t.head()) && !"SubPort".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) return null;
+        if (!"Pump".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) return null;
         String shipName = name(t.child(0));
         String portName = name(t.child(1));
         String subPort = t.size()<3 ? null : name(t.child(2));
         Ship ship = shipMap.get(shipName);
         if (ship==null) throw new RuntimeException("no such ship \""+shipName+"\"");
         Destination ret = null;
-        BenkoBox bb = null;
-        for(BenkoBox b : ship.getBenkoBoxes())
+        Pump bb = null;
+        for(Pump b : ship.getPumps())
             if (b.getName().equals(portName)) {
                 bb = b;
             }
         if (bb==null)
-            throw new RuntimeException("no such benkobox \""+portName+"\"");
+            throw new RuntimeException("no such pump \""+portName+"\"");
         if (subPort==null) subPort="";
         for(Destination d : bb.getDestinations())
             if (d.getDestinationName().equals(subPort))
                 return d;
         if (ret==null)
-            throw new RuntimeException("no such benkobox \""+portName+"\" on ships of type \""+ship.getType()+"\"");
+            throw new RuntimeException("no such pump \""+portName+"\" on ships of type \""+ship.getType()+"\"");
         return ret;
     }
 
-    BenkoBox benkoBox(Tree<String> t) {
-        if (!"Port".equals(t.head()) && !"SubPort".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) return null;
+    Pump pump(Tree<String> t) {
+        if (!"Pump".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head()))
+            throw new RuntimeException(t+"");
         String shipName = name(t.child(0));
         String portName = name(t.child(1));
         Ship ship = shipMap.get(shipName);
         if (ship==null) throw new RuntimeException("no such ship \""+shipName+"\"");
-        BenkoBox bb = null;
-        for(BenkoBox b : ship.getBenkoBoxes())
+        Pump bb = null;
+        for(Pump b : ship.getPumps())
             if (b.getName().equals(portName))
                 return b;
-        throw new RuntimeException("no such benkobox \""+portName+"\"");
+        throw new RuntimeException("no such pump \""+portName+"\"");
     }
 
     private HashMap<String,Integer> numAllocated = new HashMap<String,Integer>();
@@ -212,64 +222,97 @@ public class Parser {
         throw new RuntimeException("no more ships of type \""+shipType+"\"");
     }
 
+    private long parseSSL(Tree t) {
+        String shipType = name(t.child(0));
+        String portName = name(t.child(1));
+        Ship chosenship = null;
+        for(Ship ship : fleet) {
+            if (ship.getType().equals(shipType)) {
+                chosenship = ship;
+                break;
+            }
+        }
+        Pump chosenport = chosenship.getPump(portName);
+        Tree specs = t.child(2);
+        long literal = 0;
+        for(int i=0; i<specs.size(); i++) {
+            Tree tt = specs.child(i);
+            literal |= chosenport.resolveLiteral(stringBody(tt));
+        }
+        return literal;
+    }
+
+    private int anoncount = 1;
     void fillCodeBag(Tree<String> t, CodeBag cb) {
         if (t.head()==null) return;
-        else if (t.head().equals("NamedCodeBag")) {
+        else if (t.head().equals("CodeBagDef")) {
             CodeBag cb2 = getCodeBag(name(t.child(0)));
             for(Tree<String> statement : t.child(1))
                 fillCodeBag(statement, cb2);
 
-        } else if (t.head().equals("ShipSpecificLiteral")) {
-            String shipType = name(t.child(0).child(0));
-            String portName = name(t.child(0).child(1));
-            Ship chosenship = null;
-            for(Ship ship : fleet) {
-                if (ship.getType().equals(shipType)) {
-                    chosenship = ship;
-                    break;
-                }
-            }
-            BenkoBox chosenport = chosenship.getBenkoBox(portName);
-            Tree specs = t.child(0).child(2);
-            long literal = 0;
-            for(int i=0; i<specs.size(); i++) {
-                Tree tt = specs.child(i);
-                literal |= chosenport.resolveLiteral(string(tt));
-            }
-            cb.add(new Instruction.Literal.Absolute(portReference(t.child(1)), literal));
-
-        } else if (t.head().equals("Literal")) {
-            long literal = Long.parseLong(string(t.child(0)));
-            cb.add(new Instruction.Literal.Absolute(portReference(t.child(1)), literal));
-
-        } else if (t.head().equals("CodeBagDescriptor")) {
-            String refname = name(t.child(0).child(0));
-            CodeBag cb2 = getCodeBag(refname);
-            cb.add(new Instruction.Literal.CodeBagDescriptor(portReference(t.child(1)), cb2.getFakeAddress(), 0));
-
         } else if (t.head().equals("Fiber")) {
-            BenkoBox benkobox = (BenkoBox)benkoBox(t.child(0));
+            Pump pump = (Pump)pump(t.child(0));
             
             OUTER: for(Tree tt : t.child(1)) {
                 int count = 1;
-                Tree ttx = null;
-                boolean requeue = false;
-                ttx = tt.child(1);
-                if (tt.size() > 1 && tt.child(0).size()>0) {
-                    tt = tt.child(0).child(0);
-                    if (tt.head().equals("BrackStar")) {
-                        count = 0;
-                        requeue = false;
-                    } else if (tt.head().equals("ParenStar")) {
+                if ("unclog".equals(tt.head()))    {
+                    cb.add(new Instruction.UnClog(pump));
+                    continue;
+                } else if ("clog".equals(tt.head()))    {
+                    cb.add(new Instruction.Clog(pump));
+                    continue;
+                } else if ("kill".equals(tt.head()))    {
+                    count = tt.size()==0 ? 1 : (int)number(tt.child(0));
+                    cb.add(new Instruction.Kill(pump, count));
+                    continue;
+                } else if ("massacre".equals(tt.head()))    {
+                    cb.add(new Instruction.Massacre(pump));
+                    continue;
+                } else if ("literal".equals(tt.head()))  {
+                    long literal = 0;
+                    if (tt.child(0).head().equals("CodeBagBody")) {
+                        Tree<String> tq = tt;
+                        CodeBag cb2 = getCodeBag("anon"+(anoncount++));
+                        for(Tree<String> statement : tq.child(0))
+                            fillCodeBag(statement, cb2);
+                        cb.add(new Instruction.CodeBagDescriptor(pump, cb2.getFakeAddress(), 0));
+                        continue OUTER;
+                    } else if (tt.child(0).head().equals("Name")) {
+                        String refname = name(tt.child(0));
+                        CodeBag cb2 = getCodeBag(refname);
+                        cb.add(new Instruction.CodeBagDescriptor(pump, cb2.getFakeAddress(), 0));
+                        continue OUTER;
+                    } else if (tt.child(0).head().equals("[")) {
+                        literal = parseSSL(tt.child(0));
+                    } else {
+                        literal = number(tt.child(0));
+                    }
+                    count = 1;
+                    if ("int".equals(tt.child(1).head())) {
+                        count = (int)number(tt.child(1));
+                    } else if ("forever".equals(tt.child(1).head())) {
                         count = 0;
-                        requeue = true;
-                    } else if (tt.head().equals("Brack")) {
-                        count = Integer.parseInt(string(tt.child(0)));
-                        requeue = false;
-                    } else if (tt.head().equals("Paren")) {
-                        count = Integer.parseInt(string(tt.child(0)));
-                        requeue = true;
                     }
+                    cb.add(new Instruction.LocalLiteral(pump, literal, count));
+                    continue;
+                }
+                Tree ttx = null;
+                boolean requeue = false;
+                ttx = tt.child(1).head().equals("Commands") ? tt.child(1) : tt;
+                if ("int".equals(tt.child(2).head())) {
+                    count = (int)number(tt.child(2));
+                    requeue = true;
+                } else if ("forever".equals(tt.child(2).head())) {
+                    count = 0;
+                    requeue = true;
+                }
+                tt = tt.child(0);
+                if (tt.head().equals("[*]")) {
+                    count = 0;
+                    requeue = false;
+                } else if (tt.head().equals("int")) {
+                    count = (int)number(tt);
+                    requeue = false;
                 }
                 boolean tokenIn = false;
                 boolean dataIn = false;
@@ -277,36 +320,39 @@ public class Parser {
                 boolean dataOut = false;
                 boolean tokenOut = false;
                 boolean dataOutDest = false;
+                boolean localLiteral = false;
+                boolean ignoreUntilLast = false;
+                long literal = 0;
                 Destination dest = null;
                 for(int i=0; i<ttx.size(); i++) {
                     Tree ttt = ttx.child(i);
-                    if      ("Wait".equals(ttt.head()))    { tokenIn = true; }
-                    else if ("Nop".equals(ttt.head()))     { }
-                    else if ("KillStar".equals(ttt.head()))    {
-                        cb.add(new Instruction.Kill(benkobox, count, true));
-                        continue OUTER;
-                    } else if ("Kill".equals(ttt.head()))    {
-                        cb.add(new Instruction.Kill(benkobox, count, false));
+                    if      ("wait".equals(ttt.head()))    { tokenIn = true; }
+                    else if ("nop".equals(ttt.head()))     { }
+                    else if ("kill".equals(ttt.head()))    {
+                        cb.add(new Instruction.Kill(pump, count));
                         continue OUTER;
                     }
-                    else if ("Discard".equals(ttt.head())) { dataIn = true; latch = false; }
-                    else if ("Take".equals(ttt.head()))    { dataIn = true; latch = true; }
-                    else if ("SendTo".equals(ttt.head()))  { dataOut = true; dest = portReference(ttt.child(0)); }
-                    else if ("DataOutDest".equals(ttt.head()))  { dataOutDest = true; }
-                    else if ("Deliver".equals(ttt.head())) { dataOut = true;  }
-                    else if ("Ack".equals(ttt.head()))     { tokenOut = true; dest = portReference(ttt.child(0)); }
+                    else if ("discard".equals(ttt.head())) { dataIn = true; latch = false; }
+                    else if ("take".equals(ttt.head()))    { dataIn = true; latch = true; }
+                    else if ("recieve".equals(ttt.head()))    { dataIn = true; latch = true; }
+                    else if ("send".equals(ttt.head()))  { dataOutDest = true; }
+                    else if ("sendto".equals(ttt.head()))  { dataOut = true; dest = portReference(ttt.child(0)); }
+                    else if ("deliver".equals(ttt.head())) { dataOut = true;  }
+                    else if ("notify".equals(ttt.head()))     { tokenOut = true; dest = portReference(ttt.child(0)); }
+                    else if ("notifyLast".equals(ttt.head()))     { tokenOut = true; ignoreUntilLast = true; dest = portReference(ttt.child(0)); }
                 }
-                cb.add(new Instruction.Executable(benkobox,
-                                                  dest, count, tokenIn, dataIn,
-                                                  latch, dataOutDest, dataOut, tokenOut, requeue));
+                    cb.add(new Instruction.Move(pump,
+                                                dest, count, tokenIn, dataIn,
+                                                latch, dataOutDest, dataOut, tokenOut, requeue, ignoreUntilLast));
             }
         }
     }
 
     private class CodeBag extends ArrayList<Instruction> {
         public long address = -1;
-        public CodeBag() { codeBags.add(this); }
-        public CodeBag(String name) { this(); codeBagsByName.put(name, this); }
+        public final String name;
+        public CodeBag() { codeBags.add(this); this.name = "root"; }
+        public CodeBag(String name) { codeBags.add(this); codeBagsByName.put(name, this); this.name = name; }
         public long getFakeAddress() { return codeBags.indexOf(this); }
         public boolean equals(Object o) { return this==o; }
     }
@@ -315,4 +361,16 @@ public class Parser {
     public static ArrayList<Long> expect;
     public static boolean         skip;
 
+    private static long number(Tree t) {
+        String ret = "";
+        for(Object c : t.child(2)) ret += ((Tree)c).head();
+        boolean negative = "-".equals(t.child(0).head());
+        ret = ret.trim();
+        long val = 0;
+        if      ("0x".equals(t.child(1).head())) val = Long.parseLong(ret, 16);
+        else if ("0b".equals(t.child(1).head())) val = Long.parseLong(ret, 2);
+        else                                     val = Long.parseLong(ret);
+        if (negative) val = -1L * val;
+        return val;
+    }
 }