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