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