slicc: add a protocol statement and an include statement
authorNathan Binkert <nate@binkert.org>
Wed, 6 Jul 2011 01:30:05 +0000 (18:30 -0700)
committerNathan Binkert <nate@binkert.org>
Wed, 6 Jul 2011 01:30:05 +0000 (18:30 -0700)
All protocols must specify their name
The include statement allows any file to include another file.

src/mem/protocol/MESI_CMP_directory.slicc
src/mem/protocol/MI_example.slicc
src/mem/protocol/MOESI_CMP_directory.slicc
src/mem/protocol/MOESI_CMP_token.slicc
src/mem/protocol/MOESI_hammer.slicc
src/mem/protocol/Network_test.slicc
src/mem/protocol/RubySlicc_interfaces.slicc
src/mem/protocol/SConscript
src/mem/slicc/main.py
src/mem/slicc/parser.py

index 3ba85fb40d66702f785f01bea423d6ff510fe894..07b55620bd062025974c06a87197865ed187b5a7 100644 (file)
@@ -1,6 +1,8 @@
-MESI_CMP_directory-msg.sm
-MESI_CMP_directory-L1cache.sm
-MESI_CMP_directory-L2cache.sm
-MESI_CMP_directory-dir.sm
-MESI_CMP_directory-dma.sm
-standard_CMP-protocol.sm
+protocol "MESI_CMP_directory";
+include "RubySlicc_interfaces.slicc";
+include "MESI_CMP_directory-msg.sm";
+include "MESI_CMP_directory-L1cache.sm";
+include "MESI_CMP_directory-L2cache.sm";
+include "MESI_CMP_directory-dir.sm";
+include "MESI_CMP_directory-dma.sm";
+include "standard_CMP-protocol.sm";
index 523668177cdbd652094f2ed661dcc1540b4627d1..00508673be0412be356879b2535697f212249b23 100644 (file)
@@ -1,5 +1,7 @@
-MI_example-msg.sm
-MI_example-cache.sm
-MI_example-dir.sm
-MI_example-dma.sm
-standard_1level_CMP-protocol.sm
+protocol "MI_example";
+include "RubySlicc_interfaces.slicc";
+include "MI_example-msg.sm";
+include "MI_example-cache.sm";
+include "MI_example-dir.sm";
+include "MI_example-dma.sm";
+include "standard_1level_CMP-protocol.sm";
index f288aa4b0539707b3b81de7a41b74a763242ccba..199ea174d7e006e18639a788b5eba8ebb06f5662 100644 (file)
@@ -1,6 +1,8 @@
-MOESI_CMP_directory-msg.sm
-MOESI_CMP_directory-L2cache.sm
-MOESI_CMP_directory-L1cache.sm
-MOESI_CMP_directory-dma.sm
-MOESI_CMP_directory-dir.sm
-standard_CMP-protocol.sm
+protocol "MOESI_CMP_directory";
+include "RubySlicc_interfaces.slicc";
+include "MOESI_CMP_directory-msg.sm";
+include "MOESI_CMP_directory-L2cache.sm";
+include "MOESI_CMP_directory-L1cache.sm";
+include "MOESI_CMP_directory-dma.sm";
+include "MOESI_CMP_directory-dir.sm";
+include "standard_CMP-protocol.sm";
index a41226f90ebebddc814ad4a14b77960ba052ef38..9818561d66260ad839f4fdfeaa9ad34ceea5b9ec 100644 (file)
@@ -1,6 +1,8 @@
-MOESI_CMP_token-msg.sm
-MOESI_CMP_token-L1cache.sm
-MOESI_CMP_token-L2cache.sm
-MOESI_CMP_token-dir.sm
-MOESI_CMP_token-dma.sm
-standard_CMP-protocol.sm
+protocol "MOESI_CMP_token";
+include "RubySlicc_interfaces.slicc";
+include "MOESI_CMP_token-msg.sm";
+include "MOESI_CMP_token-L1cache.sm";
+include "MOESI_CMP_token-L2cache.sm";
+include "MOESI_CMP_token-dir.sm";
+include "MOESI_CMP_token-dma.sm";
+include "standard_CMP-protocol.sm";
index 31ad47c2efc9632c14ffbb484a5a7d2512b3bf77..66d217c9cd99a3744ccc7c2698fb6e66a3684cab 100644 (file)
@@ -1,5 +1,7 @@
-MOESI_hammer-msg.sm
-MOESI_hammer-cache.sm
-MOESI_hammer-dir.sm
-MOESI_hammer-dma.sm
-standard_1level_CMP-protocol.sm
+protocol "MOESI_hammer";
+include "RubySlicc_interfaces.slicc";
+include "MOESI_hammer-msg.sm";
+include "MOESI_hammer-cache.sm";
+include "MOESI_hammer-dir.sm";
+include "MOESI_hammer-dma.sm";
+include "standard_1level_CMP-protocol.sm";
index 9629a385cb89190bfdf6b2a95aece7401ef480a9..b122b149cee5175c4e6b310ec686c2533d5eb405 100644 (file)
@@ -1,4 +1,6 @@
-Network_test-msg.sm
-Network_test-cache.sm
-Network_test-dir.sm
-standard_1level_CMP-protocol.sm
+protocol "Network_test";
+include "RubySlicc_interfaces.slicc";
+include "Network_test-msg.sm";
+include "Network_test-cache.sm";
+include "Network_test-dir.sm";
+include "standard_1level_CMP-protocol.sm";
index 280a847638efe6edd48b8513d7237b13be938ae1..4b6800847377d2494d52899c0f4545883d134871 100644 (file)
@@ -1,7 +1,7 @@
-RubySlicc_Exports.sm
-RubySlicc_Types.sm
-RubySlicc_Util.sm
-RubySlicc_ComponentMapping.sm
-RubySlicc_Profiler.sm
-RubySlicc_Defines.sm
-RubySlicc_MemControl.sm
+include "RubySlicc_Exports.sm";
+include "RubySlicc_Types.sm";
+include "RubySlicc_Util.sm";
+include "RubySlicc_ComponentMapping.sm";
+include "RubySlicc_Profiler.sm";
+include "RubySlicc_Defines.sm";
+include "RubySlicc_MemControl.sm";
index 47a19aecb05463afb366ab38c610a162ae6360dd..a4e2a5264629770aa4a5903f1cc0b56290c25383 100644 (file)
@@ -63,10 +63,10 @@ slicc_scanner = Classic("SliccScanner", ['.sm', '.slicc'], "SLICC_PATH",
 env.Append(SCANNERS=slicc_scanner)
 
 def slicc_emitter(target, source, env):
-    protocol = source[0].get_contents()
-    files = [s.srcnode().abspath for s in source[1:]]
-    slicc = SLICC(protocol, verbose=False)
-    slicc.load(files)
+    assert len(source) == 1
+    filepath = source[0].srcnode().abspath
+
+    slicc = SLICC(filepath, verbose=False)
     slicc.process()
     slicc.writeCodeFiles(protocol_dir.abspath)
     if not env['NO_HTML']:
@@ -76,10 +76,10 @@ def slicc_emitter(target, source, env):
     return target, source
 
 def slicc_action(target, source, env):
-    protocol = source[0].get_contents()
-    files = [s.srcnode().abspath for s in source[1:]]
-    slicc = SLICC(protocol, verbose=True)
-    slicc.load(files)
+    assert len(source) == 1
+    filepath = source[0].srcnode().abspath
+
+    slicc = SLICC(filepath, verbose=True)
     slicc.process()
     slicc.writeCodeFiles(protocol_dir.abspath)
     if not env['NO_HTML']:
@@ -89,11 +89,10 @@ slicc_builder = Builder(action=MakeAction(slicc_action, Transform("SLICC")),
                         emitter=slicc_emitter)
 
 protocol = env['PROTOCOL']
-sources = [ protocol_dir.File("RubySlicc_interfaces.slicc"),
-            protocol_dir.File("%s.slicc" % protocol) ]
+sources = [ protocol_dir.File("%s.slicc" % protocol) ]
 
 env.Append(BUILDERS={'SLICC' : slicc_builder})
-nodes = env.SLICC([], [ Value(protocol) ] + sources)
+nodes = env.SLICC([], sources)
 env.Depends(nodes, slicc_depends)
 
 for f in nodes:
index 15eb9d4bea6e6ff7e5e43c9d3403ed2a43e0e802..0b528d805c8344d7ca886b29d81a123e3113c118 100644 (file)
@@ -66,7 +66,7 @@ def main(args=None):
                       help="don't print messages")
     opts,files = parser.parse_args(args=args)
 
