1# Copyright (c) 2003-2005 The Regents of The University of Michigan 2# Copyright (c) 2013 Advanced Micro Devices, Inc. 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; --- 13 unchanged lines hidden (view full) --- 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27# 28# Authors: Steve Reinhardt 29 |
30from __future__ import with_statement |
31import os 32import sys 33import re 34import string 35import inspect, traceback 36# get type names 37from types import * 38 --- 270 unchanged lines hidden (view full) --- 309 # dictionary. For all other output types they get collapsed into 310 # a single string. 311 def __init__(self, parser, 312 header_output = '', decoder_output = '', exec_output = '', 313 decode_block = '', has_decode_default = False): 314 self.parser = parser 315 self.header_output = parser.expandCpuSymbolsToString(header_output) 316 self.decoder_output = parser.expandCpuSymbolsToString(decoder_output) |
317 self.exec_output = exec_output 318 self.decode_block = decode_block |
319 self.has_decode_default = has_decode_default 320 |
321 # Write these code chunks out to the filesystem. They will be properly 322 # interwoven by the write_top_level_files(). 323 def emit(self): 324 if self.header_output: 325 self.parser.get_file('header').write(self.header_output) 326 if self.decoder_output: 327 self.parser.get_file('decoder').write(self.decoder_output) 328 if self.exec_output: 329 self.parser.get_file('exec').write(self.exec_output) 330 if self.decode_block: 331 self.parser.get_file('decode_block').write(self.decode_block) 332 |
333 # Override '+' operator: generate a new GenCode object that 334 # concatenates all the individual strings in the operands. 335 def __add__(self, other): |
336 return GenCode(self.parser, 337 self.header_output + other.header_output, 338 self.decoder_output + other.decoder_output, |
339 self.exec_output + other.exec_output, |
340 self.decode_block + other.decode_block, 341 self.has_decode_default or other.has_decode_default) 342 343 # Prepend a string (typically a comment) to all the strings. 344 def prepend_all(self, pre): 345 self.header_output = pre + self.header_output 346 self.decoder_output = pre + self.decoder_output 347 self.decode_block = pre + self.decode_block |
348 self.exec_output = pre + self.exec_output |
349 350 # Wrap the decode block in a pair of strings (e.g., 'case foo:' 351 # and 'break;'). Used to build the big nested switch statement. 352 def wrap_decode_block(self, pre, post = ''): 353 self.decode_block = pre + indent(self.decode_block) + post 354 355##################################################################### 356# --- 811 unchanged lines hidden (view full) --- 1168 def push(self, item): 1169 self.append(item); 1170 1171 def top(self): 1172 return self[-1] 1173 1174####################### 1175# |
1176# ISA Parser 1177# parses ISA DSL and emits C++ headers and source |
1178# 1179 |
1180class ISAParser(Grammar): 1181 def __init__(self, output_dir, cpu_models): 1182 super(ISAParser, self).__init__() 1183 self.output_dir = output_dir 1184 |
1185 self.filename = None # for output file watermarking/scaremongering 1186 |
1187 self.cpuModels = cpu_models 1188 1189 # variable to hold templates 1190 self.templateMap = {} 1191 1192 # This dictionary maps format name strings to Format objects. 1193 self.formatMap = {} 1194 |
1195 # Track open files and, if applicable, how many chunks it has been 1196 # split into so far. 1197 self.files = {} 1198 self.splits = {} 1199 1200 # isa_name / namespace identifier from namespace declaration. 1201 # before the namespace declaration, None. 1202 self.isa_name = None 1203 self.namespace = None 1204 |
1205 # The format stack. 1206 self.formatStack = Stack(NoFormat()) 1207 1208 # The default case stack. 1209 self.defaultStack = Stack(None) 1210 1211 # Stack that tracks current file and line number. Each 1212 # element is a tuple (filename, lineno) that records the 1213 # *current* filename and the line number in the *previous* 1214 # file where it was included. 1215 self.fileNameStack = Stack() 1216 1217 symbols = ('makeList', 're', 'string') 1218 self.exportContext = dict([(s, eval(s)) for s in symbols]) 1219 1220 self.maxInstSrcRegs = 0 1221 self.maxInstDestRegs = 0 1222 self.maxMiscDestRegs = 0 1223 |
1224 def __getitem__(self, i): # Allow object (self) to be 1225 return getattr(self, i) # passed to %-substitutions 1226 1227 # Change the file suffix of a base filename: 1228 # (e.g.) decoder.cc -> decoder-g.cc.inc for 'global' outputs 1229 def suffixize(self, s, sec): 1230 extn = re.compile('(\.[^\.]+)$') # isolate extension 1231 if self.namespace: 1232 return extn.sub(r'-ns\1.inc', s) # insert some text on either side 1233 else: 1234 return extn.sub(r'-g\1.inc', s) 1235 1236 # Get the file object for emitting code into the specified section 1237 # (header, decoder, exec, decode_block). 1238 def get_file(self, section): 1239 if section == 'decode_block': 1240 filename = 'decode-method.cc.inc' 1241 else: 1242 if section == 'header': 1243 file = 'decoder.hh' 1244 else: 1245 file = '%s.cc' % section 1246 filename = self.suffixize(file, section) 1247 try: 1248 return self.files[filename] 1249 except KeyError: pass 1250 1251 f = self.open(filename) 1252 self.files[filename] = f 1253 1254 # The splittable files are the ones with many independent 1255 # per-instruction functions - the decoder's instruction constructors 1256 # and the instruction execution (execute()) methods. These both have 1257 # the suffix -ns.cc.inc, meaning they are within the namespace part 1258 # of the ISA, contain object-emitting C++ source, and are included 1259 # into other top-level files. These are the files that need special 1260 # #define's to allow parts of them to be compiled separately. Rather 1261 # than splitting the emissions into separate files, the monolithic 1262 # output of the ISA parser is maintained, but the value (or lack 1263 # thereof) of the __SPLIT definition during C preprocessing will 1264 # select the different chunks. If no 'split' directives are used, 1265 # the cpp emissions have no effect. 1266 if re.search('-ns.cc.inc$', filename): 1267 print >>f, '#if !defined(__SPLIT) || (__SPLIT == 1)' 1268 self.splits[f] = 1 1269 # ensure requisite #include's 1270 elif filename in ['decoder-g.cc.inc', 'exec-g.cc.inc']: 1271 print >>f, '#include "decoder.hh"' 1272 elif filename == 'decoder-g.hh.inc': 1273 print >>f, '#include "base/bitfield.hh"' 1274 1275 return f 1276 1277 # Weave together the parts of the different output sections by 1278 # #include'ing them into some very short top-level .cc/.hh files. 1279 # These small files make it much clearer how this tool works, since 1280 # you directly see the chunks emitted as files that are #include'd. 1281 def write_top_level_files(self): 1282 dep = self.open('inc.d', bare=True) 1283 1284 # decoder header - everything depends on this 1285 file = 'decoder.hh' 1286 with self.open(file) as f: 1287 inc = [] 1288 1289 fn = 'decoder-g.hh.inc' 1290 assert(fn in self.files) 1291 f.write('#include "%s"\n' % fn) 1292 inc.append(fn) 1293 1294 fn = 'decoder-ns.hh.inc' 1295 assert(fn in self.files) 1296 f.write('namespace %s {\n#include "%s"\n}\n' 1297 % (self.namespace, fn)) 1298 inc.append(fn) 1299 1300 print >>dep, file+':', ' '.join(inc) 1301 1302 # decoder method - cannot be split 1303 file = 'decoder.cc' 1304 with self.open(file) as f: 1305 inc = [] 1306 1307 fn = 'decoder-g.cc.inc' 1308 assert(fn in self.files) 1309 f.write('#include "%s"\n' % fn) 1310 inc.append(fn) 1311 1312 fn = 'decode-method.cc.inc' 1313 # is guaranteed to have been written for parse to complete 1314 f.write('#include "%s"\n' % fn) 1315 inc.append(fn) 1316 1317 inc.append("decoder.hh") 1318 print >>dep, file+':', ' '.join(inc) 1319 1320 extn = re.compile('(\.[^\.]+)$') 1321 1322 # instruction constructors 1323 splits = self.splits[self.get_file('decoder')] 1324 file_ = 'inst-constrs.cc' 1325 for i in range(1, splits+1): 1326 if splits > 1: 1327 file = extn.sub(r'-%d\1' % i, file_) 1328 else: 1329 file = file_ 1330 with self.open(file) as f: 1331 inc = [] 1332 1333 fn = 'decoder-g.cc.inc' 1334 assert(fn in self.files) 1335 f.write('#include "%s"\n' % fn) 1336 inc.append(fn) 1337 1338 fn = 'decoder-ns.cc.inc' 1339 assert(fn in self.files) 1340 print >>f, 'namespace %s {' % self.namespace 1341 if splits > 1: 1342 print >>f, '#define __SPLIT %u' % i 1343 print >>f, '#include "%s"' % fn 1344 print >>f, '}' 1345 inc.append(fn) 1346 1347 inc.append("decoder.hh") 1348 print >>dep, file+':', ' '.join(inc) 1349 1350 # instruction execution per-CPU model 1351 splits = self.splits[self.get_file('exec')] 1352 for cpu in self.cpuModels: 1353 for i in range(1, splits+1): 1354 if splits > 1: 1355 file = extn.sub(r'_%d\1' % i, cpu.filename) 1356 else: 1357 file = cpu.filename 1358 with self.open(file) as f: 1359 inc = [] 1360 1361 fn = 'exec-g.cc.inc' 1362 assert(fn in self.files) 1363 f.write('#include "%s"\n' % fn) 1364 inc.append(fn) 1365 1366 f.write(cpu.includes+"\n") 1367 1368 fn = 'exec-ns.cc.inc' 1369 assert(fn in self.files) 1370 print >>f, 'namespace %s {' % self.namespace 1371 print >>f, '#define CPU_EXEC_CONTEXT %s' \ 1372 % cpu.strings['CPU_exec_context'] 1373 if splits > 1: 1374 print >>f, '#define __SPLIT %u' % i 1375 print >>f, '#include "%s"' % fn 1376 print >>f, '}' 1377 inc.append(fn) 1378 1379 inc.append("decoder.hh") 1380 print >>dep, file+':', ' '.join(inc) 1381 1382 # max_inst_regs.hh 1383 self.update('max_inst_regs.hh', 1384 '''namespace %(namespace)s { 1385 const int MaxInstSrcRegs = %(maxInstSrcRegs)d; 1386 const int MaxInstDestRegs = %(maxInstDestRegs)d; 1387 const int MaxMiscDestRegs = %(maxMiscDestRegs)d;\n}\n''' % self) 1388 print >>dep, 'max_inst_regs.hh:' 1389 1390 dep.close() 1391 1392 1393 scaremonger_template ='''// DO NOT EDIT 1394// This file was automatically generated from an ISA description: 1395// %(filename)s 1396 1397'''; 1398 |
1399 ##################################################################### 1400 # 1401 # Lexer 1402 # 1403 # The PLY lexer module takes two things as input: 1404 # - A list of token names (the string list 'tokens') 1405 # - A regular expression describing a match for each token. The 1406 # regexp for token FOO can be provided in two ways: --- 5 unchanged lines hidden (view full) --- 1412 ##################################################################### 1413 1414 # Reserved words. These are listed separately as they are matched 1415 # using the same regexp as generic IDs, but distinguished in the 1416 # t_ID() function. The PLY documentation suggests this approach. 1417 reserved = ( 1418 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT', 1419 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS', |
1420 'OUTPUT', 'SIGNED', 'SPLIT', 'TEMPLATE' |
1421 ) 1422 1423 # List of tokens. The lex module requires this. 1424 tokens = reserved + ( 1425 # identifier 1426 'ID', 1427 1428 # integer literal --- 136 unchanged lines hidden (view full) --- 1565 # The LHS of the first grammar rule is used as the start symbol 1566 # (in this case, 'specification'). Note that this rule enforces 1567 # that there will be exactly one namespace declaration, with 0 or 1568 # more global defs/decls before and after it. The defs & decls 1569 # before the namespace decl will be outside the namespace; those 1570 # after will be inside. The decoder function is always inside the 1571 # namespace. 1572 def p_specification(self, t): |
1573 'specification : opt_defs_and_outputs top_level_decode_block' |
1574 |
1575 for f in self.splits.iterkeys(): 1576 f.write('\n#endif\n') |
1577 |
1578 for f in self.files.itervalues(): # close ALL the files; 1579 f.close() # not doing so can cause compilation to fail 1580 1581 self.write_top_level_files() 1582 1583 t[0] = True 1584 1585 # 'opt_defs_and_outputs' is a possibly empty sequence of def and/or 1586 # output statements. Its productions do the hard work of eventually 1587 # instantiating a GenCode, which are generally emitted (written to disk) 1588 # as soon as possible, except for the decode_block, which has to be 1589 # accumulated into one large function of nested switch/case blocks. |
1590 def p_opt_defs_and_outputs_0(self, t): 1591 'opt_defs_and_outputs : empty' |
1592 1593 def p_opt_defs_and_outputs_1(self, t): 1594 'opt_defs_and_outputs : defs_and_outputs' |
1595 1596 def p_defs_and_outputs_0(self, t): 1597 'defs_and_outputs : def_or_output' |
1598 1599 def p_defs_and_outputs_1(self, t): 1600 'defs_and_outputs : defs_and_outputs def_or_output' |
1601 1602 # The list of possible definition/output statements. |
1603 # They are all processed as they are seen. |
1604 def p_def_or_output(self, t): |
1605 '''def_or_output : name_decl 1606 | def_format |
1607 | def_bitfield 1608 | def_bitfield_struct 1609 | def_template 1610 | def_operand_types 1611 | def_operands |
1612 | output 1613 | global_let 1614 | split''' 1615 1616 # Utility function used by both invocations of splitting - explicit 1617 # 'split' keyword and split() function inside "let {{ }};" blocks. 1618 def split(self, sec, write=False): 1619 assert(sec != 'header' and "header cannot be split") 1620 1621 f = self.get_file(sec) 1622 self.splits[f] += 1 1623 s = '\n#endif\n#if __SPLIT == %u\n' % self.splits[f] 1624 if write: 1625 f.write(s) 1626 else: 1627 return s 1628 1629 # split output file to reduce compilation time 1630 def p_split(self, t): 1631 'split : SPLIT output_type SEMI' 1632 assert(self.isa_name and "'split' not allowed before namespace decl") 1633 1634 self.split(t[2], True) 1635 1636 def p_output_type(self, t): 1637 '''output_type : DECODER 1638 | HEADER 1639 | EXEC''' |
1640 t[0] = t[1] 1641 |
1642 # ISA name declaration looks like "namespace <foo>;" 1643 def p_name_decl(self, t): 1644 'name_decl : NAMESPACE ID SEMI' 1645 assert(self.isa_name == None and "Only 1 namespace decl permitted") 1646 self.isa_name = t[2] 1647 self.namespace = t[2] + 'Inst' 1648 |
1649 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied 1650 # directly to the appropriate output section. 1651 1652 # Massage output block by substituting in template definitions and 1653 # bit operators. We handle '%'s embedded in the string that don't 1654 # indicate template substitutions (or CPU-specific symbols, which 1655 # get handled in GenCode) by doubling them first so that the 1656 # format operation will reduce them back to single '%'s. 1657 def process_output(self, s): 1658 s = self.protectNonSubstPercents(s) 1659 # protects cpu-specific symbols too 1660 s = self.protectCpuSymbols(s) 1661 return substBitOps(s % self.templateMap) 1662 |
1663 def p_output(self, t): 1664 'output : OUTPUT output_type CODELIT SEMI' 1665 kwargs = { t[2]+'_output' : self.process_output(t[3]) } 1666 GenCode(self, **kwargs).emit() |
1667 |
1668 # global let blocks 'let {{...}}' (Python code blocks) are 1669 # executed directly when seen. Note that these execute in a 1670 # special variable context 'exportContext' to prevent the code 1671 # from polluting this script's namespace. 1672 def p_global_let(self, t): 1673 'global_let : LET CODELIT SEMI' |
1674 def _split(sec): 1675 return self.split(sec) |
1676 self.updateExportContext() 1677 self.exportContext["header_output"] = '' 1678 self.exportContext["decoder_output"] = '' 1679 self.exportContext["exec_output"] = '' 1680 self.exportContext["decode_block"] = '' |
1681 self.exportContext["split"] = _split 1682 split_setup = ''' 1683def wrap(func): 1684 def split(sec): 1685 globals()[sec + '_output'] += func(sec) 1686 return split 1687split = wrap(split) 1688del wrap 1689''' 1690 # This tricky setup (immediately above) allows us to just write 1691 # (e.g.) "split('exec')" in the Python code and the split #ifdef's 1692 # will automatically be added to the exec_output variable. The inner 1693 # Python execution environment doesn't know about the split points, 1694 # so we carefully inject and wrap a closure that can retrieve the 1695 # next split's #define from the parser and add it to the current 1696 # emission-in-progress. |
1697 try: |
1698 exec split_setup+fixPythonIndentation(t[2]) in self.exportContext |
1699 except Exception, exc: 1700 if debug: 1701 raise 1702 error(t, 'error: %s in global let block "%s".' % (exc, t[2])) |
1703 GenCode(self, 1704 header_output=self.exportContext["header_output"], 1705 decoder_output=self.exportContext["decoder_output"], 1706 exec_output=self.exportContext["exec_output"], 1707 decode_block=self.exportContext["decode_block"]).emit() |
1708 1709 # Define the mapping from operand type extensions to C++ types and 1710 # bit widths (stored in operandTypeMap). 1711 def p_def_operand_types(self, t): 1712 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' 1713 try: 1714 self.operandTypeMap = eval('{' + t[3] + '}') 1715 except Exception, exc: 1716 if debug: 1717 raise 1718 error(t, 1719 'error: %s in def operand_types block "%s".' % (exc, t[3])) |
1720 1721 # Define the mapping from operand names to operand classes and 1722 # other traits. Stored in operandNameMap. 1723 def p_def_operands(self, t): 1724 'def_operands : DEF OPERANDS CODELIT SEMI' 1725 if not hasattr(self, 'operandTypeMap'): 1726 error(t, 'error: operand types must be defined before operands') 1727 try: 1728 user_dict = eval('{' + t[3] + '}', self.exportContext) 1729 except Exception, exc: 1730 if debug: 1731 raise 1732 error(t, 'error: %s in def operands block "%s".' % (exc, t[3])) 1733 self.buildOperandNameMap(user_dict, t.lexer.lineno) |
1734 1735 # A bitfield definition looks like: 1736 # 'def [signed] bitfield <ID> [<first>:<last>]' 1737 # This generates a preprocessor macro in the output file. 1738 def p_def_bitfield_0(self, t): 1739 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' 1740 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) 1741 if (t[2] == 'signed'): 1742 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr) 1743 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) |
1744 GenCode(self, header_output=hash_define).emit() |
1745 1746 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]' 1747 def p_def_bitfield_1(self, t): 1748 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI' 1749 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6]) 1750 if (t[2] == 'signed'): 1751 expr = 'sext<%d>(%s)' % (1, expr) 1752 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) |
1753 GenCode(self, header_output=hash_define).emit() |
1754 1755 # alternate form for structure member: 'def bitfield <ID> <ID>' 1756 def p_def_bitfield_struct(self, t): 1757 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' 1758 if (t[2] != ''): 1759 error(t, 'error: structure bitfields are always unsigned.') 1760 expr = 'machInst.%s' % t[5] 1761 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) |
1762 GenCode(self, header_output=hash_define).emit() |
1763 1764 def p_id_with_dot_0(self, t): 1765 'id_with_dot : ID' 1766 t[0] = t[1] 1767 1768 def p_id_with_dot_1(self, t): 1769 'id_with_dot : ID DOT id_with_dot' 1770 t[0] = t[1] + t[2] + t[3] 1771 1772 def p_opt_signed_0(self, t): 1773 'opt_signed : SIGNED' 1774 t[0] = t[1] 1775 1776 def p_opt_signed_1(self, t): 1777 'opt_signed : empty' 1778 t[0] = '' 1779 1780 def p_def_template(self, t): 1781 'def_template : DEF TEMPLATE ID CODELIT SEMI' |
1782 if t[3] in self.templateMap: 1783 print "warning: template %s already defined" % t[3] |
1784 self.templateMap[t[3]] = Template(self, t[4]) |
1785 1786 # An instruction format definition looks like 1787 # "def format <fmt>(<params>) {{...}};" 1788 def p_def_format(self, t): 1789 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' 1790 (id, params, code) = (t[3], t[5], t[7]) 1791 self.defFormat(id, params, code, t.lexer.lineno) |
1792 1793 # The formal parameter list for an instruction format is a 1794 # possibly empty list of comma-separated parameters. Positional 1795 # (standard, non-keyword) parameters must come first, followed by 1796 # keyword parameters, followed by a '*foo' parameter that gets 1797 # excess positional arguments (as in Python). Each of these three 1798 # parameter categories is optional. 1799 # --- 54 unchanged lines hidden (view full) --- 1854 1855 # End of format definition-related rules. 1856 ############## 1857 1858 # 1859 # A decode block looks like: 1860 # decode <field1> [, <field2>]* [default <inst>] { ... } 1861 # |
1862 def p_top_level_decode_block(self, t): 1863 'top_level_decode_block : decode_block' 1864 codeObj = t[1] 1865 codeObj.wrap_decode_block(''' 1866StaticInstPtr 1867%(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst) 1868{ 1869 using namespace %(namespace)s; 1870''' % self, '}') 1871 1872 codeObj.emit() 1873 |
1874 def p_decode_block(self, t): 1875 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' 1876 default_defaults = self.defaultStack.pop() 1877 codeObj = t[5] 1878 # use the "default defaults" only if there was no explicit 1879 # default statement in decode_stmt_list 1880 if not codeObj.has_decode_default: 1881 codeObj += default_defaults --- 398 unchanged lines hidden (view full) --- 2280 2281 def mungeSnippet(self, s): 2282 '''Fix up code snippets for final substitution in templates.''' 2283 if isinstance(s, str): 2284 return self.substMungedOpNames(substBitOps(s)) 2285 else: 2286 return s 2287 |
2288 def open(self, name, bare=False): 2289 '''Open the output file for writing and include scary warning.''' 2290 filename = os.path.join(self.output_dir, name) 2291 f = open(filename, 'w') 2292 if f: 2293 if not bare: 2294 f.write(ISAParser.scaremonger_template % self) 2295 return f 2296 |
2297 def update(self, file, contents): |
2298 '''Update the output file only. Scons should handle the case when 2299 the new contents are unchanged using its built-in hash feature.''' 2300 f = self.open(file) |
2301 f.write(contents) 2302 f.close() 2303 2304 # This regular expression matches '##include' directives 2305 includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[^"]*)".*$', 2306 re.MULTILINE) 2307 2308 def replace_include(self, matchobj, dirname): --- 23 unchanged lines hidden (view full) --- 2332 # Find any includes and include them 2333 def replace(matchobj): 2334 return self.replace_include(matchobj, current_dir) 2335 contents = self.includeRE.sub(replace, contents) 2336 2337 self.fileNameStack.pop() 2338 return contents 2339 |
2340 AlreadyGenerated = {} 2341 |
2342 def _parse_isa_desc(self, isa_desc_file): 2343 '''Read in and parse the ISA description.''' 2344 |
2345 # The build system can end up running the ISA parser twice: once to 2346 # finalize the build dependencies, and then to actually generate 2347 # the files it expects (in src/arch/$ARCH/generated). This code 2348 # doesn't do anything different either time, however; the SCons 2349 # invocations just expect different things. Since this code runs 2350 # within SCons, we can just remember that we've already run and 2351 # not perform a completely unnecessary run, since the ISA parser's 2352 # effect is idempotent. 2353 if isa_desc_file in ISAParser.AlreadyGenerated: 2354 return 2355 2356 # grab the last three path components of isa_desc_file 2357 self.filename = '/'.join(isa_desc_file.split('/')[-3:]) 2358 |
2359 # Read file and (recursively) all included files into a string. 2360 # PLY requires that the input be in a single string so we have to 2361 # do this up front. 2362 isa_desc = self.read_and_flatten(isa_desc_file) 2363 2364 # Initialize filename stack with outer file. 2365 self.fileNameStack.push((isa_desc_file, 0)) 2366 |
2367 # Parse. 2368 self.parse_string(isa_desc) |
2369 |
2370 ISAParser.AlreadyGenerated[isa_desc_file] = None |
2371 |
2372 def parse_isa_desc(self, *args, **kwargs): 2373 try: 2374 self._parse_isa_desc(*args, **kwargs) 2375 except ISAParserError, e: 2376 e.exit(self.fileNameStack) 2377 2378# Called as script: get args from command line. 2379# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models> 2380if __name__ == '__main__': 2381 execfile(sys.argv[1]) # read in CpuModel definitions 2382 cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]] 2383 ISAParser(sys.argv[3], cpu_models).parse_isa_desc(sys.argv[2]) |