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.
This commit is contained in:
Nathan Binkert 2011-07-05 18:30:05 -07:00
parent 831e9b3b7a
commit da1eaaca0e
10 changed files with 100 additions and 100 deletions

View 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";

View 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";

View 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";

View 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";

View 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";

View 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";

View 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";

View 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:

View 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()):

View 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])