-    if len(files) < 1:
+    if len(files) != 1:
         parser.print_help()
         sys.exit(2)
 
@@ -75,8 +75,7 @@ def main(args=None):
     output("SLICC v0.4")
     output("Parsing...")
 
-    slicc = SLICC(debug=opts.debug)
-    slicc.load(files)
+    slicc = SLICC(files[0], verbose=True, debug=opts.debug, traceback=opts.tb)
 
     if opts.print_files:
         for i in sorted(slicc.files()):
index 596b89f64976dbcad42c206b5748c9a715b06680..f35a3691a9708bbb980134abb6769a9e5a90ae32 100644 (file)
@@ -37,26 +37,20 @@ import slicc.ast as ast
 import slicc.util as util
 from slicc.symbols import SymbolTable
 
-def read_slicc(sources):
-    if not isinstance(sources, (list,tuple)):
-        sources = [ sources ]
-
-    for source in sources:
-        for sm_file in file(source, "r"):
-            sm_file = sm_file.strip()
-            if not sm_file:
-                continue
-            if sm_file.startswith("#"):
-                continue
-            yield sm_file
-
 class SLICC(Grammar):
-    def __init__(self, protocol, verbose=False):
-        self.decl_list_vec = []
-        self.protocol = protocol
+    def __init__(self, filename, verbose=False, traceback=False, **kwargs):
+        self.protocol = None
+        self.traceback = traceback
         self.verbose = verbose
         self.symtab = SymbolTable(self)
 
