isa_parser.py (12222:6db0fc7407a5) isa_parser.py (12234:78ece221f9f5)
1# Copyright (c) 2014, 2016 ARM Limited
2# All rights reserved
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder. You may use the software subject to the license

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

117 self.template = t
118
119 def subst(self, d):
120 myDict = None
121
122 # Protect non-Python-dict substitutions (e.g. if there's a printf
123 # in the templated C++ code)
124 template = self.parser.protectNonSubstPercents(self.template)
1# Copyright (c) 2014, 2016 ARM Limited
2# All rights reserved
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder. You may use the software subject to the license

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

117 self.template = t
118
119 def subst(self, d):
120 myDict = None
121
122 # Protect non-Python-dict substitutions (e.g. if there's a printf
123 # in the templated C++ code)
124 template = self.parser.protectNonSubstPercents(self.template)
125 # CPU-model-specific substitutions are handled later (in GenCode).
126 template = self.parser.protectCpuSymbols(template)
127
128 # Build a dict ('myDict') to use for the template substitution.
129 # Start with the template namespace. Make a copy since we're
130 # going to modify it.
131 myDict = self.parser.templateMap.copy()
132
133 if isinstance(d, InstObjParams):
134 # If we're dealing with an InstObjParams object, we need

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

213 myDict.update(d)
214 elif hasattr(d, '__dict__'):
215 # if the argument is an object, we use its attribute map.
216 myDict.update(d.__dict__)
217 else:
218 raise TypeError, "Template.subst() arg must be or have dictionary"
219 return template % myDict
220
125
126 # Build a dict ('myDict') to use for the template substitution.
127 # Start with the template namespace. Make a copy since we're
128 # going to modify it.
129 myDict = self.parser.templateMap.copy()
130
131 if isinstance(d, InstObjParams):
132 # If we're dealing with an InstObjParams object, we need

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

211 myDict.update(d)
212 elif hasattr(d, '__dict__'):
213 # if the argument is an object, we use its attribute map.
214 myDict.update(d.__dict__)
215 else:
216 raise TypeError, "Template.subst() arg must be or have dictionary"
217 return template % myDict
218
221 # Convert to string. This handles the case when a template with a
222 # CPU-specific term gets interpolated into another template or into
223 # an output block.
219 # Convert to string.
224 def __str__(self):
220 def __str__(self):
225 return self.parser.expandCpuSymbolsToString(self.template)
221 return self.template
226
227################
228# Format object.
229#
230# A format object encapsulates an instruction format. It must provide
231# a defineInst() method that generates the code for an instruction
232# definition.
233

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

279###############
280# GenCode class
281#
282# The GenCode class encapsulates generated code destined for various
283# output files. The header_output and decoder_output attributes are
284# strings containing code destined for decoder.hh and decoder.cc
285# respectively. The decode_block attribute contains code to be
286# incorporated in the decode function itself (that will also end up in
222
223################
224# Format object.
225#
226# A format object encapsulates an instruction format. It must provide
227# a defineInst() method that generates the code for an instruction
228# definition.
229

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

275###############
276# GenCode class
277#
278# The GenCode class encapsulates generated code destined for various
279# output files. The header_output and decoder_output attributes are
280# strings containing code destined for decoder.hh and decoder.cc
281# respectively. The decode_block attribute contains code to be
282# incorporated in the decode function itself (that will also end up in
287# decoder.cc). The exec_output attribute is a dictionary with a key
288# for each CPU model name; the value associated with a particular key
289# is the string of code for that CPU model's exec.cc file. The
290# has_decode_default attribute is used in the decode block to allow
291# explicit default clauses to override default default clauses.
283# decoder.cc). The exec_output attribute is the string of code for the
284# exec.cc file. The has_decode_default attribute is used in the decode block
285# to allow explicit default clauses to override default default clauses.
292
293class GenCode(object):
286
287class GenCode(object):
294 # Constructor. At this point we substitute out all CPU-specific
295 # symbols. For the exec output, these go into the per-model
296 # dictionary. For all other output types they get collapsed into
297 # a single string.
288 # Constructor.
298 def __init__(self, parser,
299 header_output = '', decoder_output = '', exec_output = '',
300 decode_block = '', has_decode_default = False):
301 self.parser = parser
289 def __init__(self, parser,
290 header_output = '', decoder_output = '', exec_output = '',
291 decode_block = '', has_decode_default = False):
292 self.parser = parser
302 self.header_output = parser.expandCpuSymbolsToString(header_output)
303 self.decoder_output = parser.expandCpuSymbolsToString(decoder_output)
293 self.header_output = header_output
294 self.decoder_output = decoder_output
304 self.exec_output = exec_output
305 self.decode_block = decode_block
306 self.has_decode_default = has_decode_default
307
308 # Write these code chunks out to the filesystem. They will be properly
309 # interwoven by the write_top_level_files().
310 def emit(self):
311 if self.header_output:

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

