From da1eaaca0ec7f65525dd2706f4b6b207bf9ee691 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 5 Jul 2011 18:30:05 -0700 Subject: [PATCH] slicc: add a protocol statement and an include statement All protocols must specify their name The include statement allows any file to include another file. --- src/mem/protocol/MESI_CMP_directory.slicc | 14 ++-- src/mem/protocol/MI_example.slicc | 12 +-- src/mem/protocol/MOESI_CMP_directory.slicc | 14 ++-- src/mem/protocol/MOESI_CMP_token.slicc | 14 ++-- src/mem/protocol/MOESI_hammer.slicc | 12 +-- src/mem/protocol/Network_test.slicc | 10 ++- src/mem/protocol/RubySlicc_interfaces.slicc | 14 ++-- src/mem/protocol/SConscript | 21 +++--- src/mem/slicc/main.py | 5 +- src/mem/slicc/parser.py | 84 +++++++++------------ 10 files changed, 100 insertions(+), 100 deletions(-) diff --git a/src/mem/protocol/MESI_CMP_directory.slicc b/src/mem/protocol/MESI_CMP_directory.slicc index 3ba85fb40..07b55620b 100644 --- a/src/mem/protocol/MESI_CMP_directory.slicc +++ b/src/mem/protocol/MESI_CMP_directory.slicc @@ -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"; diff --git a/src/mem/protocol/MI_example.slicc b/src/mem/protocol/MI_example.slicc index 523668177..00508673b 100644 --- a/src/mem/protocol/MI_example.slicc +++ b/src/mem/protocol/MI_example.slicc @@ -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"; diff --git a/src/mem/protocol/MOESI_CMP_directory.slicc b/src/mem/protocol/MOESI_CMP_directory.slicc index f288aa4b0..199ea174d 100644 --- a/src/mem/protocol/MOESI_CMP_directory.slicc +++ b/src/mem/protocol/MOESI_CMP_directory.slicc @@ -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"; diff --git a/src/mem/protocol/MOESI_CMP_token.slicc b/src/mem/protocol/MOESI_CMP_token.slicc index a41226f90..9818561d6 100644 --- a/src/mem/protocol/MOESI_CMP_token.slicc +++ b/src/mem/protocol/MOESI_CMP_token.slicc @@ -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"; diff --git a/src/mem/protocol/MOESI_hammer.slicc b/src/mem/protocol/MOESI_hammer.slicc index 31ad47c2e..66d217c9c 100644 --- a/src/mem/protocol/MOESI_hammer.slicc +++ b/src/mem/protocol/MOESI_hammer.slicc @@ -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"; diff --git a/src/mem/protocol/Network_test.slicc b/src/mem/protocol/Network_test.slicc index 9629a385c..b122b149c 100644 --- a/src/mem/protocol/Network_test.slicc +++ b/src/mem/protocol/Network_test.slicc @@ -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"; diff --git a/src/mem/protocol/RubySlicc_interfaces.slicc b/src/mem/protocol/RubySlicc_interfaces.slicc index 280a84763..4b6800847 100644 --- a/src/mem/protocol/RubySlicc_interfaces.slicc +++ b/src/mem/protocol/RubySlicc_interfaces.slicc @@ -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"; diff --git a/src/mem/protocol/SConscript b/src/mem/protocol/SConscript index 47a19aecb..a4e2a5264 100644 --- a/src/mem/protocol/SConscript +++ b/src/mem/protocol/SConscript @@ -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: diff --git a/src/mem/slicc/main.py b/src/mem/slicc/main.py index 15eb9d4be..0b528d805 100644 --- a/src/mem/slicc/main.py +++ b/src/mem/slicc/main.py @@ -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()): diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py index 596b89f64..f35a3691a 100644 --- a/src/mem/slicc/parser.py +++ b/src/mem/slicc/parser.py @@ -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])