isa_parser: Move more stuff into the ISAParser class

This commit is contained in:
Nathan Binkert 2010-02-26 18:14:48 -08:00
parent f7a627338c
commit f82a92925c

View file

@ -1222,8 +1222,10 @@ namespace %(namespace)s {
''' '''
class ISAParser(Grammar): class ISAParser(Grammar):
def __init__(self, *args, **kwargs): def __init__(self, output_dir):
super(ISAParser, self).__init__(*args, **kwargs) super(ISAParser, self).__init__()
self.output_dir = output_dir
self.templateMap = {} self.templateMap = {}
##################################################################### #####################################################################
@ -1915,13 +1917,12 @@ StaticInstPtr
# END OF GRAMMAR RULES # END OF GRAMMAR RULES
# Now build the parser. def update_if_needed(self, file, contents):
parser = ISAParser() '''Update the output file only if the new contents are
different from the current contents. Minimizes the files that
need to be rebuilt after minor changes.'''
# Update the output file only if the new contents are different from file = os.path.join(self.output_dir, file)
# the current contents. Minimizes the files that need to be rebuilt
# after minor changes.
def update_if_needed(file, contents):
update = False update = False
if os.access(file, os.R_OK): if os.access(file, os.R_OK):
f = open(file, 'r') f = open(file, 'r')
@ -1941,50 +1942,56 @@ def update_if_needed(file, contents):
f.write(contents) f.write(contents)
f.close() f.close()
# This regular expression matches '##include' directives # This regular expression matches '##include' directives
includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$', includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
re.MULTILINE) re.MULTILINE)
# Function to replace a matched '##include' directive with the def replace_include(self, matchobj, dirname):
# contents of the specified file (with nested ##includes replaced """Function to replace a matched '##include' directive with the
# recursively). 'matchobj' is an re match object (from a match of contents of the specified file (with nested ##includes
# includeRE) and 'dirname' is the directory relative to which the file replaced recursively). 'matchobj' is an re match object
# path should be resolved. (from a match of includeRE) and 'dirname' is the directory
def replace_include(matchobj, dirname): relative to which the file path should be resolved."""
fname = matchobj.group('filename') fname = matchobj.group('filename')
full_fname = os.path.normpath(os.path.join(dirname, fname)) full_fname = os.path.normpath(os.path.join(dirname, fname))
contents = '##newfile "%s"\n%s\n##endfile\n' % \ contents = '##newfile "%s"\n%s\n##endfile\n' % \
(full_fname, read_and_flatten(full_fname)) (full_fname, self.read_and_flatten(full_fname))
return contents return contents
# Read a file and recursively flatten nested '##include' files. def read_and_flatten(self, filename):
def read_and_flatten(filename): """Read a file and recursively flatten nested '##include' files."""
current_dir = os.path.dirname(filename) current_dir = os.path.dirname(filename)
try: try:
contents = open(filename).read() contents = open(filename).read()
except IOError: except IOError:
error(0, 'Error including file "%s"' % filename) error(0, 'Error including file "%s"' % filename)
fileNameStack.push((filename, 0)) fileNameStack.push((filename, 0))
# Find any includes and include them # Find any includes and include them
contents = includeRE.sub(lambda m: replace_include(m, current_dir), def replace(matchobj):
contents) return self.replace_include(matchobj, current_dir)
contents = self.includeRE.sub(replace, contents)
fileNameStack.pop() fileNameStack.pop()
return contents return contents
# def parse_isa_desc(self, isa_desc_file):
# Read in and parse the ISA description. '''Read in and parse the ISA description.'''
#
def parse_isa_desc(isa_desc_file, output_dir):
# Read file and (recursively) all included files into a string. # Read file and (recursively) all included files into a string.
# PLY requires that the input be in a single string so we have to # PLY requires that the input be in a single string so we have to
# do this up front. # do this up front.
isa_desc = read_and_flatten(isa_desc_file) isa_desc = self.read_and_flatten(isa_desc_file)
# Initialize filename stack with outer file. # Initialize filename stack with outer file.
fileNameStack.push((isa_desc_file, 0)) fileNameStack.push((isa_desc_file, 0))
# Parse it. # Parse it.
(isa_name, namespace, global_code, namespace_code) = parser.parse(isa_desc) (isa_name, namespace, global_code, namespace_code) = \
self.parse(isa_desc)
# grab the last three path components of isa_desc_file to put in # grab the last three path components of isa_desc_file to put in
# the output # the output
@ -1995,7 +2002,7 @@ def parse_isa_desc(isa_desc_file, output_dir):
global_output = global_code.header_output global_output = global_code.header_output
namespace_output = namespace_code.header_output namespace_output = namespace_code.header_output
decode_function = '' decode_function = ''
update_if_needed(output_dir + '/decoder.hh', file_template % vars()) self.update_if_needed('decoder.hh', file_template % vars())
# generate decoder.cc # generate decoder.cc
includes = '#include "decoder.hh"' includes = '#include "decoder.hh"'
@ -2003,7 +2010,7 @@ def parse_isa_desc(isa_desc_file, output_dir):
namespace_output = namespace_code.decoder_output namespace_output = namespace_code.decoder_output
# namespace_output += namespace_code.decode_block # namespace_output += namespace_code.decode_block
decode_function = namespace_code.decode_block decode_function = namespace_code.decode_block
update_if_needed(output_dir + '/decoder.cc', file_template % vars()) self.update_if_needed('decoder.cc', file_template % vars())
# generate per-cpu exec files # generate per-cpu exec files
for cpu in cpu_models: for cpu in cpu_models:
@ -2012,17 +2019,17 @@ def parse_isa_desc(isa_desc_file, output_dir):
global_output = global_code.exec_output[cpu.name] global_output = global_code.exec_output[cpu.name]
namespace_output = namespace_code.exec_output[cpu.name] namespace_output = namespace_code.exec_output[cpu.name]
decode_function = '' decode_function = ''
update_if_needed(output_dir + '/' + cpu.filename, self.update_if_needed(cpu.filename, file_template % vars())
file_template % vars())
# The variable names here are hacky, but this will creat local variables # The variable names here are hacky, but this will creat local
# which will be referenced in vars() which have the value of the globals. # variables which will be referenced in vars() which have the
# value of the globals.
global maxInstSrcRegs global maxInstSrcRegs
MaxInstSrcRegs = maxInstSrcRegs MaxInstSrcRegs = maxInstSrcRegs
global maxInstDestRegs global maxInstDestRegs
MaxInstDestRegs = maxInstDestRegs MaxInstDestRegs = maxInstDestRegs
# max_inst_regs.hh # max_inst_regs.hh
update_if_needed(output_dir + '/max_inst_regs.hh', \ self.update_if_needed('max_inst_regs.hh',
max_inst_regs_template % vars()) max_inst_regs_template % vars())
# global list of CpuModel objects (see cpu_models.py) # global list of CpuModel objects (see cpu_models.py)
@ -2033,4 +2040,5 @@ cpu_models = []
if __name__ == '__main__': if __name__ == '__main__':
execfile(sys.argv[1]) # read in CpuModel definitions execfile(sys.argv[1]) # read in CpuModel definitions
cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]] cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
parse_isa_desc(sys.argv[2], sys.argv[3]) parser = ISAParser(sys.argv[3])
parser.parse_isa_desc(sys.argv[2])