isa_parser.py (6988:55b7e9ba3b4f) isa_parser.py (6989:73afd9458692)
1# Copyright (c) 2003-2005 The Regents of The University of Michigan
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met: redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer;
8# redistributions in binary form must reproduce the above copyright

--- 195 unchanged lines hidden (view full) ---

204
205################
206# Format object.
207#
208# A format object encapsulates an instruction format. It must provide
209# a defineInst() method that generates the code for an instruction
210# definition.
211
1# Copyright (c) 2003-2005 The Regents of The University of Michigan
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met: redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer;
8# redistributions in binary form must reproduce the above copyright

--- 195 unchanged lines hidden (view full) ---

204
205################
206# Format object.
207#
208# A format object encapsulates an instruction format. It must provide
209# a defineInst() method that generates the code for an instruction
210# definition.
211
212exportContextSymbols = ('InstObjParams', 'makeList', 're', 'string')
213
214exportContext = {}
215
216def updateExportContext():
217 exportContext.update(exportDict(*exportContextSymbols))
218 exportContext.update(parser.templateMap)
219
220def exportDict(*symNames):
221 return dict([(s, eval(s)) for s in symNames])
222
223
224class Format(object):
212class Format(object):
225 def __init__(self, id, params, code):
226 # constructor: just save away arguments
213 def __init__(self, parser, id, params, code):
214 self.parser = parser
227 self.id = id
228 self.params = params
229 label = 'def format ' + id
230 self.user_code = compile(fixPythonIndentation(code), label, 'exec')
231 param_list = string.join(params, ", ")
232 f = '''def defInst(_code, _context, %s):
233 my_locals = vars().copy()
234 exec _code in _context, my_locals
235 return my_locals\n''' % param_list
236 c = compile(f, label + ' wrapper', 'exec')
237 exec c
238 self.func = defInst
239
240 def defineInst(self, name, args, lineno):
215 self.id = id
216 self.params = params
217 label = 'def format ' + id
218 self.user_code = compile(fixPythonIndentation(code), label, 'exec')
219 param_list = string.join(params, ", ")
220 f = '''def defInst(_code, _context, %s):
221 my_locals = vars().copy()
222 exec _code in _context, my_locals
223 return my_locals\n''' % param_list
224 c = compile(f, label + ' wrapper', 'exec')
225 exec c
226 self.func = defInst
227
228 def defineInst(self, name, args, lineno):
241 context = {}
242 updateExportContext()
243 context.update(exportContext)
229 self.parser.updateExportContext()
230 context = self.parser.exportContext.copy()
244 if len(name):
245 Name = name[0].upper()
246 if len(name) > 1:
247 Name += name[1:]
231 if len(name):
232 Name = name[0].upper()
233 if len(name) > 1:
234 Name += name[1:]
248 context.update({ 'name': name, 'Name': Name })
235 context.update({ 'name' : name, 'Name' : Name })
249 try:
250 vars = self.func(self.user_code, context, *args[0], **args[1])
251 except Exception, exc:
252 if debug:
253 raise
254 error(lineno, 'error defining "%s": %s.' % (name, exc))
255 for k in vars.keys():
256 if k not in ('header_output', 'decoder_output',

--- 6 unchanged lines hidden (view full) ---

263class NoFormat(object):
264 def __init__(self):
265 self.defaultInst = ''
266
267 def defineInst(self, name, args, lineno):
268 error(lineno,
269 'instruction definition "%s" with no active format!' % name)
270
236 try:
237 vars = self.func(self.user_code, context, *args[0], **args[1])
238 except Exception, exc:
239 if debug:
240 raise
241 error(lineno, 'error defining "%s": %s.' % (name, exc))
242 for k in vars.keys():
243 if k not in ('header_output', 'decoder_output',

--- 6 unchanged lines hidden (view full) ---

250class NoFormat(object):
251 def __init__(self):
252 self.defaultInst = ''
253
254 def defineInst(self, name, args, lineno):
255 error(lineno,
256 'instruction definition "%s" with no active format!' % name)
257
271# This dictionary maps format name strings to Format objects.
272formatMap = {}
273
274# Define a new format
275def defFormat(id, params, code, lineno):
276 # make sure we haven't already defined this one
277 if formatMap.get(id, None) != None:
278 error(lineno, 'format %s redefined.' % id)
279 # create new object and store in global map
280 formatMap[id] = Format(id, params, code)
281
282#####################################################################
283#
284# Support Classes
285#
286#####################################################################
287
288# Expand template with CPU-specific references into a dictionary with
289# an entry for each CPU model name. The entry key is the model name

--- 955 unchanged lines hidden (view full) ---

1245
1246class ISAParser(Grammar):
1247 def __init__(self, output_dir):
1248 super(ISAParser, self).__init__()
1249 self.output_dir = output_dir
1250
1251 self.templateMap = {}
1252
258#####################################################################
259#
260# Support Classes
261#
262#####################################################################
263
264# Expand template with CPU-specific references into a dictionary with
265# an entry for each CPU model name. The entry key is the model name

--- 955 unchanged lines hidden (view full) ---

1221
1222class ISAParser(Grammar):
1223 def __init__(self, output_dir):
1224 super(ISAParser, self).__init__()
1225 self.output_dir = output_dir
1226
1227 self.templateMap = {}
1228
1229 # This dictionary maps format name strings to Format objects.
1230 self.formatMap = {}
1231
1253 # The format stack.
1254 self.formatStack = Stack(NoFormat())
1255
1256 # The default case stack.
1257 self.defaultStack = Stack(None)
1258
1232 # The format stack.
1233 self.formatStack = Stack(NoFormat())
1234
1235 # The default case stack.
1236 self.defaultStack = Stack(None)
1237
1238 self.exportContext = {}
1239
1259 #####################################################################
1260 #
1261 # Lexer
1262 #
1263 # The PLY lexer module takes two things as input:
1264 # - A list of token names (the string list 'tokens')
1265 # - A regular expression describing a match for each token. The
1266 # regexp for token FOO can be provided in two ways:

--- 244 unchanged lines hidden (view full) ---

1511 t[0] = GenCode(exec_output = self.process_output(t[3]))
1512
1513 # global let blocks 'let {{...}}' (Python code blocks) are
1514 # executed directly when seen. Note that these execute in a
1515 # special variable context 'exportContext' to prevent the code
1516 # from polluting this script's namespace.
1517 def p_global_let(self, t):
1518 'global_let : LET CODELIT SEMI'
1240 #####################################################################
1241 #
1242 # Lexer
1243 #
1244 # The PLY lexer module takes two things as input:
1245 # - A list of token names (the string list 'tokens')
1246 # - A regular expression describing a match for each token. The
1247 # regexp for token FOO can be provided in two ways:

--- 244 unchanged lines hidden (view full) ---

1492 t[0] = GenCode(exec_output = self.process_output(t[3]))
1493
1494 # global let blocks 'let {{...}}' (Python code blocks) are
1495 # executed directly when seen. Note that these execute in a
1496 # special variable context 'exportContext' to prevent the code
1497 # from polluting this script's namespace.
1498 def p_global_let(self, t):
1499 'global_let : LET CODELIT SEMI'
1519 updateExportContext()
1520 exportContext["header_output"] = ''
1521 exportContext["decoder_output"] = ''
1522 exportContext["exec_output"] = ''
1523 exportContext["decode_block"] = ''
1500 self.updateExportContext()
1501 self.exportContext["header_output"] = ''
1502 self.exportContext["decoder_output"] = ''
1503 self.exportContext["exec_output"] = ''
1504 self.exportContext["decode_block"] = ''
1524 try:
1505 try:
1525 exec fixPythonIndentation(t[2]) in exportContext
1506 exec fixPythonIndentation(t[2]) in self.exportContext
1526 except Exception, exc:
1527 if debug:
1528 raise
1529 error(t, 'error: %s in global let block "%s".' % (exc, t[2]))
1507 except Exception, exc:
1508 if debug:
1509 raise
1510 error(t, 'error: %s in global let block "%s".' % (exc, t[2]))
1530 t[0] = GenCode(header_output = exportContext["header_output"],
1531 decoder_output = exportContext["decoder_output"],
1532 exec_output = exportContext["exec_output"],
1533 decode_block = exportContext["decode_block"])
1511 t[0] = GenCode(header_output=self.exportContext["header_output"],
1512 decoder_output=self.exportContext["decoder_output"],
1513 exec_output=self.exportContext["exec_output"],
1514 decode_block=self.exportContext["decode_block"])
1534
1535 # Define the mapping from operand type extensions to C++ types and
1536 # bit widths (stored in operandTypeMap).
1537 def p_def_operand_types(self, t):
1538 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1539 try:
1540 user_dict = eval('{' + t[3] + '}')
1541 except Exception, exc:

--- 6 unchanged lines hidden (view full) ---

1548
1549 # Define the mapping from operand names to operand classes and
1550 # other traits. Stored in operandNameMap.
1551 def p_def_operands(self, t):
1552 'def_operands : DEF OPERANDS CODELIT SEMI'
1553 if not globals().has_key('operandTypeMap'):
1554 error(t, 'error: operand types must be defined before operands')
1555 try:
1515
1516 # Define the mapping from operand type extensions to C++ types and
1517 # bit widths (stored in operandTypeMap).
1518 def p_def_operand_types(self, t):
1519 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1520 try:
1521 user_dict = eval('{' + t[3] + '}')
1522 except Exception, exc:

--- 6 unchanged lines hidden (view full) ---

1529
1530 # Define the mapping from operand names to operand classes and
1531 # other traits. Stored in operandNameMap.
1532 def p_def_operands(self, t):
1533 'def_operands : DEF OPERANDS CODELIT SEMI'
1534 if not globals().has_key('operandTypeMap'):
1535 error(t, 'error: operand types must be defined before operands')
1536 try:
1556 user_dict = eval('{' + t[3] + '}', exportContext)
1537 user_dict = eval('{' + t[3] + '}', self.exportContext)
1557 except Exception, exc:
1558 if debug:
1559 raise
1560 error(t, 'error: %s in def operands block "%s".' % (exc, t[3]))
1561 buildOperandNameMap(user_dict, t.lexer.lineno)
1562 t[0] = GenCode() # contributes nothing to the output C++ file
1563
1564 # A bitfield definition looks like:

--- 46 unchanged lines hidden (view full) ---

1611 self.templateMap[t[3]] = Template(t[4])
1612 t[0] = GenCode()
1613
1614 # An instruction format definition looks like
1615 # "def format <fmt>(<params>) {{...}};"
1616 def p_def_format(self, t):
1617 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1618 (id, params, code) = (t[3], t[5], t[7])
1538 except Exception, exc:
1539 if debug:
1540 raise
1541 error(t, 'error: %s in def operands block "%s".' % (exc, t[3]))
1542 buildOperandNameMap(user_dict, t.lexer.lineno)
1543 t[0] = GenCode() # contributes nothing to the output C++ file
1544
1545 # A bitfield definition looks like:

--- 46 unchanged lines hidden (view full) ---

1592 self.templateMap[t[3]] = Template(t[4])
1593 t[0] = GenCode()
1594
1595 # An instruction format definition looks like
1596 # "def format <fmt>(<params>) {{...}};"
1597 def p_def_format(self, t):
1598 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1599 (id, params, code) = (t[3], t[5], t[7])
1619 defFormat(id, params, code, t.lexer.lineno)
1600 self.defFormat(id, params, code, t.lexer.lineno)
1620 t[0] = GenCode()
1621
1622 # The formal parameter list for an instruction format is a
1623 # possibly empty list of comma-separated parameters. Positional
1624 # (standard, non-keyword) parameters must come first, followed by
1625 # keyword parameters, followed by a '*foo' parameter that gets
1626 # excess positional arguments (as in Python). Each of these three
1627 # parameter categories is optional.

--- 138 unchanged lines hidden (view full) ---

1766 t[0] = t[4]
1767
1768 # This rule exists so we can set the current format (& push the
1769 # stack) when we recognize the format name part of the format
1770 # block.
1771 def p_push_format_id(self, t):
1772 'push_format_id : ID'
1773 try:
1601 t[0] = GenCode()
1602
1603 # The formal parameter list for an instruction format is a
1604 # possibly empty list of comma-separated parameters. Positional
1605 # (standard, non-keyword) parameters must come first, followed by
1606 # keyword parameters, followed by a '*foo' parameter that gets
1607 # excess positional arguments (as in Python). Each of these three
1608 # parameter categories is optional.

--- 138 unchanged lines hidden (view full) ---

1747 t[0] = t[4]
1748
1749 # This rule exists so we can set the current format (& push the
1750 # stack) when we recognize the format name part of the format
1751 # block.
1752 def p_push_format_id(self, t):
1753 'push_format_id : ID'
1754 try:
1774 self.formatStack.push(formatMap[t[1]])
1755 self.formatStack.push(self.formatMap[t[1]])
1775 t[0] = ('', '// format %s' % t[1])
1776 except KeyError:
1777 error(t, 'instruction format "%s" not defined.' % t[1])
1778
1779 # Nested decode block: if the value of the current field matches
1780 # the specified constant, do a nested decode on some other field.
1781 def p_decode_stmt_decode(self, t):
1782 'decode_stmt : case_label COLON decode_block'

--- 57 unchanged lines hidden (view full) ---

1840 codeObj.prepend_all(comment)
1841 t[0] = codeObj
1842
1843 # Define an instruction using an explicitly specified format:
1844 # "<fmt>::<mnemonic>(<args>)"
1845 def p_inst_1(self, t):
1846 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1847 try:
1756 t[0] = ('', '// format %s' % t[1])
1757 except KeyError:
1758 error(t, 'instruction format "%s" not defined.' % t[1])
1759
1760 # Nested decode block: if the value of the current field matches
1761 # the specified constant, do a nested decode on some other field.
1762 def p_decode_stmt_decode(self, t):
1763 'decode_stmt : case_label COLON decode_block'

--- 57 unchanged lines hidden (view full) ---

1821 codeObj.prepend_all(comment)
1822 t[0] = codeObj
1823
1824 # Define an instruction using an explicitly specified format:
1825 # "<fmt>::<mnemonic>(<args>)"
1826 def p_inst_1(self, t):
1827 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1828 try:
1848 format = formatMap[t[1]]
1829 format = self.formatMap[t[1]]
1849 except KeyError:
1850 error(t, 'instruction format "%s" not defined.' % t[1])
1851 codeObj = format.defineInst(t[3], t[5], t.lexer.lineno)
1852 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5])
1853 codeObj.prepend_all(comment)
1854 t[0] = codeObj
1855
1856 # The arg list generates a tuple, where the first element is a