1457
1458#######################
1459#
1460# ISA Parser
1461# parses ISA DSL and emits C++ headers and source
1462#
1463
1464class ISAParser(Grammar):
295 self.exec_output = exec_output
296 self.decode_block = decode_block
297 self.has_decode_default = has_decode_default
298
299 # Write these code chunks out to the filesystem. They will be properly
300 # interwoven by the write_top_level_files().
301 def emit(self):
302 if self.header_output:

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

1448
1449#######################
1450#
1451# ISA Parser
1452# parses ISA DSL and emits C++ headers and source
1453#
1454
1455class ISAParser(Grammar):
1465 class CpuModel(object):
1466 def __init__(self, name, filename, includes, strings):
1467 self.name = name
1468 self.filename = filename
1469 self.includes = includes
1470 self.strings = strings
1471
1472 def __init__(self, output_dir):
1473 super(ISAParser, self).__init__()
1474 self.output_dir = output_dir
1475
1476 self.filename = None # for output file watermarking/scaremongering
1477
1456 def __init__(self, output_dir):
1457 super(ISAParser, self).__init__()
1458 self.output_dir = output_dir
1459
1460 self.filename = None # for output file watermarking/scaremongering
1461
1478 self.cpuModels = [
1479 ISAParser.CpuModel('ExecContext',
1480 'generic_cpu_exec.cc',
1481 '#include "cpu/exec_context.hh"',
1482 { "CPU_exec_context" : "ExecContext" }),
1483 ]
1484
1485 # variable to hold templates
1486 self.templateMap = {}
1487
1488 # This dictionary maps format name strings to Format objects.
1489 self.formatMap = {}
1490
1491 # Track open files and, if applicable, how many chunks it has been
1492 # split into so far.

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

1620 fn = 'decoder-ns.cc.inc'
1621 assert(fn in self.files)
1622 print >>f, 'namespace %s {' % self.namespace
1623 if splits > 1:
1624 print >>f, '#define __SPLIT %u' % i
1625 print >>f, '#include "%s"' % fn
1626 print >>f, '}'
1627
1462 # variable to hold templates
1463 self.templateMap = {}
1464
1465 # This dictionary maps format name strings to Format objects.
1466 self.formatMap = {}
1467
1468 # Track open files and, if applicable, how many chunks it has been
1469 # split into so far.

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

1597 fn = 'decoder-ns.cc.inc'
1598 assert(fn in self.files)
1599 print >>f, 'namespace %s {' % self.namespace
1600 if splits > 1:
1601 print >>f, '#define __SPLIT %u' % i
1602 print >>f, '#include "%s"' % fn
1603 print >>f, '}'
1604
1628 # instruction execution per-CPU model
1605 # instruction execution
1629 splits = self.splits[self.get_file('exec')]
1606 splits = self.splits[self.get_file('exec')]
1630 for cpu in self.cpuModels:
1631 for i in range(1, splits+1):
1607 for i in range(1, splits+1):
1608 file = 'generic_cpu_exec.cc'
1609 if splits > 1:
1610 file = extn.sub(r'_%d\1' % i, file)
1611 with self.open(file) as f:
1612 fn = 'exec-g.cc.inc'
1613 assert(fn in self.files)
1614 f.write('#include "%s"\n' % fn)
1615 f.write('#include "cpu/exec_context.hh"\n')
1616 f.write('#include "decoder.hh"\n')
1617
1618 fn = 'exec-ns.cc.inc'
1619 assert(fn in self.files)
1620 print >>f, 'namespace %s {' % self.namespace
1632 if splits > 1:
1621 if splits > 1:
1633 file = extn.sub(r'_%d\1' % i, cpu.filename)
1634 else:
1635 file = cpu.filename
1636 with self.open(file) as f:
1637 fn = 'exec-g.cc.inc'
1638 assert(fn in self.files)
1639 f.write('#include "%s"\n' % fn)
1622 print >>f, '#define __SPLIT %u' % i
1623 print >>f, '#include "%s"' % fn
1624 print >>f, '}'
1640
1625
1641 f.write(cpu.includes+"\n")
1642
1643 fn = 'decoder.hh'
1644 f.write('#include "%s"\n' % fn)
1645
1646 fn = 'exec-ns.cc.inc'
1647 assert(fn in self.files)
1648 print >>f, 'namespace %s {' % self.namespace
1649 print >>f, '#define CPU_EXEC_CONTEXT %s' \
1650 % cpu.strings['CPU_exec_context']
1651 if splits > 1:
1652 print >>f, '#define __SPLIT %u' % i
1653 print >>f, '#include "%s"' % fn
1654 print >>f, '}'
1655
1656 # max_inst_regs.hh
1657 self.update('max_inst_regs.hh',
1658 '''namespace %(namespace)s {
1659 const int MaxInstSrcRegs = %(maxInstSrcRegs)d;
1660 const int MaxInstDestRegs = %(maxInstDestRegs)d;
1661 const int MaxMiscDestRegs = %(maxMiscDestRegs)d;\n}\n''' % self)
1662
1663 scaremonger_template ='''// DO NOT EDIT

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

1916 self.isa_name = t[2]
1917 self.namespace = t[2] + 'Inst'
1918
1919 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1920 # directly to the appropriate output section.
1921
1922 # Massage output block by substituting in template definitions and
1923 # bit operators. We handle '%'s embedded in the string that don't
1626 # max_inst_regs.hh
1627 self.update('max_inst_regs.hh',
1628 '''namespace %(namespace)s {
1629 const int MaxInstSrcRegs = %(maxInstSrcRegs)d;
1630 const int MaxInstDestRegs = %(maxInstDestRegs)d;
1631 const int MaxMiscDestRegs = %(maxMiscDestRegs)d;\n}\n''' % self)
1632
1633 scaremonger_template ='''// DO NOT EDIT

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