+        try:
+            self.decl_list = self.parse_file(filename, **kwargs)
+        except ParseError, e:
+            if not self.traceback:
+                sys.exit(str(e))
+            raise
+
     def currentLocation(self):
         return util.Location(self.current_source, self.current_line,
                              no_warning=not self.verbose)
@@ -66,35 +60,9 @@ class SLICC(Grammar):
         code['protocol'] = self.protocol
         return code
 
-    def parse(self, filename):
-        try:
-            decl_list = self.parse_file(filename)
-        except ParseError, e:
-            sys.exit(str(e))
-        self.decl_list_vec.append(decl_list)
-
-    def load(self, filenames):
-        filenames = list(filenames)
-        while filenames:
-            f = filenames.pop(0)
-            if isinstance(f, (list, tuple)):
-                filenames[0:0] = list(f)
-                continue
-
-            if f.endswith(".slicc"):
-                dirname,basename = os.path.split(f)
-                filenames[0:0] = [ os.path.join(dirname, x) \
-                                   for x in read_slicc(f)]
-            else:
-                assert f.endswith(".sm")
-                self.parse(f)
-
     def process(self):
-        for decl_list in self.decl_list_vec:
-            decl_list.findMachines()
-
-        for decl_list in self.decl_list_vec:
-            decl_list.generate()
+        self.decl_list.findMachines()
+        self.decl_list.generate()
 
     def writeCodeFiles(self, code_path):
         self.symtab.writeCodeFiles(code_path)
@@ -108,8 +76,7 @@ class SLICC(Grammar):
             'MachineType.hh',
             'Types.hh' ])
 
-        for decl_list in self.decl_list_vec:
-            f |= decl_list.files()
+        f |= self.decl_list.files()
 
         return f
 
@@ -129,6 +96,8 @@ class SLICC(Grammar):
         t.lexer.lineno += len(t.value)
 
     reserved = {
+        'protocol' : 'PROTOCOL',
+        'include' : 'INCLUDE',
         'global' : 'GLOBAL',
         'machine' : 'MACHINE',
         'in_port' : 'IN_PORT',
@@ -256,12 +225,33 @@ class SLICC(Grammar):
 
     def p_declsx__list(self, p):
         "declsx : decl declsx"
-        p[0] = [ p[1] ] + p[2]
+        if isinstance(p[1], ast.DeclListAST):
+            decls = p[1].decls
+        elif p[1] is None:
+            decls = []
+        else:
+            decls = [ p[1] ]
+        p[0] = decls + p[2]
 
     def p_declsx__none(self, p):
         "declsx : empty"
         p[0] = []
 
+    def p_decl__protocol(self, p):
+        "decl : PROTOCOL STRING SEMI"
+        if self.protocol:
+            msg = "Protocol can only be set once! Error at %s:%s\n" % \
+                (self.current_source, self.current_line)
+            raise ParseError(msg)
+        self.protocol = p[2]
+        p[0] = None
+
+    def p_decl__include(self, p):
+        "decl : INCLUDE STRING SEMI"
+        dirname = os.path.dirname(self.current_source)
+        filename = os.path.join(dirname, p[2])
+        p[0] = self.parse_file(filename)
+
     def p_decl__machine(self, p):
         "decl : MACHINE '(' ident pairs ')' ':' params '{' decls '}'"
         p[0] = ast.MachineAST(self, p[3], p[4], p[7], p[9])