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 + -
显示快捷键?