# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Steve Reinhardt
-# Gabe Black
-# Korey Sewell
import os
import sys
t_DOT = r'\.'
t_COLON = r':'
t_DBLCOLON = r'::'
-t_ASTERISK = r'\*'
+t_ASTERISK = r'\*'
# Identifiers and reserved words
reserved_map = { }
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
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
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
# 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):
# 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
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(header_output = exportContext["header_output"],
decoder_output = exportContext["decoder_output"],
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
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] + '}')
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:
def p_def_bitfield_struct(t):
'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI'
if (t[2] != ''):
- error(t.lineno(1), 'error: structure bitfields are always unsigned.')
+ 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_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
#
# A decode block looks like:
-# decode <field1> [, <field2>]* [default <inst>] { ... }
+# decode <field1> [, <field2>]* [default <inst>] { ... }
#
def p_decode_block(t):
'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
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]
#
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.
'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)
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
# *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)
ctype = 'uint%d_t' % size
is_signed = 0
elif desc == 'float':
- is_signed = 1 # shouldn't really matter
+ is_signed = 1 # shouldn't really matter
if size == 32:
ctype = 'float'
elif size == 64:
def isControlReg(self):
return 0
+ def isIControlReg(self):
+ return 0
+
def getFlags(self):
# note the empty slice '[:]' gives us a copy of self.flags[0]
# instead of a reference to it
error(0, 'Attempt to write control register as FP')
wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \
(self.dest_reg_idx, self.base_name)
+ wb += 'if (traceData) { traceData->setData(%s); }' % \
+ self.base_name
+ return wb
+
+class IControlRegOperand(Operand):
+ def isReg(self):
+ return 1
+
+ def isIControlReg(self):
+ return 1
+
+ def makeConstructor(self):
+ c = ''
+ if self.is_src:
+ c += '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
+ c += '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
+ (self.dest_reg_idx, self.reg_spec)
+ return c
+
+ def makeRead(self):
+ bit_select = 0
+ if (self.ctype == 'float' or self.ctype == 'double'):
+ error(0, 'Attempt to read control register as FP')
+ base = 'xc->readMiscReg(%s)' % self.reg_spec
+ if self.size == self.dflt_size:
+ return '%s = %s;\n' % (self.base_name, base)
+ else:
+ return '%s = bits(%s, %d, 0);\n' % \
+ (self.base_name, base, self.size-1)
+
+ def makeWrite(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
+ error(0, 'Attempt to write control register as FP')
+ wb = 'xc->setMiscReg(%s, %s);\n' % \
+ (self.reg_spec, self.base_name)
+ wb += 'if (traceData) { traceData->setData(%s); }' % \
+ self.base_name
+ return wb
class ControlBitfieldOperand(ControlRegOperand):
def makeRead(self):
def makeAccSize(self):
return self.size
+class 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_name
+
+class 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_name
class NPCOperand(Operand):
def makeConstructor(self):
operands = userDict.keys()
operandsREString = (r'''
- (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
+ (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
- (?![\w\.]) # neg. lookahead assertion: prevent partial matches
+ (?![\w\.]) # neg. lookahead assertion: prevent partial matches
'''
% string.join(operands, '|'))
global operandsWithExtRE
operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)
+maxInstSrcRegs = 0
+maxInstDestRegs = 0
class OperandList:
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:
%(decode_function)s
'''
+max_inst_regs_template = '''
+/*
+ * DO NOT EDIT THIS FILE!!!
+ *
+ * It was automatically generated from the ISA description in %(filename)s
+ */
+
+namespace %(namespace)s {
+
+ const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
+ const int MaxInstDestRegs = %(MaxInstDestRegs)d;
+
+} // namespace %(namespace)s
+
+'''
+
# Update the output file only if the new contents are different from
# the current contents. Minimizes the files that need to be rebuilt
update_if_needed(output_dir + '/' + cpu.filename,
file_template % vars())
+ # The variable names here are hacky, but this will creat local variables
+ # which will be referenced in vars() which have the value of the globals.
+ global maxInstSrcRegs
+ MaxInstSrcRegs = maxInstSrcRegs
+ global maxInstDestRegs
+ MaxInstDestRegs = maxInstDestRegs
+ # max_inst_regs.hh
+ update_if_needed(output_dir + '/max_inst_regs.hh', \
+ max_inst_regs_template % vars())
+
# global list of CpuModel objects (see cpu_models.py)
cpu_models = []