X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Farch%2Fisa_parser.py;h=d5b5bbe4f9c56586082475689918e2ffc335da2c;hb=931405da2f8828c23463d83f0b77b551d633565c;hp=9b63c88428e76e65e9dcd309d3a5425f682a1e3a;hpb=82874eefca231fa960fbd39a90ed98929915c414;p=gem5.git diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index 9b63c8842..d5b5bbe4f 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -25,7 +25,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Authors: Steve Reinhardt -# Korey Sewell import os import sys @@ -40,8 +39,8 @@ from types import * # of 'build' in the current tree. sys.path[0:0] = [os.environ['M5_PLY']] -import lex -import yacc +from ply import lex +from ply import yacc ##################################################################### # @@ -81,12 +80,12 @@ tokens = reserved + ( # code literal 'CODELIT', - # ( ) [ ] { } < > , ; : :: * + # ( ) [ ] { } < > , ; . : :: * 'LPAREN', 'RPAREN', 'LBRACKET', 'RBRACKET', 'LBRACE', 'RBRACE', 'LESS', 'GREATER', 'EQUALS', - 'COMMA', 'SEMI', 'COLON', 'DBLCOLON', + 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON', 'ASTERISK', # C preprocessor directives @@ -113,9 +112,10 @@ t_GREATER = r'\>' t_EQUALS = r'=' t_COMMA = r',' t_SEMI = r';' +t_DOT = r'\.' t_COLON = r':' t_DBLCOLON = r'::' -t_ASTERISK = r'\*' +t_ASTERISK = r'\*' # Identifiers and reserved words reserved_map = { } @@ -133,7 +133,7 @@ def t_INTLIT(t): try: t.value = int(t.value,0) except ValueError: - error(t.lineno, 'Integer value "%s" too large' % t.value) + error(t.lexer.lineno, 'Integer value "%s" too large' % t.value) t.value = 0 return t @@ -143,7 +143,7 @@ def t_STRLIT(t): r"(?m)'([^'])+'" # strip off quotes t.value = t.value[1:-1] - t.lineno += t.value.count('\n') + t.lexer.lineno += t.value.count('\n') return t @@ -153,22 +153,22 @@ def t_CODELIT(t): r"(?m)\{\{([^\}]|}(?!\}))+\}\}" # strip off {{ & }} t.value = t.value[2:-2] - t.lineno += t.value.count('\n') + t.lexer.lineno += t.value.count('\n') return t def t_CPPDIRECTIVE(t): r'^\#[^\#].*\n' - t.lineno += t.value.count('\n') + t.lexer.lineno += t.value.count('\n') return t def t_NEWFILE(t): r'^\#\#newfile\s+"[\w/.-]*"' - fileNameStack.push((t.value[11:-1], t.lineno)) - t.lineno = 0 + fileNameStack.push((t.value[11:-1], t.lexer.lineno)) + t.lexer.lineno = 0 def t_ENDFILE(t): r'^\#\#endfile' - (old_filename, t.lineno) = fileNameStack.pop() + (old_filename, t.lexer.lineno) = fileNameStack.pop() # # The functions t_NEWLINE, t_ignore, and t_error are @@ -178,7 +178,7 @@ def t_ENDFILE(t): # Newlines def t_NEWLINE(t): r'\n+' - t.lineno += t.value.count('\n') + t.lexer.lineno += t.value.count('\n') # Comments def t_comment(t): @@ -189,11 +189,11 @@ t_ignore = ' \t\x0c' # Error handler def t_error(t): - error(t.lineno, "illegal character '%s'" % t.value[0]) + error(t.lexer.lineno, "illegal character '%s'" % t.value[0]) t.skip(1) # Build the lexer -lex.lex() +lexer = lex.lex() ##################################################################### # @@ -261,6 +261,7 @@ def p_defs_and_outputs_1(t): def p_def_or_output(t): '''def_or_output : def_format | def_bitfield + | def_bitfield_struct | def_template | def_operand_types | def_operands @@ -309,12 +310,19 @@ def p_output_exec(t): def p_global_let(t): 'global_let : LET CODELIT SEMI' updateExportContext() + exportContext["header_output"] = '' + exportContext["decoder_output"] = '' + exportContext["exec_output"] = '' + exportContext["decode_block"] = '' try: exec fixPythonIndentation(t[2]) in exportContext except Exception, exc: - error(t.lineno(1), + error(t.lexer.lineno, 'error: %s in global let block "%s".' % (exc, t[2])) - t[0] = GenCode() # contributes nothing to the output C++ file + t[0] = GenCode(header_output = exportContext["header_output"], + decoder_output = exportContext["decoder_output"], + exec_output = exportContext["exec_output"], + decode_block = exportContext["decode_block"]) # Define the mapping from operand type extensions to C++ types and bit # widths (stored in operandTypeMap). @@ -323,9 +331,9 @@ def p_def_operand_types(t): try: userDict = eval('{' + t[3] + '}') except Exception, exc: - error(t.lineno(1), + error(t.lexer.lineno, 'error: %s in def operand_types block "%s".' % (exc, t[3])) - buildOperandTypeMap(userDict, t.lineno(1)) + buildOperandTypeMap(userDict, t.lexer.lineno) t[0] = GenCode() # contributes nothing to the output C++ file # Define the mapping from operand names to operand classes and other @@ -333,14 +341,14 @@ def p_def_operand_types(t): def p_def_operands(t): 'def_operands : DEF OPERANDS CODELIT SEMI' if not globals().has_key('operandTypeMap'): - error(t.lineno(1), + error(t.lexer.lineno, 'error: operand types must be defined before operands') try: - userDict = eval('{' + t[3] + '}') + userDict = eval('{' + t[3] + '}', exportContext) except Exception, exc: - error(t.lineno(1), + error(t.lexer.lineno, 'error: %s in def operands block "%s".' % (exc, t[3])) - buildOperandNameMap(userDict, t.lineno(1)) + buildOperandNameMap(userDict, t.lexer.lineno) t[0] = GenCode() # contributes nothing to the output C++ file # A bitfield definition looks like: @@ -363,6 +371,23 @@ def p_def_bitfield_1(t): hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) t[0] = GenCode(header_output = hash_define) +# alternate form for structure member: 'def bitfield ' +def p_def_bitfield_struct(t): + 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' + if (t[2] != ''): + error(t.lexer.lineno, 'error: structure bitfields are always unsigned.') + expr = 'machInst.%s' % t[5] + hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) + t[0] = GenCode(header_output = hash_define) + +def p_id_with_dot_0(t): + 'id_with_dot : ID' + t[0] = t[1] + +def p_id_with_dot_1(t): + 'id_with_dot : ID DOT id_with_dot' + t[0] = t[1] + t[2] + t[3] + def p_opt_signed_0(t): 'opt_signed : SIGNED' t[0] = t[1] @@ -384,7 +409,7 @@ def p_def_template(t): def p_def_format(t): 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' (id, params, code) = (t[3], t[5], t[7]) - defFormat(id, params, code, t.lineno(1)) + defFormat(id, params, code, t.lexer.lineno) t[0] = GenCode() # The formal parameter list for an instruction format is a possibly @@ -454,7 +479,7 @@ def p_excess_args_param(t): # # A decode block looks like: -# decode [, ]* [default ] { ... } +# decode [, ]* [default ] { ... } # def p_decode_block(t): 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' @@ -494,7 +519,7 @@ def p_decode_stmt_list_0(t): def p_decode_stmt_list_1(t): 'decode_stmt_list : decode_stmt decode_stmt_list' if (t[1].has_decode_default and t[2].has_decode_default): - error(t.lineno(1), 'Two default cases in decode block') + error(t.lexer.lineno, 'Two default cases in decode block') t[0] = t[1] + t[2] # @@ -539,7 +564,7 @@ def p_push_format_id(t): formatStack.push(formatMap[t[1]]) t[0] = ('', '// format %s' % t[1]) except KeyError: - error(t.lineno(1), 'instruction format "%s" not defined.' % t[1]) + error(t.lexer.lineno, 'instruction format "%s" not defined.' % t[1]) # Nested decode block: if the value of the current field matches the # specified constant, do a nested decode on some other field. @@ -591,7 +616,7 @@ def p_inst_0(t): 'inst : ID LPAREN arg_list RPAREN' # Pass the ID and arg list to the current format class to deal with. currentFormat = formatStack.top() - codeObj = currentFormat.defineInst(t[1], t[3], t.lineno(1)) + codeObj = currentFormat.defineInst(t[1], t[3], t.lexer.lineno) args = ','.join(map(str, t[3])) args = re.sub('(?m)^', '//', args) args = re.sub('^//', '', args) @@ -606,8 +631,8 @@ def p_inst_1(t): try: format = formatMap[t[1]] except KeyError: - error(t.lineno(1), 'instruction format "%s" not defined.' % t[1]) - codeObj = format.defineInst(t[3], t[5], t.lineno(1)) + error(t.lexer.lineno, 'instruction format "%s" not defined.' % t[1]) + codeObj = format.defineInst(t[3], t[5], t.lexer.lineno) comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5]) codeObj.prepend_all(comment) t[0] = codeObj @@ -696,14 +721,14 @@ def p_empty(t): # *token*, not a grammar symbol (hence the need to use t.value) def p_error(t): if t: - error(t.lineno, "syntax error at '%s'" % t.value) + error(t.lexer.lineno, "syntax error at '%s'" % t.value) else: error(0, "unknown syntax error", True) # END OF GRAMMAR RULES # # Now build the parser. -yacc.yacc() +parser = yacc.yacc() ##################################################################### @@ -840,7 +865,11 @@ class Format: context = {} updateExportContext() context.update(exportContext) - context.update({ 'name': name, 'Name': string.capitalize(name) }) + if len(name): + Name = name[0].upper() + if len(name) > 1: + Name += name[1:] + context.update({ 'name': name, 'Name': Name }) try: vars = self.func(self.user_code, context, *args[0], **args[1]) except Exception, exc: @@ -1002,7 +1031,7 @@ def substBitOps(code): # Template objects are format strings that allow substitution from # the attribute spaces of other objects (e.g. InstObjParams instances). -labelRE = re.compile(r'[^%]%\(([^\)]+)\)[sd]') +labelRE = re.compile(r'(?(%s)' % (self.size, self.base_name) + else: + final_val = self.base_name + code = self.write_code % {"name": self.base_name, + "func": func, + "op_idx": self.dest_reg_idx, + "reg_idx": self.reg_spec, + "size": self.size, + "ctype": self.ctype, + "final_val": final_val} + return ''' + { + %s final_val = %s; + %s; + if (traceData) { traceData->setData(final_val); } + }''' % (self.dflt_ctype, final_val, code) + def __init__(self, full_name, ext, is_src, is_dest): self.full_name = full_name self.ext = ext @@ -1240,6 +1302,8 @@ class IntRegOperand(Operand): def makeRead(self): if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to read integer register as FP') + if self.read_code != None: + return self.buildReadCode('readIntRegOperand') if (self.size == self.dflt_size): return '%s = xc->readIntRegOperand(this, %d);\n' % \ (self.base_name, self.src_reg_idx) @@ -1256,6 +1320,8 @@ class IntRegOperand(Operand): def makeWrite(self): if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to write integer register as FP') + if self.write_code != None: + return self.buildWriteCode('setIntRegOperand') if (self.size != self.dflt_size and self.is_signed): final_val = 'sext<%d>(%s)' % (self.size, self.base_name) else: @@ -1287,27 +1353,15 @@ class FloatRegOperand(Operand): def makeRead(self): bit_select = 0 - width = 0; - if (self.ctype == 'float'): - func = 'readFloatRegOperand' - width = 32; - elif (self.ctype == 'double'): + if (self.ctype == 'float' or self.ctype == 'double'): func = 'readFloatRegOperand' - width = 64; else: func = 'readFloatRegOperandBits' - if (self.ctype == 'uint32_t'): - width = 32; - elif (self.ctype == 'uint64_t'): - width = 64; if (self.size != self.dflt_size): bit_select = 1 - if width: - base = 'xc->%s(this, %d, %d)' % \ - (func, self.src_reg_idx, width) - else: - base = 'xc->%s(this, %d)' % \ - (func, self.src_reg_idx) + base = 'xc->%s(this, %d)' % (func, self.src_reg_idx) + if self.read_code != None: + return self.buildReadCode(func) if bit_select: return '%s = bits(%s, %d, 0);\n' % \ (self.base_name, base, self.size-1) @@ -1317,34 +1371,23 @@ class FloatRegOperand(Operand): def makeWrite(self): final_val = self.base_name final_ctype = self.ctype - widthSpecifier = '' - width = 0 - if (self.ctype == 'float'): - width = 32 - func = 'setFloatRegOperand' - elif (self.ctype == 'double'): - width = 64 + if (self.ctype == 'float' or self.ctype == 'double'): func = 'setFloatRegOperand' - elif (self.ctype == 'uint32_t'): - func = 'setFloatRegOperandBits' - width = 32 - elif (self.ctype == 'uint64_t'): + elif (self.ctype == 'uint32_t' or self.ctype == 'uint64_t'): func = 'setFloatRegOperandBits' - width = 64 else: func = 'setFloatRegOperandBits' final_ctype = 'uint%d_t' % self.dflt_size if (self.size != self.dflt_size and self.is_signed): final_val = 'sext<%d>(%s)' % (self.size, self.base_name) - if width: - widthSpecifier = ', %d' % width + if self.write_code != None: + return self.buildWriteCode(func) wb = ''' { %s final_val = %s; - xc->%s(this, %d, final_val%s);\n + xc->%s(this, %d, final_val);\n if (traceData) { traceData->setData(final_val); } - }''' % (final_ctype, final_val, func, self.dest_reg_idx, - widthSpecifier) + }''' % (final_ctype, final_val, func, self.dest_reg_idx) return wb class ControlRegOperand(Operand): @@ -1368,7 +1411,9 @@ class ControlRegOperand(Operand): bit_select = 0 if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to read control register as FP') - base = 'xc->readMiscRegOperandWithEffect(this, %s)' % self.src_reg_idx + if self.read_code != None: + return self.buildReadCode('readMiscRegOperand') + base = 'xc->readMiscRegOperand(this, %s)' % self.src_reg_idx if self.size == self.dflt_size: return '%s = %s;\n' % (self.base_name, base) else: @@ -1378,7 +1423,9 @@ class ControlRegOperand(Operand): def makeWrite(self): if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to write control register as FP') - wb = 'xc->setMiscRegOperandWithEffect(this, %s, %s);\n' % \ + if self.write_code != None: + return self.buildWriteCode('setMiscRegOperand') + wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \ (self.dest_reg_idx, self.base_name) wb += 'if (traceData) { traceData->setData(%s); }' % \ self.base_name @@ -1402,9 +1449,13 @@ class MemOperand(Operand): return c def makeRead(self): + if self.read_code != None: + return self.buildReadCode() return '' def makeWrite(self): + if self.write_code != None: + return self.buildWriteCode() return '' # Return the memory access size *in bits*, suitable for @@ -1412,15 +1463,46 @@ class MemOperand(Operand): def makeAccSize(self): return self.size +class UPCOperand(Operand): + def makeConstructor(self): + return '' + + def makeRead(self): + if self.read_code != None: + return self.buildReadCode('readMicroPC') + return '%s = xc->readMicroPC();\n' % self.base_name + + def makeWrite(self): + if self.write_code != None: + return self.buildWriteCode('setMicroPC') + return 'xc->setMicroPC(%s);\n' % self.base_name + +class NUPCOperand(Operand): + def makeConstructor(self): + return '' + + def makeRead(self): + if self.read_code != None: + return self.buildReadCode('readNextMicroPC') + return '%s = xc->readNextMicroPC();\n' % self.base_name + + def makeWrite(self): + if self.write_code != None: + return self.buildWriteCode('setNextMicroPC') + return 'xc->setNextMicroPC(%s);\n' % self.base_name class NPCOperand(Operand): def makeConstructor(self): return '' def makeRead(self): + if self.read_code != None: + return self.buildReadCode('readNextPC') return '%s = xc->readNextPC();\n' % self.base_name def makeWrite(self): + if self.write_code != None: + return self.buildWriteCode('setNextPC') return 'xc->setNextPC(%s);\n' % self.base_name class NNPCOperand(Operand): @@ -1428,16 +1510,33 @@ class NNPCOperand(Operand): return '' def makeRead(self): + if self.read_code != None: + return self.buildReadCode('readNextNPC') return '%s = xc->readNextNPC();\n' % self.base_name def makeWrite(self): + if self.write_code != None: + return self.buildWriteCode('setNextNPC') return 'xc->setNextNPC(%s);\n' % self.base_name def buildOperandNameMap(userDict, lineno): global operandNameMap operandNameMap = {} for (op_name, val) in userDict.iteritems(): - (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val + (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val[:5] + if len(val) > 5: + read_code = val[5] + else: + read_code = None + if len(val) > 6: + write_code = val[6] + else: + write_code = None + if len(val) > 7: + error(lineno, + 'error: too many attributes for operand "%s"' % + base_cls_name) + (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 @@ -1462,7 +1561,8 @@ def buildOperandNameMap(userDict, lineno): # 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'): + 'dflt_size', 'dflt_ctype', 'dflt_is_signed', + 'read_code', 'write_code'): tmp_dict[attr] = eval(attr) tmp_dict['base_name'] = op_name # New class name will be e.g. "IntReg_Ra" @@ -1484,9 +1584,9 @@ def buildOperandNameMap(userDict, lineno): operands = userDict.keys() operandsREString = (r''' - (?