isa_parser.py (6991:be03f7cea1f9) | isa_parser.py (6992:0288d8e8b192) |
---|---|
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 --- 143 unchanged lines hidden (view full) --- 152 # The "operands" and "snippets" attributes of the InstObjParams 153 # objects are for internal use and not substitution. 154 del myDict['operands'] 155 del myDict['snippets'] 156 157 snippetLabels = [l for l in labelRE.findall(template) 158 if d.snippets.has_key(l)] 159 | 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 --- 143 unchanged lines hidden (view full) --- 152 # The "operands" and "snippets" attributes of the InstObjParams 153 # objects are for internal use and not substitution. 154 del myDict['operands'] 155 del myDict['snippets'] 156 157 snippetLabels = [l for l in labelRE.findall(template) 158 if d.snippets.has_key(l)] 159 |
160 snippets = dict([(s, mungeSnippet(d.snippets[s])) | 160 snippets = dict([(s, self.parser.mungeSnippet(d.snippets[s])) |
161 for s in snippetLabels]) 162 163 myDict.update(snippets) 164 165 compositeCode = ' '.join(map(str, snippets.values())) 166 167 # Add in template itself in case it references any 168 # operands explicitly (like Mem) 169 compositeCode += ' ' + template 170 | 161 for s in snippetLabels]) 162 163 myDict.update(snippets) 164 165 compositeCode = ' '.join(map(str, snippets.values())) 166 167 # Add in template itself in case it references any 168 # operands explicitly (like Mem) 169 compositeCode += ' ' + template 170 |
171 operands = SubOperandList(compositeCode, d.operands) | 171 operands = SubOperandList(self.parser, compositeCode, d.operands) |
172 173 myDict['op_decl'] = operands.concatAttrStrings('op_decl') 174 175 is_src = lambda op: op.is_src 176 is_dest = lambda op: op.is_dest 177 178 myDict['op_src_decl'] = \ 179 operands.concatSomeAttrStrings(is_src, 'op_src_decl') --- 195 unchanged lines hidden (view full) --- 375 return arg 376 elif isinstance(arg, tuple): 377 return list(arg) 378 elif not arg: 379 return [] 380 else: 381 return [ arg ] 382 | 172 173 myDict['op_decl'] = operands.concatAttrStrings('op_decl') 174 175 is_src = lambda op: op.is_src 176 is_dest = lambda op: op.is_dest 177 178 myDict['op_src_decl'] = \ 179 operands.concatSomeAttrStrings(is_src, 'op_src_decl') --- 195 unchanged lines hidden (view full) --- 375 return arg 376 elif isinstance(arg, tuple): 377 return list(arg) 378 elif not arg: 379 return [] 380 else: 381 return [ arg ] 382 |
383# Generate operandTypeMap from the user's 'def operand_types' 384# statement. 385def buildOperandTypeMap(user_dict, lineno): 386 global operandTypeMap 387 operandTypeMap = {} 388 for (ext, (desc, size)) in user_dict.iteritems(): 389 if desc == 'signed int': 390 ctype = 'int%d_t' % size 391 is_signed = 1 392 elif desc == 'unsigned int': 393 ctype = 'uint%d_t' % size 394 is_signed = 0 395 elif desc == 'float': 396 is_signed = 1 # shouldn't really matter 397 if size == 32: 398 ctype = 'float' 399 elif size == 64: 400 ctype = 'double' 401 elif desc == 'twin64 int': 402 is_signed = 0 403 ctype = 'Twin64_t' 404 elif desc == 'twin32 int': 405 is_signed = 0 406 ctype = 'Twin32_t' 407 if ctype == '': 408 error(lineno, 'Unrecognized type description "%s" in user_dict') 409 operandTypeMap[ext] = (size, ctype, is_signed) 410 | |
411class Operand(object): 412 '''Base class for operand descriptors. An instance of this class 413 (or actually a class derived from this one) represents a specific 414 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate 415 derived classes encapsulates the traits of a particular operand 416 type (e.g., "32-bit integer register").''' 417 418 def buildReadCode(self, func = None): --- 24 unchanged lines hidden (view full) --- 443 "final_val": final_val} 444 return ''' 445 { 446 %s final_val = %s; 447 %s; 448 if (traceData) { traceData->setData(final_val); } 449 }''' % (self.dflt_ctype, final_val, code) 450 | 383class Operand(object): 384 '''Base class for operand descriptors. An instance of this class 385 (or actually a class derived from this one) represents a specific 386 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate 387 derived classes encapsulates the traits of a particular operand 388 type (e.g., "32-bit integer register").''' 389 390 def buildReadCode(self, func = None): --- 24 unchanged lines hidden (view full) --- 415 "final_val": final_val} 416 return ''' 417 { 418 %s final_val = %s; 419 %s; 420 if (traceData) { traceData->setData(final_val); } 421 }''' % (self.dflt_ctype, final_val, code) 422 |
451 def __init__(self, full_name, ext, is_src, is_dest): | 423 def __init__(self, parser, full_name, ext, is_src, is_dest): |
452 self.full_name = full_name 453 self.ext = ext 454 self.is_src = is_src 455 self.is_dest = is_dest 456 # The 'effective extension' (eff_ext) is either the actual 457 # extension, if one was explicitly provided, or the default. 458 if ext: 459 self.eff_ext = ext 460 else: 461 self.eff_ext = self.dflt_ext 462 | 424 self.full_name = full_name 425 self.ext = ext 426 self.is_src = is_src 427 self.is_dest = is_dest 428 # The 'effective extension' (eff_ext) is either the actual 429 # extension, if one was explicitly provided, or the default. 430 if ext: 431 self.eff_ext = ext 432 else: 433 self.eff_ext = self.dflt_ext 434 |
463 (self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext] | 435 self.size, self.ctype, self.is_signed = \ 436 parser.operandTypeMap[self.eff_ext] |
464 465 # note that mem_acc_size is undefined for non-mem operands... 466 # template must be careful not to use it if it doesn't apply. 467 if self.isMem(): 468 self.mem_acc_size = self.makeAccSize() 469 if self.ctype in ['Twin32_t', 'Twin64_t']: 470 self.mem_acc_type = 'Twin' 471 else: --- 293 unchanged lines hidden (view full) --- 765 return self.buildReadCode('readNextNPC') 766 return '%s = xc->readNextNPC();\n' % self.base_name 767 768 def makeWrite(self): 769 if self.write_code != None: 770 return self.buildWriteCode('setNextNPC') 771 return 'xc->setNextNPC(%s);\n' % self.base_name 772 | 437 438 # note that mem_acc_size is undefined for non-mem operands... 439 # template must be careful not to use it if it doesn't apply. 440 if self.isMem(): 441 self.mem_acc_size = self.makeAccSize() 442 if self.ctype in ['Twin32_t', 'Twin64_t']: 443 self.mem_acc_type = 'Twin' 444 else: --- 293 unchanged lines hidden (view full) --- 738 return self.buildReadCode('readNextNPC') 739 return '%s = xc->readNextNPC();\n' % self.base_name 740 741 def makeWrite(self): 742 if self.write_code != None: 743 return self.buildWriteCode('setNextNPC') 744 return 'xc->setNextNPC(%s);\n' % self.base_name 745 |
773def buildOperandNameMap(user_dict, lineno): 774 global operandNameMap 775 operandNameMap = {} 776 for (op_name, val) in user_dict.iteritems(): 777 (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val[:5] 778 if len(val) > 5: 779 read_code = val[5] 780 else: 781 read_code = None 782 if len(val) > 6: 783 write_code = val[6] 784 else: 785 write_code = None 786 if len(val) > 7: 787 error(lineno, 788 'error: too many attributes for operand "%s"' % 789 base_cls_name) 790 791 (dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext] 792 # Canonical flag structure is a triple of lists, where each list 793 # indicates the set of flags implied by this operand always, when 794 # used as a source, and when used as a dest, respectively. 795 # For simplicity this can be initialized using a variety of fairly 796 # obvious shortcuts; we convert these to canonical form here. 797 if not flags: 798 # no flags specified (e.g., 'None') 799 flags = ( [], [], [] ) 800 elif isinstance(flags, str): 801 # a single flag: assumed to be unconditional 802 flags = ( [ flags ], [], [] ) 803 elif isinstance(flags, list): 804 # a list of flags: also assumed to be unconditional 805 flags = ( flags, [], [] ) 806 elif isinstance(flags, tuple): 807 # it's a tuple: it should be a triple, 808 # but each item could be a single string or a list 809 (uncond_flags, src_flags, dest_flags) = flags 810 flags = (makeList(uncond_flags), 811 makeList(src_flags), makeList(dest_flags)) 812 # Accumulate attributes of new operand class in tmp_dict 813 tmp_dict = {} 814 for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri', 815 'dflt_size', 'dflt_ctype', 'dflt_is_signed', 816 'read_code', 'write_code'): 817 tmp_dict[attr] = eval(attr) 818 tmp_dict['base_name'] = op_name 819 # New class name will be e.g. "IntReg_Ra" 820 cls_name = base_cls_name + '_' + op_name 821 # Evaluate string arg to get class object. Note that the 822 # actual base class for "IntReg" is "IntRegOperand", i.e. we 823 # have to append "Operand". 824 try: 825 base_cls = eval(base_cls_name + 'Operand') 826 except NameError: 827 if debug: 828 raise 829 error(lineno, 830 'error: unknown operand base class "%s"' % base_cls_name) 831 # The following statement creates a new class called 832 # <cls_name> as a subclass of <base_cls> with the attributes 833 # in tmp_dict, just as if we evaluated a class declaration. 834 operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict) 835 836 # Define operand variables. 837 operands = user_dict.keys() 838 839 operandsREString = (r''' 840 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches 841 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix 842 (?![\w\.]) # neg. lookahead assertion: prevent partial matches 843 ''' 844 % string.join(operands, '|')) 845 846 global operandsRE 847 operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) 848 849 # Same as operandsREString, but extension is mandatory, and only two 850 # groups are returned (base and ext, not full name as above). 851 # Used for subtituting '_' for '.' to make C++ identifiers. 852 operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])' 853 % string.join(operands, '|')) 854 855 global operandsWithExtRE 856 operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE) 857 | |
858class OperandList(object): 859 '''Find all the operands in the given code block. Returns an operand 860 descriptor list (instance of class OperandList).''' 861 def __init__(self, parser, code): 862 self.items = [] 863 self.bases = {} 864 # delete comments so we don't match on reg specifiers inside 865 code = commentRE.sub('', code) 866 # search for operands 867 next_pos = 0 868 while 1: | 746class OperandList(object): 747 '''Find all the operands in the given code block. Returns an operand 748 descriptor list (instance of class OperandList).''' 749 def __init__(self, parser, code): 750 self.items = [] 751 self.bases = {} 752 # delete comments so we don't match on reg specifiers inside 753 code = commentRE.sub('', code) 754 # search for operands 755 next_pos = 0 756 while 1: |
869 match = operandsRE.search(code, next_pos) | 757 match = parser.operandsRE.search(code, next_pos) |
870 if not match: 871 # no more matches: we're done 872 break 873 op = match.groups() 874 # regexp groups are operand full name, base, and extension 875 (op_full, op_base, op_ext) = op 876 # if the token following the operand is an assignment, this is 877 # a destination (LHS), else it's a source (RHS) --- 4 unchanged lines hidden (view full) --- 882 if op_desc: 883 if op_desc.ext != op_ext: 884 error('Inconsistent extensions for operand %s' % \ 885 op_base) 886 op_desc.is_src = op_desc.is_src or is_src 887 op_desc.is_dest = op_desc.is_dest or is_dest 888 else: 889 # new operand: create new descriptor | 758 if not match: 759 # no more matches: we're done 760 break 761 op = match.groups() 762 # regexp groups are operand full name, base, and extension 763 (op_full, op_base, op_ext) = op 764 # if the token following the operand is an assignment, this is 765 # a destination (LHS), else it's a source (RHS) --- 4 unchanged lines hidden (view full) --- 770 if op_desc: 771 if op_desc.ext != op_ext: 772 error('Inconsistent extensions for operand %s' % \ 773 op_base) 774 op_desc.is_src = op_desc.is_src or is_src 775 op_desc.is_dest = op_desc.is_dest or is_dest 776 else: 777 # new operand: create new descriptor |
890 op_desc = operandNameMap[op_base](op_full, op_ext, 891 is_src, is_dest) | 778 op_desc = parser.operandNameMap[op_base](parser, 779 op_full, op_ext, is_src, is_dest) |
892 self.append(op_desc) 893 # start next search after end of current match 894 next_pos = match.end() 895 self.sort() 896 # enumerate source & dest register operands... used in building 897 # constructor later 898 self.numSrcRegs = 0 899 self.numDestRegs = 0 --- 68 unchanged lines hidden (view full) --- 968 return self.__internalConcatAttrs(attr_name, filter, []) 969 970 def sort(self): 971 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri) 972 973class SubOperandList(OperandList): 974 '''Find all the operands in the given code block. Returns an operand 975 descriptor list (instance of class OperandList).''' | 780 self.append(op_desc) 781 # start next search after end of current match 782 next_pos = match.end() 783 self.sort() 784 # enumerate source & dest register operands... used in building 785 # constructor later 786 self.numSrcRegs = 0 787 self.numDestRegs = 0 --- 68 unchanged lines hidden (view full) --- 856 return self.__internalConcatAttrs(attr_name, filter, []) 857 858 def sort(self): 859 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri) 860 861class SubOperandList(OperandList): 862 '''Find all the operands in the given code block. Returns an operand 863 descriptor list (instance of class OperandList).''' |
976 def __init__(self, code, master_list): | 864 def __init__(self, parser, code, master_list): |
977 self.items = [] 978 self.bases = {} 979 # delete comments so we don't match on reg specifiers inside 980 code = commentRE.sub('', code) 981 # search for operands 982 next_pos = 0 983 while 1: | 865 self.items = [] 866 self.bases = {} 867 # delete comments so we don't match on reg specifiers inside 868 code = commentRE.sub('', code) 869 # search for operands 870 next_pos = 0 871 while 1: |
984 match = operandsRE.search(code, next_pos) | 872 match = parser.operandsRE.search(code, next_pos) |
985 if not match: 986 # no more matches: we're done 987 break 988 op = match.groups() 989 # regexp groups are operand full name, base, and extension 990 (op_full, op_base, op_ext) = op 991 # find this op in the master list 992 op_desc = master_list.find_base(op_base) --- 20 unchanged lines hidden (view full) --- 1013# Regular expression object to match C++ comments 1014# (used in findOperands()) 1015commentRE = re.compile(r'//.*\n') 1016 1017# Regular expression object to match assignment statements 1018# (used in findOperands()) 1019assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) 1020 | 873 if not match: 874 # no more matches: we're done 875 break 876 op = match.groups() 877 # regexp groups are operand full name, base, and extension 878 (op_full, op_base, op_ext) = op 879 # find this op in the master list 880 op_desc = master_list.find_base(op_base) --- 20 unchanged lines hidden (view full) --- 901# Regular expression object to match C++ comments 902# (used in findOperands()) 903commentRE = re.compile(r'//.*\n') 904 905# Regular expression object to match assignment statements 906# (used in findOperands()) 907assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) 908 |
1021# Munge operand names in code string to make legal C++ variable names. 1022# This means getting rid of the type extension if any. 1023# (Will match base_name attribute of Operand object.) 1024def substMungedOpNames(code): 1025 return operandsWithExtRE.sub(r'\1', code) 1026 1027# Fix up code snippets for final substitution in templates. 1028def mungeSnippet(s): 1029 if isinstance(s, str): 1030 return substMungedOpNames(substBitOps(s)) 1031 else: 1032 return s 1033 | |
1034def makeFlagConstructor(flag_list): 1035 if len(flag_list) == 0: 1036 return '' 1037 # filter out repeated flags 1038 flag_list.sort() 1039 i = 1 1040 while i < len(flag_list): 1041 if flag_list[i] == flag_list[i-1]: --- 81 unchanged lines hidden (view full) --- 1123 list.__init__(self, items) 1124 1125 def push(self, item): 1126 self.append(item); 1127 1128 def top(self): 1129 return self[-1] 1130 | 909def makeFlagConstructor(flag_list): 910 if len(flag_list) == 0: 911 return '' 912 # filter out repeated flags 913 flag_list.sort() 914 i = 1 915 while i < len(flag_list): 916 if flag_list[i] == flag_list[i-1]: --- 81 unchanged lines hidden (view full) --- 998 list.__init__(self, items) 999 1000 def push(self, item): 1001 self.append(item); 1002 1003 def top(self): 1004 return self[-1] 1005 |
1131# Global stack that tracks current file and line number. 1132# Each element is a tuple (filename, lineno) that records the 1133# *current* filename and the line number in the *previous* file where 1134# it was included. 1135fileNameStack = Stack() 1136 1137 | |
1138####################### 1139# 1140# Output file template 1141# 1142 1143file_template = ''' 1144/* 1145 * DO NOT EDIT THIS FILE!!! --- 44 unchanged lines hidden (view full) --- 1190 self.formatMap = {} 1191 1192 # The format stack. 1193 self.formatStack = Stack(NoFormat()) 1194 1195 # The default case stack. 1196 self.defaultStack = Stack(None) 1197 | 1006####################### 1007# 1008# Output file template 1009# 1010 1011file_template = ''' 1012/* 1013 * DO NOT EDIT THIS FILE!!! --- 44 unchanged lines hidden (view full) --- 1058 self.formatMap = {} 1059 1060 # The format stack. 1061 self.formatStack = Stack(NoFormat()) 1062 1063 # The default case stack. 1064 self.defaultStack = Stack(None) 1065 |
1066 # Stack that tracks current file and line number. Each 1067 # element is a tuple (filename, lineno) that records the 1068 # *current* filename and the line number in the *previous* 1069 # file where it was included. 1070 self.fileNameStack = Stack() 1071 |
|
1198 symbols = ('makeList', 're', 'string') 1199 self.exportContext = dict([(s, eval(s)) for s in symbols]) 1200 1201 self.maxInstSrcRegs = 0 1202 self.maxInstDestRegs = 0 1203 1204 ##################################################################### 1205 # --- 111 unchanged lines hidden (view full) --- 1317 1318 def t_CPPDIRECTIVE(self, t): 1319 r'^\#[^\#].*\n' 1320 t.lexer.lineno += t.value.count('\n') 1321 return t 1322 1323 def t_NEWFILE(self, t): 1324 r'^\#\#newfile\s+"[\w/.-]*"' | 1072 symbols = ('makeList', 're', 'string') 1073 self.exportContext = dict([(s, eval(s)) for s in symbols]) 1074 1075 self.maxInstSrcRegs = 0 1076 self.maxInstDestRegs = 0 1077 1078 ##################################################################### 1079 # --- 111 unchanged lines hidden (view full) --- 1191 1192 def t_CPPDIRECTIVE(self, t): 1193 r'^\#[^\#].*\n' 1194 t.lexer.lineno += t.value.count('\n') 1195 return t 1196 1197 def t_NEWFILE(self, t): 1198 r'^\#\#newfile\s+"[\w/.-]*"' |
1325 fileNameStack.push((t.value[11:-1], t.lexer.lineno)) | 1199 self.fileNameStack.push((t.value[11:-1], t.lexer.lineno)) |
1326 t.lexer.lineno = 0 1327 1328 def t_ENDFILE(self, t): 1329 r'^\#\#endfile' | 1200 t.lexer.lineno = 0 1201 1202 def t_ENDFILE(self, t): 1203 r'^\#\#endfile' |
1330 (old_filename, t.lexer.lineno) = fileNameStack.pop() | 1204 (old_filename, t.lexer.lineno) = self.fileNameStack.pop() |
1331 1332 # 1333 # The functions t_NEWLINE, t_ignore, and t_error are 1334 # special for the lex module. 1335 # 1336 1337 # Newlines 1338 def t_NEWLINE(self, t): --- 145 unchanged lines hidden (view full) --- 1484 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' 1485 try: 1486 user_dict = eval('{' + t[3] + '}') 1487 except Exception, exc: 1488 if debug: 1489 raise 1490 error(t, 1491 'error: %s in def operand_types block "%s".' % (exc, t[3])) | 1205 1206 # 1207 # The functions t_NEWLINE, t_ignore, and t_error are 1208 # special for the lex module. 1209 # 1210 1211 # Newlines 1212 def t_NEWLINE(self, t): --- 145 unchanged lines hidden (view full) --- 1358 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' 1359 try: 1360 user_dict = eval('{' + t[3] + '}') 1361 except Exception, exc: 1362 if debug: 1363 raise 1364 error(t, 1365 'error: %s in def operand_types block "%s".' % (exc, t[3])) |
1492 buildOperandTypeMap(user_dict, t.lexer.lineno) | 1366 self.buildOperandTypeMap(user_dict, t.lexer.lineno) |
1493 t[0] = GenCode(self) # contributes nothing to the output C++ file 1494 1495 # Define the mapping from operand names to operand classes and 1496 # other traits. Stored in operandNameMap. 1497 def p_def_operands(self, t): 1498 'def_operands : DEF OPERANDS CODELIT SEMI' | 1367 t[0] = GenCode(self) # contributes nothing to the output C++ file 1368 1369 # Define the mapping from operand names to operand classes and 1370 # other traits. Stored in operandNameMap. 1371 def p_def_operands(self, t): 1372 'def_operands : DEF OPERANDS CODELIT SEMI' |
1499 if not globals().has_key('operandTypeMap'): | 1373 if not hasattr(self, 'operandTypeMap'): |
1500 error(t, 'error: operand types must be defined before operands') 1501 try: 1502 user_dict = eval('{' + t[3] + '}', self.exportContext) 1503 except Exception, exc: 1504 if debug: 1505 raise 1506 error(t, 'error: %s in def operands block "%s".' % (exc, t[3])) | 1374 error(t, 'error: operand types must be defined before operands') 1375 try: 1376 user_dict = eval('{' + t[3] + '}', self.exportContext) 1377 except Exception, exc: 1378 if debug: 1379 raise 1380 error(t, 'error: %s in def operands block "%s".' % (exc, t[3])) |
1507 buildOperandNameMap(user_dict, t.lexer.lineno) | 1381 self.buildOperandNameMap(user_dict, t.lexer.lineno) |
1508 t[0] = GenCode(self) # contributes nothing to the output C++ file 1509 1510 # A bitfield definition looks like: 1511 # 'def [signed] bitfield <ID> [<first>:<last>]' 1512 # This generates a preprocessor macro in the output file. 1513 def p_def_bitfield_0(self, t): 1514 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' 1515 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) --- 429 unchanged lines hidden (view full) --- 1945 return re.sub(r'%(?=\(CPU_)', '%%', template) 1946 1947 def protectNonSubstPercents(self, s): 1948 '''Protect any non-dict-substitution '%'s in a format string 1949 (i.e. those not followed by '(')''' 1950 1951 return re.sub(r'%(?!\()', '%%', s) 1952 | 1382 t[0] = GenCode(self) # contributes nothing to the output C++ file 1383 1384 # A bitfield definition looks like: 1385 # 'def [signed] bitfield <ID> [<first>:<last>]' 1386 # This generates a preprocessor macro in the output file. 1387 def p_def_bitfield_0(self, t): 1388 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' 1389 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) --- 429 unchanged lines hidden (view full) --- 1819 return re.sub(r'%(?=\(CPU_)', '%%', template) 1820 1821 def protectNonSubstPercents(self, s): 1822 '''Protect any non-dict-substitution '%'s in a format string 1823 (i.e. those not followed by '(')''' 1824 1825 return re.sub(r'%(?!\()', '%%', s) 1826 |
1827 def buildOperandTypeMap(self, user_dict, lineno): 1828 """Generate operandTypeMap from the user's 'def operand_types' 1829 statement.""" 1830 operand_type = {} 1831 for (ext, (desc, size)) in user_dict.iteritems(): 1832 if desc == 'signed int': 1833 ctype = 'int%d_t' % size 1834 is_signed = 1 1835 elif desc == 'unsigned int': 1836 ctype = 'uint%d_t' % size 1837 is_signed = 0 1838 elif desc == 'float': 1839 is_signed = 1 # shouldn't really matter 1840 if size == 32: 1841 ctype = 'float' 1842 elif size == 64: 1843 ctype = 'double' 1844 elif desc == 'twin64 int': 1845 is_signed = 0 1846 ctype = 'Twin64_t' 1847 elif desc == 'twin32 int': 1848 is_signed = 0 1849 ctype = 'Twin32_t' 1850 if ctype == '': 1851 error(parser, lineno, 1852 'Unrecognized type description "%s" in user_dict') 1853 operand_type[ext] = (size, ctype, is_signed) 1854 1855 self.operandTypeMap = operand_type 1856 1857 def buildOperandNameMap(self, user_dict, lineno): 1858 operand_name = {} 1859 for op_name, val in user_dict.iteritems(): 1860 base_cls_name, dflt_ext, reg_spec, flags, sort_pri = val[:5] 1861 if len(val) > 5: 1862 read_code = val[5] 1863 else: 1864 read_code = None 1865 if len(val) > 6: 1866 write_code = val[6] 1867 else: 1868 write_code = None 1869 if len(val) > 7: 1870 error(lineno, 1871 'error: too many attributes for operand "%s"' % 1872 base_cls_name) 1873 1874 (dflt_size, dflt_ctype, dflt_is_signed) = \ 1875 self.operandTypeMap[dflt_ext] 1876 # Canonical flag structure is a triple of lists, where each list 1877 # indicates the set of flags implied by this operand always, when 1878 # used as a source, and when used as a dest, respectively. 1879 # For simplicity this can be initialized using a variety of fairly 1880 # obvious shortcuts; we convert these to canonical form here. 1881 if not flags: 1882 # no flags specified (e.g., 'None') 1883 flags = ( [], [], [] ) 1884 elif isinstance(flags, str): 1885 # a single flag: assumed to be unconditional 1886 flags = ( [ flags ], [], [] ) 1887 elif isinstance(flags, list): 1888 # a list of flags: also assumed to be unconditional 1889 flags = ( flags, [], [] ) 1890 elif isinstance(flags, tuple): 1891 # it's a tuple: it should be a triple, 1892 # but each item could be a single string or a list 1893 (uncond_flags, src_flags, dest_flags) = flags 1894 flags = (makeList(uncond_flags), 1895 makeList(src_flags), makeList(dest_flags)) 1896 # Accumulate attributes of new operand class in tmp_dict 1897 tmp_dict = {} 1898 for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri', 1899 'dflt_size', 'dflt_ctype', 'dflt_is_signed', 1900 'read_code', 'write_code'): 1901 tmp_dict[attr] = eval(attr) 1902 tmp_dict['base_name'] = op_name 1903 # New class name will be e.g. "IntReg_Ra" 1904 cls_name = base_cls_name + '_' + op_name 1905 # Evaluate string arg to get class object. Note that the 1906 # actual base class for "IntReg" is "IntRegOperand", i.e. we 1907 # have to append "Operand". 1908 try: 1909 base_cls = eval(base_cls_name + 'Operand') 1910 except NameError: 1911 error(lineno, 1912 'error: unknown operand base class "%s"' % base_cls_name) 1913 # The following statement creates a new class called 1914 # <cls_name> as a subclass of <base_cls> with the attributes 1915 # in tmp_dict, just as if we evaluated a class declaration. 1916 operand_name[op_name] = type(cls_name, (base_cls,), tmp_dict) 1917 1918 self.operandNameMap = operand_name 1919 1920 # Define operand variables. 1921 operands = user_dict.keys() 1922 1923 operandsREString = (r''' 1924 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches 1925 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix 1926 (?![\w\.]) # neg. lookahead assertion: prevent partial matches 1927 ''' 1928 % string.join(operands, '|')) 1929 1930 self.operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) 1931 1932 # Same as operandsREString, but extension is mandatory, and only two 1933 # groups are returned (base and ext, not full name as above). 1934 # Used for subtituting '_' for '.' to make C++ identifiers. 1935 operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])' 1936 % string.join(operands, '|')) 1937 1938 self.operandsWithExtRE = \ 1939 re.compile(operandsWithExtREString, re.MULTILINE) 1940 1941 def substMungedOpNames(self, code): 1942 '''Munge operand names in code string to make legal C++ 1943 variable names. This means getting rid of the type extension 1944 if any. Will match base_name attribute of Operand object.)''' 1945 return self.operandsWithExtRE.sub(r'\1', code) 1946 1947 def mungeSnippet(self, s): 1948 '''Fix up code snippets for final substitution in templates.''' 1949 if isinstance(s, str): 1950 return self.substMungedOpNames(substBitOps(s)) 1951 else: 1952 return s 1953 |
|
1953 def update_if_needed(self, file, contents): 1954 '''Update the output file only if the new contents are 1955 different from the current contents. Minimizes the files that 1956 need to be rebuilt after minor changes.''' 1957 1958 file = os.path.join(self.output_dir, file) 1959 update = False 1960 if os.access(file, os.R_OK): --- 35 unchanged lines hidden (view full) --- 1996 """Read a file and recursively flatten nested '##include' files.""" 1997 1998 current_dir = os.path.dirname(filename) 1999 try: 2000 contents = open(filename).read() 2001 except IOError: 2002 error('Error including file "%s"' % filename) 2003 | 1954 def update_if_needed(self, file, contents): 1955 '''Update the output file only if the new contents are 1956 different from the current contents. Minimizes the files that 1957 need to be rebuilt after minor changes.''' 1958 1959 file = os.path.join(self.output_dir, file) 1960 update = False 1961 if os.access(file, os.R_OK): --- 35 unchanged lines hidden (view full) --- 1997 """Read a file and recursively flatten nested '##include' files.""" 1998 1999 current_dir = os.path.dirname(filename) 2000 try: 2001 contents = open(filename).read() 2002 except IOError: 2003 error('Error including file "%s"' % filename) 2004 |
2004 fileNameStack.push((filename, 0)) | 2005 self.fileNameStack.push((filename, 0)) |
2005 2006 # Find any includes and include them 2007 def replace(matchobj): 2008 return self.replace_include(matchobj, current_dir) 2009 contents = self.includeRE.sub(replace, contents) 2010 | 2006 2007 # Find any includes and include them 2008 def replace(matchobj): 2009 return self.replace_include(matchobj, current_dir) 2010 contents = self.includeRE.sub(replace, contents) 2011 |
2011 fileNameStack.pop() | 2012 self.fileNameStack.pop() |
2012 return contents 2013 2014 def _parse_isa_desc(self, isa_desc_file): 2015 '''Read in and parse the ISA description.''' 2016 2017 # Read file and (recursively) all included files into a string. 2018 # PLY requires that the input be in a single string so we have to 2019 # do this up front. 2020 isa_desc = self.read_and_flatten(isa_desc_file) 2021 2022 # Initialize filename stack with outer file. | 2013 return contents 2014 2015 def _parse_isa_desc(self, isa_desc_file): 2016 '''Read in and parse the ISA description.''' 2017 2018 # Read file and (recursively) all included files into a string. 2019 # PLY requires that the input be in a single string so we have to 2020 # do this up front. 2021 isa_desc = self.read_and_flatten(isa_desc_file) 2022 2023 # Initialize filename stack with outer file. |
2023 fileNameStack.push((isa_desc_file, 0)) | 2024 self.fileNameStack.push((isa_desc_file, 0)) |
2024 2025 # Parse it. 2026 (isa_name, namespace, global_code, namespace_code) = \ 2027 self.parse(isa_desc) 2028 2029 # grab the last three path components of isa_desc_file to put in 2030 # the output 2031 filename = '/'.join(isa_desc_file.split('/')[-3:]) --- 30 unchanged lines hidden (view full) --- 2062 # max_inst_regs.hh 2063 self.update_if_needed('max_inst_regs.hh', 2064 max_inst_regs_template % vars()) 2065 2066 def parse_isa_desc(self, *args, **kwargs): 2067 try: 2068 self._parse_isa_desc(*args, **kwargs) 2069 except ISAParserError, e: | 2025 2026 # Parse it. 2027 (isa_name, namespace, global_code, namespace_code) = \ 2028 self.parse(isa_desc) 2029 2030 # grab the last three path components of isa_desc_file to put in 2031 # the output 2032 filename = '/'.join(isa_desc_file.split('/')[-3:]) --- 30 unchanged lines hidden (view full) --- 2063 # max_inst_regs.hh 2064 self.update_if_needed('max_inst_regs.hh', 2065 max_inst_regs_template % vars()) 2066 2067 def parse_isa_desc(self, *args, **kwargs): 2068 try: 2069 self._parse_isa_desc(*args, **kwargs) 2070 except ISAParserError, e: |
2070 e.exit(fileNameStack) | 2071 e.exit(self.fileNameStack) |
2071 2072# Called as script: get args from command line. 2073# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models> 2074if __name__ == '__main__': 2075 execfile(sys.argv[1]) # read in CpuModel definitions 2076 cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]] 2077 ISAParser(sys.argv[3], cpu_models).parse_isa_desc(sys.argv[2]) | 2072 2073# Called as script: get args from command line. 2074# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models> 2075if __name__ == '__main__': 2076 execfile(sys.argv[1]) # read in CpuModel definitions 2077 cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]] 2078 ISAParser(sys.argv[3], cpu_models).parse_isa_desc(sys.argv[2]) |