1886 self.isa_name = t[2]
1887 self.namespace = t[2] + 'Inst'
1888
1889 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1890 # directly to the appropriate output section.
1891
1892 # Massage output block by substituting in template definitions and
1893 # bit operators. We handle '%'s embedded in the string that don't
1924 # indicate template substitutions (or CPU-specific symbols, which
1925 # get handled in GenCode) by doubling them first so that the
1894 # indicate template substitutions by doubling them first so that the
1926 # format operation will reduce them back to single '%'s.
1927 def process_output(self, s):
1928 s = self.protectNonSubstPercents(s)
1895 # format operation will reduce them back to single '%'s.
1896 def process_output(self, s):
1897 s = self.protectNonSubstPercents(s)
1929 # protects cpu-specific symbols too
1930 s = self.protectCpuSymbols(s)
1931 return substBitOps(s % self.templateMap)
1932
1933 def p_output(self, t):
1934 'output : OUTPUT output_type CODELIT SEMI'
1935 kwargs = { t[2]+'_output' : self.process_output(t[3]) }
1936 GenCode(self, **kwargs).emit()
1937
1938 # global let blocks 'let {{...}}' (Python code blocks) are

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

2421
2422 # make sure we haven't already defined this one
2423 if id in self.formatMap:
2424 error(lineno, 'format %s redefined.' % id)
2425
2426 # create new object and store in global map
2427 self.formatMap[id] = Format(id, params, code)
2428
1898 return substBitOps(s % self.templateMap)
1899
1900 def p_output(self, t):
1901 'output : OUTPUT output_type CODELIT SEMI'
1902 kwargs = { t[2]+'_output' : self.process_output(t[3]) }
1903 GenCode(self, **kwargs).emit()
1904
1905 # global let blocks 'let {{...}}' (Python code blocks) are

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

2388
2389 # make sure we haven't already defined this one
2390 if id in self.formatMap:
2391 error(lineno, 'format %s redefined.' % id)
2392
2393 # create new object and store in global map
2394 self.formatMap[id] = Format(id, params, code)
2395
2429 def expandCpuSymbolsToDict(self, template):
2430 '''Expand template with CPU-specific references into a
2431 dictionary with an entry for each CPU model name. The entry
2432 key is the model name and the corresponding value is the
2433 template with the CPU-specific refs substituted for that
2434 model.'''
2435
2436 # Protect '%'s that don't go with CPU-specific terms
2437 t = re.sub(r'%(?!\(CPU_)', '%%', template)
2438 result = {}
2439 for cpu in self.cpuModels:
2440 result[cpu.name] = t % cpu.strings
2441 return result
2442
2443 def expandCpuSymbolsToString(self, template):
2444 '''*If* the template has CPU-specific references, return a
2445 single string containing a copy of the template for each CPU
2446 model with the corresponding values substituted in. If the
2447 template has no CPU-specific references, it is returned
2448 unmodified.'''
2449
2450 if template.find('%(CPU_') != -1:
2451 return reduce(lambda x,y: x+y,
2452 self.expandCpuSymbolsToDict(template).values())
2453 else:
2454 return template
2455
2456 def protectCpuSymbols(self, template):
2457 '''Protect CPU-specific references by doubling the
2458 corresponding '%'s (in preparation for substituting a different
2459 set of references into the template).'''
2460
2461 return re.sub(r'%(?=\(CPU_)', '%%', template)
2462
2463 def protectNonSubstPercents(self, s):
2464 '''Protect any non-dict-substitution '%'s in a format string
2465 (i.e. those not followed by '(')'''
2466
2467 return re.sub(r'%(?!\()', '%%', s)
2468
2469 def buildOperandNameMap(self, user_dict, lineno):
2470 operand_name = {}

--- 212 unchanged lines hidden ---
2396 def protectNonSubstPercents(self, s):
2397 '''Protect any non-dict-substitution '%'s in a format string
2398 (i.e. those not followed by '(')'''
2399
2400 return re.sub(r'%(?!\()', '%%', s)
2401
2402 def buildOperandNameMap(self, user_dict, lineno):
2403 operand_name = {}

--- 212 unchanged lines hidden ---