isa_parser.py
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· Python 代码 · 共 1,867 行 · 第 1/5 页
PY
1,867 行
return '' def makeWrite(self): return '' # Return the memory access size *in bits*, suitable for # forming a type via "uint%d_t". Divide by 8 if you want bytes. def makeAccSize(self): return self.sizeclass UPCOperand(Operand): def makeConstructor(self): return '' def makeRead(self): return '%s = xc->readMicroPC();\n' % self.base_name def makeWrite(self): return 'xc->setMicroPC(%s);\n' % self.base_nameclass NUPCOperand(Operand): def makeConstructor(self): return '' def makeRead(self): return '%s = xc->readNextMicroPC();\n' % self.base_name def makeWrite(self): return 'xc->setNextMicroPC(%s);\n' % self.base_nameclass NPCOperand(Operand): def makeConstructor(self): return '' def makeRead(self): return '%s = xc->readNextPC();\n' % self.base_name def makeWrite(self): return 'xc->setNextPC(%s);\n' % self.base_nameclass NNPCOperand(Operand): def makeConstructor(self): return '' def makeRead(self): return '%s = xc->readNextNPC();\n' % self.base_name def makeWrite(self): return 'xc->setNextNPC(%s);\n' % self.base_namedef buildOperandNameMap(userDict, lineno): global operandNameMap operandNameMap = {} for (op_name, val) in userDict.iteritems(): (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val (dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext] # Canonical flag structure is a triple of lists, where each list # indicates the set of flags implied by this operand always, when # used as a source, and when used as a dest, respectively. # For simplicity this can be initialized using a variety of fairly # obvious shortcuts; we convert these to canonical form here. if not flags: # no flags specified (e.g., 'None') flags = ( [], [], [] ) elif isinstance(flags, str): # a single flag: assumed to be unconditional flags = ( [ flags ], [], [] ) elif isinstance(flags, list): # a list of flags: also assumed to be unconditional flags = ( flags, [], [] ) elif isinstance(flags, tuple): # it's a tuple: it should be a triple, # but each item could be a single string or a list (uncond_flags, src_flags, dest_flags) = flags flags = (makeList(uncond_flags), makeList(src_flags), makeList(dest_flags)) # Accumulate attributes of new operand class in tmp_dict tmp_dict = {} for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri', 'dflt_size', 'dflt_ctype', 'dflt_is_signed'): tmp_dict[attr] = eval(attr) tmp_dict['base_name'] = op_name # New class name will be e.g. "IntReg_Ra" cls_name = base_cls_name + '_' + op_name # Evaluate string arg to get class object. Note that the # actual base class for "IntReg" is "IntRegOperand", i.e. we # have to append "Operand". try: base_cls = eval(base_cls_name + 'Operand') except NameError: error(lineno, 'error: unknown operand base class "%s"' % base_cls_name) # The following statement creates a new class called # <cls_name> as a subclass of <base_cls> with the attributes # in tmp_dict, just as if we evaluated a class declaration. operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict) # Define operand variables. operands = userDict.keys() operandsREString = (r''' (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix (?![\w\.]) # neg. lookahead assertion: prevent partial matches ''' % string.join(operands, '|')) global operandsRE operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) # Same as operandsREString, but extension is mandatory, and only two # groups are returned (base and ext, not full name as above). # Used for subtituting '_' for '.' to make C++ identifiers. operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])' % string.join(operands, '|')) global operandsWithExtRE operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)maxInstSrcRegs = 0maxInstDestRegs = 0class OperandList: # Find all the operands in the given code block. Returns an operand # descriptor list (instance of class OperandList). def __init__(self, code): self.items = [] self.bases = {} # delete comments so we don't match on reg specifiers inside code = commentRE.sub('', code) # search for operands next_pos = 0 while 1: match = operandsRE.search(code, next_pos) if not match: # no more matches: we're done break op = match.groups() # regexp groups are operand full name, base, and extension (op_full, op_base, op_ext) = op # if the token following the operand is an assignment, this is # a destination (LHS), else it's a source (RHS) is_dest = (assignRE.match(code, match.end()) != None) is_src = not is_dest # see if we've already seen this one op_desc = self.find_base(op_base) if op_desc: if op_desc.ext != op_ext: error(0, 'Inconsistent extensions for operand %s' % \ op_base) op_desc.is_src = op_desc.is_src or is_src op_desc.is_dest = op_desc.is_dest or is_dest else: # new operand: create new descriptor op_desc = operandNameMap[op_base](op_full, op_ext, is_src, is_dest) self.append(op_desc) # start next search after end of current match next_pos = match.end() self.sort() # enumerate source & dest register operands... used in building # constructor later self.numSrcRegs = 0 self.numDestRegs = 0 self.numFPDestRegs = 0 self.numIntDestRegs = 0 self.memOperand = None for op_desc in self.items: if op_desc.isReg(): if op_desc.is_src: op_desc.src_reg_idx = self.numSrcRegs self.numSrcRegs += 1 if op_desc.is_dest: op_desc.dest_reg_idx = self.numDestRegs self.numDestRegs += 1 if op_desc.isFloatReg(): self.numFPDestRegs += 1 elif op_desc.isIntReg(): self.numIntDestRegs += 1 elif op_desc.isMem(): if self.memOperand: error(0, "Code block has more than one memory operand.") self.memOperand = op_desc global maxInstSrcRegs global maxInstDestRegs if maxInstSrcRegs < self.numSrcRegs: maxInstSrcRegs = self.numSrcRegs if maxInstDestRegs < self.numDestRegs: maxInstDestRegs = self.numDestRegs # now make a final pass to finalize op_desc fields that may depend # on the register enumeration for op_desc in self.items: op_desc.finalize() def __len__(self): return len(self.items) def __getitem__(self, index): return self.items[index] def append(self, op_desc): self.items.append(op_desc) self.bases[op_desc.base_name] = op_desc def find_base(self, base_name): # like self.bases[base_name], but returns None if not found # (rather than raising exception) return self.bases.get(base_name) # internal helper function for concat[Some]Attr{Strings|Lists} def __internalConcatAttrs(self, attr_name, filter, result): for op_desc in self.items: if filter(op_desc): result += getattr(op_desc, attr_name) return result # return a single string that is the concatenation of the (string) # values of the specified attribute for all operands def concatAttrStrings(self, attr_name): return self.__internalConcatAttrs(attr_name, lambda x: 1, '') # like concatAttrStrings, but only include the values for the operands # for which the provided filter function returns true def concatSomeAttrStrings(self, filter, attr_name): return self.__internalConcatAttrs(attr_name, filter, '') # return a single list that is the concatenation of the (list) # values of the specified attribute for all operands def concatAttrLists(self, attr_name): return self.__internalConcatAttrs(attr_name, lambda x: 1, []) # like concatAttrLists, but only include the values for the operands # for which the provided filter function returns true def concatSomeAttrLists(self, filter, attr_name): return self.__internalConcatAttrs(attr_name, filter, []) def sort(self): self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)class SubOperandList(OperandList): # Find all the operands in the given code block. Returns an operand # descriptor list (instance of class OperandList). def __init__(self, code, master_list): self.items = [] self.bases = {} # delete comments so we don't match on reg specifiers inside code = commentRE.sub('', code) # search for operands next_pos = 0 while 1: match = operandsRE.search(code, next_pos) if not match: # no more matches: we're done break op = match.groups() # regexp groups are operand full name, base, and extension (op_full, op_base, op_ext) = op # find this op in the master list op_desc = master_list.find_base(op_base) if not op_desc: error(0, 'Found operand %s which is not in the master list!' \ ' This is an internal error' % \ op_base) else: # See if we've already found this operand op_desc = self.find_base(op_base) if not op_desc: # if not, add a reference to it to this sub list self.append(master_list.bases[op_base]) # start next search after end of current match next_pos = match.end() self.sort() self.memOperand = None for op_desc in self.items: if op_desc.isMem(): if self.memOperand: error(0, "Code block has more than one memory operand.") self.memOperand = op_desc# Regular expression object to match C++ comments# (used in findOperands())commentRE = re.compile(r'//.*\n')# Regular expression object to match assignment statements# (used in findOperands())assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)# Munge operand names in code string to make legal C++ variable names.# This means getting rid of the type extension if any.# (Will match base_name attribute of Operand object.)def substMungedOpNames(code): return operandsWithExtRE.sub(r'\1', code)# Fix up code snippets for final substitution in templates.def mungeSnippet(s): if isinstance(s, str): return substMungedOpNames(substBitOps(s)) else: return sdef makeFlagConstructor(flag_list): if len(flag_list) == 0: return '' # filter out repeated flags flag_list.sort() i = 1 while i < len(flag_list): if flag_list[i] == flag_list[i-1]: del flag_list[i] else: i += 1 pre = '\n\tflags[' post = '] = true;' code = pre + string.join(flag_list, post + pre) + post return code# Assume all instruction flags are of the form 'IsFoo'instFlagRE = re.compile(r'Is.*')# OpClass constants end in 'Op' except No_OpClassopClassRE = re.compile(r'.*Op|No_OpClass')class InstObjParams: def __init__(self, mnem, class_name, base_class = '', snippets = {}, opt_args = []): self.mnemonic = mnem self.class_name = class_name self.base_class = base_class if not isinstance(snippets, dict): snippets = {'code' : snippets} compositeCode = ' '.join(map(str, snippets.values())) self.snippets = snippets self.operands = OperandList(compositeCode) self.constructor = self.operands.concatAttrStrings('constructor') self.constructor += \ '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs self.constructor += \ '\n\t_numDestRegs = %d;' % self.operands.numDestRegs self.constructor += \ '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs self.constructor += \ '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs self.flags = self.operands.concatAttrLists('flags') # Make a basic guess on the operand class (function unit type). # These are good enough for most cases, and can be overridden # later otherwise. if 'IsStore' in self.flags: self.op_class = 'MemWriteOp' elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags: self.op_class = 'MemReadOp' elif 'IsFloating' in self.flags: self.op_class = 'FloatAddOp' else: self.op_class = 'IntAluOp' # Optional arguments are assumed to be either StaticInst flags # or an OpClass value. To avoid having to import a complete # list of these values to match against, we do it ad-hoc # with regexps. for oa in opt_args: if instFlagRE.match(oa): self.flags.append(oa) elif opClassRE.match(oa): self.op_class = oa else: error(0, 'InstObjPa
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?