--- 83 unchanged lines hidden (view full) ---

1940 def p_error(self, t):
1941 if t:
1942 error(t, "syntax error at '%s'" % t.value)
1943 else:
1944 error("unknown syntax error")
1945
1946 # END OF GRAMMAR RULES
1947
1830 except KeyError:
1831 error(t, 'instruction format "%s" not defined.' % t[1])
1832 codeObj = format.defineInst(t[3], t[5], t.lexer.lineno)
1833 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5])
1834 codeObj.prepend_all(comment)
1835 t[0] = codeObj
1836
1837 # The arg list generates a tuple, where the first element is a

--- 83 unchanged lines hidden (view full) ---

1921 def p_error(self, t):
1922 if t:
1923 error(t, "syntax error at '%s'" % t.value)
1924 else:
1925 error("unknown syntax error")
1926
1927 # END OF GRAMMAR RULES
1928
1929 exportContextSymbols = ('InstObjParams', 'makeList', 're', 'string')
1930 def updateExportContext(self):
1931 exportDict = dict([(s, eval(s)) for s in self.exportContextSymbols])
1932 self.exportContext.update(exportDict)
1933 self.exportContext.update(parser.templateMap)
1934
1935 def defFormat(self, id, params, code, lineno):
1936 '''Define a new format'''
1937
1938 # make sure we haven't already defined this one
1939 if id in self.formatMap:
1940 error(lineno, 'format %s redefined.' % id)
1941
1942 # create new object and store in global map
1943 self.formatMap[id] = Format(self, id, params, code)
1944
1948 def update_if_needed(self, file, contents):
1949 '''Update the output file only if the new contents are
1950 different from the current contents. Minimizes the files that
1951 need to be rebuilt after minor changes.'''
1952
1953 file = os.path.join(self.output_dir, file)
1954 update = False
1955 if os.access(file, os.R_OK):

--- 123 unchanged lines hidden ---
1945 def update_if_needed(self, file, contents):
1946 '''Update the output file only if the new contents are
1947 different from the current contents. Minimizes the files that
1948 need to be rebuilt after minor changes.'''
1949
1950 file = os.path.join(self.output_dir, file)
1951 update = False
1952 if os.access(file, os.R_OK):

--- 123 unchanged lines hidden ---