From 89596f0cfa223a2f2836caa56ed79b8a0996f740 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Tue, 24 Jan 2006 19:57:17 -0500 Subject: Some stuff aparently didn't get committed which was from before the new repository was created. SConscript: There is a new SConscript in the arch/alpha directory which has the alpha specific files. To add files for an arch, a similar file should be created. arch/isa_parser.py: The isa parser now supports include directives. These are done with ##include build/SConstruct: The target directory is passed on so that the architecture specific SConscript can have it. Also, sparc was added as a valid architecture type. arch/alpha/SConscript: This SConscript adds the alpha specific source arch/sparc/isa_desc/operands.h: This sets up the operand types that the sparc isa uses arch/sparc/isa_traits.cc: Implementation of sparc specific things, like a register file with windows build/build_options/default/SPARC_SE: The default options for a sparc syscall emulation build. --HG-- extra : convert_revision : 1afedae61dc8cae0d59d3bf1d41420d929be2efd --- arch/isa_parser.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 8f4c6bce7..6a8935963 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -91,6 +91,14 @@ tokens = reserved + ( # C preprocessor directives 'CPPDIRECTIVE' + +# The following are matched but never returned. commented out to +# suppress PLY warning + # newfile directive +# 'NEWFILE', + + # endfile directive +# 'ENDFILE' ) # Regular expressions for token matching @@ -149,10 +157,20 @@ def t_CODELIT(t): return t def t_CPPDIRECTIVE(t): - r'^\#.*\n' + r'^\#[^\#].*\n' t.lineno += t.value.count('\n') return t +def t_NEWFILE(t): + r'^\#\#newfile[ /t]*\"[A-Za-z0-9\\/-_.]*\"' + global fileNameStack + fileNameStack.append((t.value[11:-1], t.lineno)) + t.lineno = 0 + +def t_ENDFILE(t): + r'^\#\#endfile' + (filename, t.lineno) = fileNameStack.pop() + # # The functions t_NEWLINE, t_ignore, and t_error are # special for the lex module. @@ -852,7 +870,12 @@ def fixPythonIndentation(s): # Error handler. Just call exit. Output formatted to work under # Emacs compile-mode. def error(lineno, string): - sys.exit("%s:%d: %s" % (input_filename, lineno, string)) + global fileNameStack + spaces = "" + for (filename, line) in fileNameStack[0:-1]: + print spaces + "In file included from " + filename + spaces += " " + sys.exit(spaces + "%s:%d: %s" % (fileNameStack[-1][0], lineno, string)) # Like error(), but include a Python stack backtrace (for processing # Python exceptions). @@ -1601,6 +1624,25 @@ def update_if_needed(file, contents): f.write(contents) f.close() +# This regular expression matches include directives +regExp = re.compile('(?P^[ \t]*##include[ \t]*\"[ \t]*(?P[A-Za-z0-9\\/-_.]*)[ \t]*\"[ \t]*\n)', re.MULTILINE) + +def preprocess_isa_desc(isa_desc): + # Find any includes and include them + + # Look for an include + m = re.search(regExp, isa_desc) + while m: + filename = m.group('filename') + print 'Including file "%s"' % filename + includeFile = open(filename) + includecontents = includeFile.read() + isa_desc = isa_desc[:m.start('include')] + '##newfile "' + filename + '"\n' + includecontents + '##endfile\n' + isa_desc[m.end('include'):] + # Look for the next include + m = re.search(regExp, isa_desc) + return isa_desc + + # # Read in and parse the ISA description. # @@ -1608,12 +1650,17 @@ def parse_isa_desc(isa_desc_file, output_dir, include_path): # set a global var for the input filename... used in error messages global input_filename input_filename = isa_desc_file + global fileNameStack + fileNameStack = [(input_filename, 1)] # Suck the ISA description file in. input = open(isa_desc_file) isa_desc = input.read() input.close() + # Perform Preprocessing + isa_desc = preprocess_isa_desc(isa_desc) + # Parse it. (isa_name, namespace, global_code, namespace_code) = yacc.parse(isa_desc) -- cgit v1.2.3 From 879aaa55691285403d47e5891b79399974f6f221 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 9 Feb 2006 14:51:37 -0500 Subject: Change how isa_parser.py generates C++ names for isa_desc operands. arch/isa_parser.py: Get rid of "munged name" for operands in C++ code. That is, "Ra.uq" will now be known in the C++ as "Ra" rather than "Ra_uq". It wasn't legal to use different type extensions for the same operand at the same time anyway, and now it will be easier to refer to explicit operands in template code if necessary. --HG-- extra : convert_revision : 9ff41e0201aeefe761743084ecdb34f4b9c84fdb --- arch/isa_parser.py | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 8f4c6bce7..bf8b31090 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -1045,7 +1045,7 @@ class OperandTraits: (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] # Note that initializations in the declarations are solely # to avoid 'uninitialized variable' errors from the compiler. - return type + ' ' + op_desc.munged_name + ' = 0;\n'; + return type + ' ' + op_desc.base_name + ' = 0;\n'; class IntRegOperandTraits(OperandTraits): def isReg(self): @@ -1070,19 +1070,19 @@ class IntRegOperandTraits(OperandTraits): error(0, 'Attempt to read integer register as FP') if (size == self.dflt_size): return '%s = xc->readIntReg(this, %d);\n' % \ - (op_desc.munged_name, op_desc.src_reg_idx) + (op_desc.base_name, op_desc.src_reg_idx) else: return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \ - (op_desc.munged_name, op_desc.src_reg_idx, size-1) + (op_desc.base_name, op_desc.src_reg_idx, size-1) def makeWrite(self, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] if (type == 'float' or type == 'double'): error(0, 'Attempt to write integer register as FP') if (size != self.dflt_size and is_signed): - final_val = 'sext<%d>(%s)' % (size, op_desc.munged_name) + final_val = 'sext<%d>(%s)' % (size, op_desc.base_name) else: - final_val = op_desc.munged_name + final_val = op_desc.base_name wb = ''' { %s final_val = %s; @@ -1123,13 +1123,13 @@ class FloatRegOperandTraits(OperandTraits): (func, op_desc.src_reg_idx) if bit_select: return '%s = bits(%s, %d, 0);\n' % \ - (op_desc.munged_name, base, size-1) + (op_desc.base_name, base, size-1) else: - return '%s = %s;\n' % (op_desc.munged_name, base) + return '%s = %s;\n' % (op_desc.base_name, base) def makeWrite(self, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] - final_val = op_desc.munged_name + final_val = op_desc.base_name if (type == 'float'): func = 'setFloatRegSingle' elif (type == 'double'): @@ -1138,7 +1138,7 @@ class FloatRegOperandTraits(OperandTraits): func = 'setFloatRegInt' type = 'uint%d_t' % self.dflt_size if (size != self.dflt_size and is_signed): - final_val = 'sext<%d>(%s)' % (size, op_desc.munged_name) + final_val = 'sext<%d>(%s)' % (size, op_desc.base_name) wb = ''' { %s final_val = %s; @@ -1171,18 +1171,18 @@ class ControlRegOperandTraits(OperandTraits): error(0, 'Attempt to read control register as FP') base = 'xc->read%s()' % self.reg_spec if size == self.dflt_size: - return '%s = %s;\n' % (op_desc.munged_name, base) + return '%s = %s;\n' % (op_desc.base_name, base) else: return '%s = bits(%s, %d, 0);\n' % \ - (op_desc.munged_name, base, size-1) + (op_desc.base_name, base, size-1) def makeWrite(self, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] if (type == 'float' or type == 'double'): error(0, 'Attempt to write control register as FP') - wb = 'xc->set%s(%s);\n' % (self.reg_spec, op_desc.munged_name) + wb = 'xc->set%s(%s);\n' % (self.reg_spec, op_desc.base_name) wb += 'if (traceData) { traceData->setData(%s); }' % \ - op_desc.munged_name + op_desc.base_name return wb class MemOperandTraits(OperandTraits): @@ -1197,7 +1197,7 @@ class MemOperandTraits(OperandTraits): # Note that initializations in the declarations are solely # to avoid 'uninitialized variable' errors from the compiler. # Declare memory data variable. - c = '%s %s = 0;\n' % (type, op_desc.munged_name) + c = '%s %s = 0;\n' % (type, op_desc.base_name) # Declare var to hold memory access flags. c += 'unsigned %s_flags = memAccessFlags;\n' % op_desc.base_name # If this operand is a dest (i.e., it's a store operation), @@ -1211,16 +1211,16 @@ class MemOperandTraits(OperandTraits): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] eff_type = 'uint%d_t' % size return 'fault = xc->read(EA, (%s&)%s, %s_flags);\n' \ - % (eff_type, op_desc.munged_name, op_desc.base_name) + % (eff_type, op_desc.base_name, op_desc.base_name) def makeWrite(self, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] eff_type = 'uint%d_t' % size wb = 'fault = xc->write((%s&)%s, EA, %s_flags, &%s_write_result);\n' \ - % (eff_type, op_desc.munged_name, op_desc.base_name, + % (eff_type, op_desc.base_name, op_desc.base_name, op_desc.base_name) wb += 'if (traceData) { traceData->setData(%s); }' % \ - op_desc.munged_name + op_desc.base_name return wb class NPCOperandTraits(OperandTraits): @@ -1228,10 +1228,10 @@ class NPCOperandTraits(OperandTraits): return '' def makeRead(self, op_desc): - return '%s = xc->readPC() + 4;\n' % op_desc.munged_name + return '%s = xc->readPC() + 4;\n' % op_desc.base_name def makeWrite(self, op_desc): - return 'xc->setNextPC(%s);\n' % op_desc.munged_name + return 'xc->setNextPC(%s);\n' % op_desc.base_name exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits', @@ -1294,14 +1294,10 @@ class OperandDescriptor: self.traits = operandTraitsMap[base_name] # The 'effective extension' (eff_ext) is either the actual # extension, if one was explicitly provided, or the default. - # The 'munged name' replaces the '.' between the base and - # extension (if any) with a '_' to make a legal C++ variable name. if ext: self.eff_ext = ext - self.munged_name = base_name + '_' + ext else: self.eff_ext = self.traits.dflt_ext - self.munged_name = base_name # Finalize additional fields (primarily code fields). This step # is done separately since some of these fields may depend on the @@ -1444,9 +1440,10 @@ def findOperands(code): return operands # Munge operand names in code string to make legal C++ variable names. -# (Will match munged_name attribute of OperandDescriptor object.) +# This means getting rid of the type extension if any. +# (Will match base_name attribute of OperandDescriptor object.) def substMungedOpNames(code): - return operandsWithExtRE.sub(r'\1_\2', code) + return operandsWithExtRE.sub(r'\1', code) def joinLists(t): return map(string.join, t) -- cgit v1.2.3 From fb90b1dd13fb6c0090bfe2731ca9ccee56479761 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 9 Feb 2006 22:27:41 -0500 Subject: Minor cleanup of include-handling code in isa_parser.py. arch/isa_parser.py: Clean up ##include code a bit. arch/sparc/isa/formats.isa: arch/sparc/isa/main.isa: Fix include paths. --HG-- extra : convert_revision : 0689963c2948e5f1088ecbf2cf6018d29bdaceff --- arch/isa_parser.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index fc6880877..b12329ebb 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -162,7 +162,7 @@ def t_CPPDIRECTIVE(t): return t def t_NEWFILE(t): - r'^\#\#newfile[ /t]*\"[A-Za-z0-9\\/-_.]*\"' + r'^\#\#newfile\s+"[\w/.-]*"' global fileNameStack fileNameStack.append((t.value[11:-1], t.lineno)) t.lineno = 0 @@ -841,7 +841,7 @@ defaultStack = Stack( None ) # Used to make nested code blocks look pretty. # def indent(s): - return re.sub(r'(?m)^(?!\#)', ' ', s) + return re.sub(r'(?m)^(?!#)', ' ', s) # # Munge a somewhat arbitrarily formatted piece of Python code @@ -870,7 +870,6 @@ def fixPythonIndentation(s): # Error handler. Just call exit. Output formatted to work under # Emacs compile-mode. def error(lineno, string): - global fileNameStack spaces = "" for (filename, line) in fileNameStack[0:-1]: print spaces + "In file included from " + filename @@ -1622,24 +1621,29 @@ def update_if_needed(file, contents): f.close() # This regular expression matches include directives -regExp = re.compile('(?P^[ \t]*##include[ \t]*\"[ \t]*(?P[A-Za-z0-9\\/-_.]*)[ \t]*\"[ \t]*\n)', re.MULTILINE) +includeRE = re.compile(r'^\s*##include\s+"(?P[\w/.-]*)".*$', + re.MULTILINE) def preprocess_isa_desc(isa_desc): # Find any includes and include them - - # Look for an include - m = re.search(regExp, isa_desc) - while m: + pos = 0 + while 1: + m = includeRE.search(isa_desc, pos) + if not m: + break filename = m.group('filename') print 'Including file "%s"' % filename - includeFile = open(filename) - includecontents = includeFile.read() - isa_desc = isa_desc[:m.start('include')] + '##newfile "' + filename + '"\n' + includecontents + '##endfile\n' + isa_desc[m.end('include'):] - # Look for the next include - m = re.search(regExp, isa_desc) + try: + isa_desc = isa_desc[:m.start()] + \ + '##newfile "' + filename + '"\n' + \ + open(filename).read() + \ + '##endfile\n' + \ + isa_desc[m.end():] + except IOError: + error(0, 'Error including file "%s"' % (filename)) + pos = m.start() return isa_desc - # # Read in and parse the ISA description. # -- cgit v1.2.3 From 3923eec0ef46dd1ce7ed2ef0cbc68419a0161796 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Fri, 10 Feb 2006 09:12:55 -0500 Subject: Change how memory operands are handled in ISA descriptions. Should enable implementation of split-phase timing loads with new memory model. May create slight timing differences under FullCPU, as I believe we were not handling software prefetches correctly before when the split MemAcc/Exec model was used. I haven't looked into this in any detail though. arch/alpha/isa/decoder.isa: HwLoadStore format split into separate HwLoad and HwStore formats. Copy instructions now fall under MiscPrefetch format. Mem_write_result is now just write_result in store conditionals. arch/alpha/isa/mem.isa: Split MemAccExecute and LoadStoreExecute templates into separate templates for loads and stores; now that memory operands are handled differently from registers, it's impossible to have a single template serve both. Also unified the handling of "regular" prefetches (loads to r31) and "misc" prefetches (e.g., wh64) under the new scheme. It looks like SW prefetches were not handled correctly in FullCPU up til now, since we generated an execute() method for the outer instruction but didn't generate a proper method for MemAcc::execute() (instead getting a default no-op method for that). arch/alpha/isa/pal.isa: Split HwLoadStore into separate HwLoad and HwStore formats to select proper template (see change to mem.isa in this changeset). arch/isa_parser.py: Stop trying to treat memory operands like register operands, since we never used them in a uniform way anyway, and it made it impossible to do split-phase loads as needed for the new CPU model. Now there's no more 'op_mem_rd', 'op_nonmem_rd', etc.: 'op_rd' just does register operands, and the template code is responsible for formulating the call to the memory system. Right now the only thing exported by InstObjParams is a new attribute 'mem_acc_size' which gives the memory access size in bits, though more attributes can be added if needed. Also moved code in findOperands() method to OperandDescriptorList.__init__(), which is where it belongs. --HG-- extra : convert_revision : 6d53d07e0c5e828455834ded4395fa40f9146a34 --- arch/isa_parser.py | 183 +++++++++++++++++++++++++---------------------------- 1 file changed, 87 insertions(+), 96 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index b12329ebb..fffcc33e5 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -868,16 +868,21 @@ def fixPythonIndentation(s): return s # Error handler. Just call exit. Output formatted to work under -# Emacs compile-mode. +# Emacs compile-mode. This function should be called when errors due +# to user input are detected (as opposed to parser bugs). def error(lineno, string): spaces = "" for (filename, line) in fileNameStack[0:-1]: print spaces + "In file included from " + filename spaces += " " + # Uncomment the following line to get a Python stack backtrace for + # these errors too. Can be handy when trying to debug the parser. + # traceback.print_exc() sys.exit(spaces + "%s:%d: %s" % (fileNameStack[-1][0], lineno, string)) # Like error(), but include a Python stack backtrace (for processing -# Python exceptions). +# Python exceptions). This function should be called for errors that +# appear to be bugs in the parser itself. def error_bt(lineno, string): traceback.print_exc() print >> sys.stderr, "%s:%d: %s" % (input_filename, lineno, string) @@ -1220,30 +1225,19 @@ class MemOperandTraits(OperandTraits): # to avoid 'uninitialized variable' errors from the compiler. # Declare memory data variable. c = '%s %s = 0;\n' % (type, op_desc.base_name) - # Declare var to hold memory access flags. - c += 'unsigned %s_flags = memAccessFlags;\n' % op_desc.base_name - # If this operand is a dest (i.e., it's a store operation), - # then we need to declare a variable for the write result code - # as well. - if op_desc.is_dest: - c += 'uint64_t %s_write_result = 0;\n' % op_desc.base_name return c def makeRead(self, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] - eff_type = 'uint%d_t' % size - return 'fault = xc->read(EA, (%s&)%s, %s_flags);\n' \ - % (eff_type, op_desc.base_name, op_desc.base_name) + return '' def makeWrite(self, op_desc): + 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, op_desc): (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] - eff_type = 'uint%d_t' % size - wb = 'fault = xc->write((%s&)%s, EA, %s_flags, &%s_write_result);\n' \ - % (eff_type, op_desc.base_name, op_desc.base_name, - op_desc.base_name) - wb += 'if (traceData) { traceData->setData(%s); }' % \ - op_desc.base_name - return wb + return size class NPCOperandTraits(OperandTraits): def makeConstructor(self, op_desc): @@ -1321,6 +1315,11 @@ class OperandDescriptor: else: self.eff_ext = self.traits.dflt_ext + # note that mem_acc_size is undefined for non-mem operands... + # template must be careful not to use it if it doesn't apply. + if self.traits.isMem(): + self.mem_acc_size = self.traits.makeAccSize(self) + # Finalize additional fields (primarily code fields). This step # is done separately since some of these fields may depend on the # register index enumeration that hasn't been performed yet at the @@ -1340,10 +1339,73 @@ class OperandDescriptor: else: self.op_wb = '' + class OperandDescriptorList: - def __init__(self): + + # Find all the operands in the given code block. Returns an operand + # descriptor list (instance of class OperandDescriptorList). + 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 = OperandDescriptor(op_full, op_base, 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.traits.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.traits.isFloatReg(): + self.numFPDestRegs += 1 + elif op_desc.traits.isIntReg(): + self.numIntDestRegs += 1 + elif op_desc.traits.isMem(): + if self.memOperand: + error(0, "Code block has more than one memory operand.") + self.memOperand = op_desc + # 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) @@ -1398,69 +1460,6 @@ commentRE = re.compile(r'//.*\n') # (used in findOperands()) assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) -# -# Find all the operands in the given code block. Returns an operand -# descriptor list (instance of class OperandDescriptorList). -# -def findOperands(code): - operands = OperandDescriptorList() - # delete comments so we don't accidentally 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 = operands.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 = OperandDescriptor(op_full, op_base, op_ext, - is_src, is_dest) - operands.append(op_desc) - # start next search after end of current match - next_pos = match.end() - operands.sort() - # enumerate source & dest register operands... used in building - # constructor later - srcRegs = 0 - destRegs = 0 - operands.numFPDestRegs = 0 - operands.numIntDestRegs = 0 - for op_desc in operands: - if op_desc.traits.isReg(): - if op_desc.is_src: - op_desc.src_reg_idx = srcRegs - srcRegs += 1 - if op_desc.is_dest: - op_desc.dest_reg_idx = destRegs - destRegs += 1 - if op_desc.traits.isFloatReg(): - operands.numFPDestRegs += 1 - elif op_desc.traits.isIntReg(): - operands.numIntDestRegs += 1 - operands.numSrcRegs = srcRegs - operands.numDestRegs = destRegs - # now make a final pass to finalize op_desc fields that may depend - # on the register enumeration - for op_desc in operands: - op_desc.finalize() - return operands - # 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 OperandDescriptor object.) @@ -1489,7 +1488,7 @@ def makeFlagConstructor(flag_list): class CodeBlock: def __init__(self, code): self.orig_code = code - self.operands = findOperands(code) + self.operands = OperandDescriptorList(code) self.code = substMungedOpNames(substBitOps(code)) self.constructor = self.operands.concatAttrStrings('constructor') self.constructor += \ @@ -1503,22 +1502,14 @@ class CodeBlock: self.op_decl = self.operands.concatAttrStrings('op_decl') - is_mem = lambda op: op.traits.isMem() - not_mem = lambda op: not op.traits.isMem() - self.op_rd = self.operands.concatAttrStrings('op_rd') self.op_wb = self.operands.concatAttrStrings('op_wb') - self.op_mem_rd = \ - self.operands.concatSomeAttrStrings(is_mem, 'op_rd') - self.op_mem_wb = \ - self.operands.concatSomeAttrStrings(is_mem, 'op_wb') - self.op_nonmem_rd = \ - self.operands.concatSomeAttrStrings(not_mem, 'op_rd') - self.op_nonmem_wb = \ - self.operands.concatSomeAttrStrings(not_mem, 'op_wb') self.flags = self.operands.concatAttrLists('flags') + if self.operands.memOperand: + self.mem_acc_size = self.operands.memOperand.mem_acc_size + # Make a basic guess on the operand class (function unit type). # These are good enough for most cases, and will be overridden # later otherwise. -- cgit v1.2.3 From 3cc6c59582a0de71a7a7c8696f503388a7447acf Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 11 Feb 2006 15:11:00 -0500 Subject: Add keyword parameters and list-valued arguments to instruction format functions in ISA description language. Take advantage of these features to clean up memory instruction definitions in Alpha. arch/alpha/isa/decoder.isa: arch/alpha/isa/mem.isa: arch/alpha/isa/pal.isa: Take advantage of new keyword parameters to disambiguate instruction vs. memory-request flags, and to provide a default EA calculation for memory ops (since 99% of them are the same). arch/isa_parser.py: Add two new features to instruction format functions: - Keyword parameters, a la Python. - List-valued arguments. Also export makeList() function to Python code blocks, as this is handy for dealing with flags. --HG-- extra : convert_revision : 99bbbaa2e765230aa96b6a06ed193793325f9fb0 --- arch/isa_parser.py | 176 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 133 insertions(+), 43 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index fffcc33e5..e7f7a897c 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -82,10 +82,9 @@ tokens = reserved + ( # ( ) [ ] { } < > , ; : :: * 'LPAREN', 'RPAREN', -# not used any more... commented out to suppress PLY warning -# 'LBRACKET', 'RBRACKET', + 'LBRACKET', 'RBRACKET', 'LBRACE', 'RBRACE', - 'LESS', 'GREATER', + 'LESS', 'GREATER', 'EQUALS', 'COMMA', 'SEMI', 'COLON', 'DBLCOLON', 'ASTERISK', @@ -104,13 +103,13 @@ tokens = reserved + ( # Regular expressions for token matching t_LPAREN = r'\(' t_RPAREN = r'\)' -# not used any more... commented out to suppress PLY warning -# t_LBRACKET = r'\[' -# t_RBRACKET = r'\]' +t_LBRACKET = r'\[' +t_RBRACKET = r'\]' t_LBRACE = r'\{' t_RBRACE = r'\}' t_LESS = r'\<' t_GREATER = r'\>' +t_EQUALS = r'=' t_COMMA = r',' t_SEMI = r';' t_COLON = r':' @@ -387,32 +386,66 @@ def p_def_format(t): t[0] = GenCode() # The formal parameter list for an instruction format is a possibly -# empty list of comma-separated parameters. +# empty list of comma-separated parameters. Positional (standard, +# non-keyword) parameters must come first, followed by keyword +# parameters, followed by a '*foo' parameter that gets excess +# positional arguments (as in Python). Each of these three parameter +# categories is optional. +# +# Note that we do not support the '**foo' parameter for collecting +# otherwise undefined keyword args. Otherwise the parameter list is +# (I believe) identical to what is supported in Python. +# +# The param list generates a tuple, where the first element is a list of +# the positional params and the second element is a dict containing the +# keyword params. def p_param_list_0(t): - 'param_list : empty' - t[0] = [ ] + 'param_list : positional_param_list COMMA nonpositional_param_list' + t[0] = t[1] + t[3] def p_param_list_1(t): - 'param_list : param' + '''param_list : positional_param_list + | nonpositional_param_list''' + t[0] = t[1] + +def p_positional_param_list_0(t): + 'positional_param_list : empty' + t[0] = [] + +def p_positional_param_list_1(t): + 'positional_param_list : ID' t[0] = [t[1]] -def p_param_list_2(t): - 'param_list : param_list COMMA param' - t[0] = t[1] - t[0].append(t[3]) +def p_positional_param_list_2(t): + 'positional_param_list : positional_param_list COMMA ID' + t[0] = t[1] + [t[3]] + +def p_nonpositional_param_list_0(t): + 'nonpositional_param_list : keyword_param_list COMMA excess_args_param' + t[0] = t[1] + t[3] -# Each formal parameter is either an identifier or an identifier -# preceded by an asterisk. As in Python, the latter (if present) gets -# a tuple containing all the excess positional arguments, allowing -# varargs functions. -def p_param_0(t): - 'param : ID' +def p_nonpositional_param_list_1(t): + '''nonpositional_param_list : keyword_param_list + | excess_args_param''' t[0] = t[1] -def p_param_1(t): - 'param : ASTERISK ID' - # just concatenate them: '*ID' - t[0] = t[1] + t[2] +def p_keyword_param_list_0(t): + 'keyword_param_list : keyword_param' + t[0] = [t[1]] + +def p_keyword_param_list_1(t): + 'keyword_param_list : keyword_param_list COMMA keyword_param' + t[0] = t[1] + [t[3]] + +def p_keyword_param(t): + 'keyword_param : ID EQUALS expr' + t[0] = t[1] + ' = ' + t[3].__repr__() + +def p_excess_args_param(t): + 'excess_args_param : ASTERISK ID' + # Just concatenate them: '*ID'. Wrap in list to be consistent + # with positional_param_list and keyword_param_list. + t[0] = [t[1] + t[2]] # End of format definition-related rules. ############## @@ -577,26 +610,79 @@ def p_inst_1(t): codeObj.prepend_all(comment) t[0] = codeObj +# The arg list generates a tuple, where the first element is a list of +# the positional args and the second element is a dict containing the +# keyword args. def p_arg_list_0(t): - 'arg_list : empty' - t[0] = [ ] + 'arg_list : positional_arg_list COMMA keyword_arg_list' + t[0] = ( t[1], t[3] ) def p_arg_list_1(t): - 'arg_list : arg' - t[0] = [t[1]] + 'arg_list : positional_arg_list' + t[0] = ( t[1], {} ) def p_arg_list_2(t): - 'arg_list : arg_list COMMA arg' + 'arg_list : keyword_arg_list' + t[0] = ( [], t[1] ) + +def p_positional_arg_list_0(t): + 'positional_arg_list : empty' + t[0] = [] + +def p_positional_arg_list_1(t): + 'positional_arg_list : expr' + t[0] = [t[1]] + +def p_positional_arg_list_2(t): + 'positional_arg_list : positional_arg_list COMMA expr' + t[0] = t[1] + [t[3]] + +def p_keyword_arg_list_0(t): + 'keyword_arg_list : keyword_arg' t[0] = t[1] - t[0].append(t[3]) -def p_arg(t): - '''arg : ID - | INTLIT - | STRLIT - | CODELIT''' +def p_keyword_arg_list_1(t): + 'keyword_arg_list : keyword_arg_list COMMA keyword_arg' + t[0] = t[1] + t[0].update(t[3]) + +def p_keyword_arg(t): + 'keyword_arg : ID EQUALS expr' + t[0] = { t[1] : t[3] } + +# +# Basic expressions. These constitute the argument values of +# "function calls" (i.e. instruction definitions in the decode block) +# and default values for formal parameters of format functions. +# +# Right now, these are either strings, integers, or (recursively) +# lists of exprs (using Python square-bracket list syntax). Note that +# bare identifiers are trated as string constants here (since there +# isn't really a variable namespace to refer to). +# +def p_expr_0(t): + '''expr : ID + | INTLIT + | STRLIT + | CODELIT''' t[0] = t[1] +def p_expr_1(t): + '''expr : LBRACKET list_expr RBRACKET''' + t[0] = t[2] + +def p_list_expr_0(t): + 'list_expr : expr' + t[0] = [t[1]] + +def p_list_expr_1(t): + 'list_expr : list_expr COMMA expr' + t[0] = t[1] + [t[3]] + +def p_list_expr_2(t): + 'list_expr : empty' + t[0] = [] + # # Empty production... use in other rules for readability. # @@ -779,7 +865,7 @@ class Format: context.update(exportContext) context.update({ 'name': name, 'Name': string.capitalize(name) }) try: - vars = self.func(self.user_code, context, *args) + vars = self.func(self.user_code, context, *args[0], **args[1]) except Exception, exc: error(lineno, 'error defining "%s": %s.' % (name, exc)) for k in vars.keys(): @@ -974,14 +1060,18 @@ class Template: # ##################################################################### -# Force the argument to be a list -def makeList(list_or_item): - if not list_or_item: +# Force the argument to be a list. Useful for flags, where a caller +# can specify a singleton flag or a list of flags. Also usful for +# converting tuples to lists so they can be modified. +def makeList(arg): + if isinstance(arg, list): + return arg + elif isinstance(arg, tuple): + return list(arg) + elif not arg: return [] - elif type(list_or_item) == ListType: - return list_or_item else: - return [ list_or_item ] + return [ arg ] # generate operandSizeMap based on provided operandTypeMap: # basically generate equiv. C++ type and make is_signed flag @@ -1253,7 +1343,7 @@ class NPCOperandTraits(OperandTraits): exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits', 'ControlRegOperandTraits', 'MemOperandTraits', 'NPCOperandTraits', 'InstObjParams', 'CodeBlock', - 're', 'string') + 'makeList', 're', 'string') exportContext = {} -- cgit v1.2.3 From 8f2e096275386cbd6744c4bd65190dba1c5b89b4 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sat, 11 Feb 2006 21:26:49 -0500 Subject: Minor cleanup of operand type and traits code in isa_parser.py. arch/isa_parser.py: Minor cleanup of operand type and traits code: - build operand size map right away when types are defined instead of waiting to do it lazily - check that operand types have been defined before operands - don't use 'type' as a variable name - use isinstance() instead of checking for types directly --HG-- extra : convert_revision : 099c1ee8d490f9c38316749bf87209388c55c971 --- arch/isa_parser.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index e7f7a897c..0e33b4ff7 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -326,12 +326,16 @@ def p_def_operand_types(t): except Exception, exc: error(t.lineno(1), 'error: %s in def operand_types block "%s".' % (exc, t[3])) + buildOperandSizeMap() t[0] = GenCode() # contributes nothing to the output C++ file # Define the mapping from operand names to operand classes and other # traits. Stored in operandTraitsMap. def p_def_operands(t): 'def_operands : DEF OPERANDS CODELIT SEMI' + if not globals().has_key('operandSizeMap'): + error(t.lineno(1), + 'error: operand types must be defined before operands') s = 'global operandTraitsMap; operandTraitsMap = {' + t[3] + '}' try: exec s @@ -1081,20 +1085,20 @@ def buildOperandSizeMap(): for ext in operandTypeMap.keys(): (desc, size) = operandTypeMap[ext] if desc == 'signed int': - type = 'int%d_t' % size + ctype = 'int%d_t' % size is_signed = 1 elif desc == 'unsigned int': - type = 'uint%d_t' % size + ctype = 'uint%d_t' % size is_signed = 0 elif desc == 'float': is_signed = 1 # shouldn't really matter if size == 32: - type = 'float' + ctype = 'float' elif size == 64: - type = 'double' - if type == '': + ctype = 'double' + if ctype == '': error(0, 'Unrecognized type description "%s" in operandTypeMap') - operandSizeMap[ext] = (size, type, is_signed) + operandSizeMap[ext] = (size, ctype, is_signed) # # Base class for operand traits. An instance of this class (or actually @@ -1103,10 +1107,6 @@ def buildOperandSizeMap(): # class OperandTraits: def __init__(self, dflt_ext, reg_spec, flags, sort_pri): - # Force construction of operandSizeMap from operandTypeMap - # if it hasn't happened yet - if not globals().has_key('operandSizeMap'): - buildOperandSizeMap() self.dflt_ext = dflt_ext (self.dflt_size, self.dflt_type, self.dflt_is_signed) = \ operandSizeMap[dflt_ext] @@ -1119,13 +1119,13 @@ class OperandTraits: if not flags: # no flags specified (e.g., 'None') self.flags = ( [], [], [] ) - elif type(flags) == StringType: + elif isinstance(flags, str): # a single flag: assumed to be unconditional self.flags = ( [ flags ], [], [] ) - elif type(flags) == ListType: + elif isinstance(flags, list): # a list of flags: also assumed to be unconditional self.flags = ( flags, [], [] ) - elif type(flags) == TupleType: + 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 -- cgit v1.2.3 From 79613686f0f6a8725e88e935a7c9ff4ede4cfc2b Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sun, 12 Feb 2006 00:31:19 -0500 Subject: Polishing of isa_parser.py internal operand handling, resulting in minor change to syntax of 'def operands' in ISA descriptions. arch/alpha/isa/main.isa: arch/mips/isa/operands.isa: arch/sparc/isa/operands.isa: Change 'def operands' statement to work with new isa_parser changes. arch/isa_parser.py: Merge OperandTraits and OperandDescriptor objects into a unified hierarchy of Operand objects. Required a change in the syntax of the 'def operands' statement in the ISA description. --HG-- extra : convert_revision : cb43f1607311497ead88ba13953d410ab5bc6a37 --- arch/isa_parser.py | 413 ++++++++++++++++++++++++++--------------------------- 1 file changed, 205 insertions(+), 208 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 0e33b4ff7..030bb5a7c 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -320,29 +320,27 @@ def p_global_let(t): # widths (stored in operandTypeMap). def p_def_operand_types(t): 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' - s = 'global operandTypeMap; operandTypeMap = {' + t[3] + '}' try: - exec s + userDict = eval('{' + t[3] + '}') except Exception, exc: error(t.lineno(1), 'error: %s in def operand_types block "%s".' % (exc, t[3])) - buildOperandSizeMap() + buildOperandTypeMap(userDict, t.lineno(1)) t[0] = GenCode() # contributes nothing to the output C++ file # Define the mapping from operand names to operand classes and other -# traits. Stored in operandTraitsMap. +# traits. Stored in operandNameMap. def p_def_operands(t): 'def_operands : DEF OPERANDS CODELIT SEMI' - if not globals().has_key('operandSizeMap'): + if not globals().has_key('operandTypeMap'): error(t.lineno(1), 'error: operand types must be defined before operands') - s = 'global operandTraitsMap; operandTraitsMap = {' + t[3] + '}' try: - exec s + userDict = eval('{' + t[3] + '}') except Exception, exc: error(t.lineno(1), 'error: %s in def operands block "%s".' % (exc, t[3])) - defineDerivedOperandVars() + buildOperandNameMap(userDict, t.lineno(1)) t[0] = GenCode() # contributes nothing to the output C++ file # A bitfield definition looks like: @@ -847,6 +845,19 @@ class GenCode: # a defineInst() method that generates the code for an instruction # definition. +exportContextSymbols = ('InstObjParams', 'CodeBlock', + 'makeList', 're', 'string') + +exportContext = {} + +def updateExportContext(): + exportContext.update(exportDict(*exportContextSymbols)) + exportContext.update(templateMap) + +def exportDict(*symNames): + return dict([(s, eval(s)) for s in symNames]) + + class Format: def __init__(self, id, params, code): # constructor: just save away arguments @@ -1077,13 +1088,12 @@ def makeList(arg): else: return [ arg ] -# generate operandSizeMap based on provided operandTypeMap: -# basically generate equiv. C++ type and make is_signed flag -def buildOperandSizeMap(): - global operandSizeMap - operandSizeMap = {} - for ext in operandTypeMap.keys(): - (desc, size) = operandTypeMap[ext] +# Generate operandTypeMap from the user's 'def operand_types' +# statement. +def buildOperandTypeMap(userDict, lineno): + global operandTypeMap + operandTypeMap = {} + for (ext, (desc, size)) in userDict.iteritems(): if desc == 'signed int': ctype = 'int%d_t' % size is_signed = 1 @@ -1097,41 +1107,56 @@ def buildOperandSizeMap(): elif size == 64: ctype = 'double' if ctype == '': - error(0, 'Unrecognized type description "%s" in operandTypeMap') - operandSizeMap[ext] = (size, ctype, is_signed) + error(0, 'Unrecognized type description "%s" in userDict') + operandTypeMap[ext] = (size, ctype, is_signed) # -# Base class for operand traits. An instance of this class (or actually -# a class derived from this one) encapsulates the traits of a particular -# operand type (e.g., "32-bit integer register"). # -class OperandTraits: - def __init__(self, dflt_ext, reg_spec, flags, sort_pri): - self.dflt_ext = dflt_ext - (self.dflt_size, self.dflt_type, self.dflt_is_signed) = \ - operandSizeMap[dflt_ext] - self.reg_spec = reg_spec - # 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') - self.flags = ( [], [], [] ) - elif isinstance(flags, str): - # a single flag: assumed to be unconditional - self.flags = ( [ flags ], [], [] ) - elif isinstance(flags, list): - # a list of flags: also assumed to be unconditional - self.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 - self.flags = (makeList(uncond_flags), - makeList(src_flags), makeList(dest_flags)) - self.sort_pri = sort_pri +# +# Base class for operand descriptors. An instance of this class (or +# actually a class derived from this one) represents a specific +# operand for a code block (e.g, "Rc.sq" as a dest). Intermediate +# derived classes encapsulates the traits of a particular operand type +# (e.g., "32-bit integer register"). +# +class Operand(object): + def __init__(self, full_name, ext, is_src, is_dest): + self.full_name = full_name + self.ext = ext + self.is_src = is_src + self.is_dest = is_dest + # The 'effective extension' (eff_ext) is either the actual + # extension, if one was explicitly provided, or the default. + if ext: + self.eff_ext = ext + else: + self.eff_ext = self.dflt_ext + + (self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext] + + # note that mem_acc_size is undefined for non-mem operands... + # template must be careful not to use it if it doesn't apply. + if self.isMem(): + self.mem_acc_size = self.makeAccSize() + + # Finalize additional fields (primarily code fields). This step + # is done separately since some of these fields may depend on the + # register index enumeration that hasn't been performed yet at the + # time of __init__(). + def finalize(self): + self.flags = self.getFlags() + self.constructor = self.makeConstructor() + self.op_decl = self.makeDecl() + + if self.is_src: + self.op_rd = self.makeRead() + else: + self.op_rd = '' + + if self.is_dest: + self.op_wb = self.makeWrite() + else: + self.op_wb = '' def isMem(self): return 0 @@ -1148,223 +1173,239 @@ class OperandTraits: def isControlReg(self): return 0 - def getFlags(self, op_desc): + def getFlags(self): # note the empty slice '[:]' gives us a copy of self.flags[0] # instead of a reference to it my_flags = self.flags[0][:] - if op_desc.is_src: + if self.is_src: my_flags += self.flags[1] - if op_desc.is_dest: + if self.is_dest: my_flags += self.flags[2] return my_flags - def makeDecl(self, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] + def makeDecl(self): # Note that initializations in the declarations are solely # to avoid 'uninitialized variable' errors from the compiler. - return type + ' ' + op_desc.base_name + ' = 0;\n'; + return self.ctype + ' ' + self.base_name + ' = 0;\n'; -class IntRegOperandTraits(OperandTraits): +class IntRegOperand(Operand): def isReg(self): return 1 def isIntReg(self): return 1 - def makeConstructor(self, op_desc): + def makeConstructor(self): c = '' - if op_desc.is_src: + if self.is_src: c += '\n\t_srcRegIdx[%d] = %s;' % \ - (op_desc.src_reg_idx, self.reg_spec) - if op_desc.is_dest: + (self.src_reg_idx, self.reg_spec) + if self.is_dest: c += '\n\t_destRegIdx[%d] = %s;' % \ - (op_desc.dest_reg_idx, self.reg_spec) + (self.dest_reg_idx, self.reg_spec) return c - def makeRead(self, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] - if (type == 'float' or type == 'double'): + def makeRead(self): + if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to read integer register as FP') - if (size == self.dflt_size): + if (self.size == self.dflt_size): return '%s = xc->readIntReg(this, %d);\n' % \ - (op_desc.base_name, op_desc.src_reg_idx) + (self.base_name, self.src_reg_idx) else: return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \ - (op_desc.base_name, op_desc.src_reg_idx, size-1) + (self.base_name, self.src_reg_idx, self.size-1) - def makeWrite(self, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] - if (type == 'float' or type == 'double'): + def makeWrite(self): + if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to write integer register as FP') - if (size != self.dflt_size and is_signed): - final_val = 'sext<%d>(%s)' % (size, op_desc.base_name) + if (self.size != self.dflt_size and self.is_signed): + final_val = 'sext<%d>(%s)' % (self.size, self.base_name) else: - final_val = op_desc.base_name + final_val = self.base_name wb = ''' { %s final_val = %s; xc->setIntReg(this, %d, final_val);\n if (traceData) { traceData->setData(final_val); } - }''' % (self.dflt_type, final_val, op_desc.dest_reg_idx) + }''' % (self.dflt_ctype, final_val, self.dest_reg_idx) return wb -class FloatRegOperandTraits(OperandTraits): +class FloatRegOperand(Operand): def isReg(self): return 1 def isFloatReg(self): return 1 - def makeConstructor(self, op_desc): + def makeConstructor(self): c = '' - if op_desc.is_src: + if self.is_src: c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \ - (op_desc.src_reg_idx, self.reg_spec) - if op_desc.is_dest: + (self.src_reg_idx, self.reg_spec) + if self.is_dest: c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \ - (op_desc.dest_reg_idx, self.reg_spec) + (self.dest_reg_idx, self.reg_spec) return c - def makeRead(self, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] + def makeRead(self): bit_select = 0 - if (type == 'float'): + if (self.ctype == 'float'): func = 'readFloatRegSingle' - elif (type == 'double'): + elif (self.ctype == 'double'): func = 'readFloatRegDouble' else: func = 'readFloatRegInt' - if (size != self.dflt_size): + if (self.size != self.dflt_size): bit_select = 1 base = 'xc->%s(this, %d)' % \ - (func, op_desc.src_reg_idx) + (func, self.src_reg_idx) if bit_select: return '%s = bits(%s, %d, 0);\n' % \ - (op_desc.base_name, base, size-1) + (self.base_name, base, self.size-1) else: - return '%s = %s;\n' % (op_desc.base_name, base) + return '%s = %s;\n' % (self.base_name, base) - def makeWrite(self, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] - final_val = op_desc.base_name - if (type == 'float'): + def makeWrite(self): + final_val = self.base_name + final_ctype = self.ctype + if (self.ctype == 'float'): func = 'setFloatRegSingle' - elif (type == 'double'): + elif (self.ctype == 'double'): func = 'setFloatRegDouble' else: func = 'setFloatRegInt' - type = 'uint%d_t' % self.dflt_size - if (size != self.dflt_size and is_signed): - final_val = 'sext<%d>(%s)' % (size, op_desc.base_name) + 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) wb = ''' { %s final_val = %s; xc->%s(this, %d, final_val);\n if (traceData) { traceData->setData(final_val); } - }''' % (type, final_val, func, op_desc.dest_reg_idx) + }''' % (final_ctype, final_val, func, self.dest_reg_idx) return wb -class ControlRegOperandTraits(OperandTraits): +class ControlRegOperand(Operand): def isReg(self): return 1 def isControlReg(self): return 1 - def makeConstructor(self, op_desc): + def makeConstructor(self): c = '' - if op_desc.is_src: + if self.is_src: c += '\n\t_srcRegIdx[%d] = %s_DepTag;' % \ - (op_desc.src_reg_idx, self.reg_spec) - if op_desc.is_dest: + (self.src_reg_idx, self.reg_spec) + if self.is_dest: c += '\n\t_destRegIdx[%d] = %s_DepTag;' % \ - (op_desc.dest_reg_idx, self.reg_spec) + (self.dest_reg_idx, self.reg_spec) return c - def makeRead(self, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] + def makeRead(self): bit_select = 0 - if (type == 'float' or type == 'double'): + if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to read control register as FP') base = 'xc->read%s()' % self.reg_spec - if size == self.dflt_size: - return '%s = %s;\n' % (op_desc.base_name, base) + if self.size == self.dflt_size: + return '%s = %s;\n' % (self.base_name, base) else: return '%s = bits(%s, %d, 0);\n' % \ - (op_desc.base_name, base, size-1) + (self.base_name, base, self.size-1) - def makeWrite(self, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] - if (type == 'float' or type == 'double'): + def makeWrite(self): + if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to write control register as FP') - wb = 'xc->set%s(%s);\n' % (self.reg_spec, op_desc.base_name) + wb = 'xc->set%s(%s);\n' % (self.reg_spec, self.base_name) wb += 'if (traceData) { traceData->setData(%s); }' % \ - op_desc.base_name + self.base_name return wb -class MemOperandTraits(OperandTraits): +class MemOperand(Operand): def isMem(self): return 1 - def makeConstructor(self, op_desc): + def makeConstructor(self): return '' - def makeDecl(self, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] + def makeDecl(self): # Note that initializations in the declarations are solely # to avoid 'uninitialized variable' errors from the compiler. # Declare memory data variable. - c = '%s %s = 0;\n' % (type, op_desc.base_name) + c = '%s %s = 0;\n' % (self.ctype, self.base_name) return c - def makeRead(self, op_desc): + def makeRead(self): return '' - def makeWrite(self, op_desc): + 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, op_desc): - (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] - return size + def makeAccSize(self): + return self.size -class NPCOperandTraits(OperandTraits): - def makeConstructor(self, op_desc): +class NPCOperand(Operand): + def makeConstructor(self): return '' - def makeRead(self, op_desc): - return '%s = xc->readPC() + 4;\n' % op_desc.base_name - - def makeWrite(self, op_desc): - return 'xc->setNextPC(%s);\n' % op_desc.base_name - - -exportContextSymbols = ('IntRegOperandTraits', 'FloatRegOperandTraits', - 'ControlRegOperandTraits', 'MemOperandTraits', - 'NPCOperandTraits', 'InstObjParams', 'CodeBlock', - 'makeList', 're', 'string') - -exportContext = {} - -def updateExportContext(): - exportContext.update(exportDict(*exportContextSymbols)) - exportContext.update(templateMap) - + def makeRead(self): + return '%s = xc->readPC() + 4;\n' % self.base_name -def exportDict(*symNames): - return dict([(s, eval(s)) for s in symNames]) + def makeWrite(self): + return 'xc->setNextPC(%s);\n' % self.base_name -# -# Define operand variables that get derived from the basic declaration -# of ISA-specific operands in operandTraitsMap. This function must be -# called by the ISA description file explicitly after defining -# operandTraitsMap (in a 'let' block). -# -def defineDerivedOperandVars(): - global operands - operands = operandTraitsMap.keys() +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 + (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 + # as a subclass of 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''' (? Date: Wed, 15 Feb 2006 13:05:21 -0500 Subject: Gives separate methods for initiating and completing a memory access, which will be helpful for the merged memory model. arch/alpha/isa/mem.isa: Include methods that allow a memory operation to be split between the part that initiates the access, and the part that completes the access. In these functions the Mem variable is explicitly declared; in the default execute functions, the Mem variable is still handled through %(op_decl)s. arch/isa_parser.py: Include recording the type of the memory access variable so that it can be used if it needs to be explicitly declared in a template. Have memory operands consider themselves neither a source nor a destination to avoid including themselves on the op_src_decl list or the op_dest_decl list. Record op_src_decl and op_dest_decl lists to allow for declaring only source or destination operands. This is needed for the split memory access methods. --HG-- extra : convert_revision : f674f7a2f747ae40ba8c3a0933b0337c87ee0b6c --- arch/isa_parser.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 030bb5a7c..96d3e8438 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -1138,6 +1138,7 @@ class Operand(object): # template must be careful not to use it if it doesn't apply. if self.isMem(): self.mem_acc_size = self.makeAccSize() + self.mem_acc_type = self.ctype # Finalize additional fields (primarily code fields). This step # is done separately since some of these fields may depend on the @@ -1148,15 +1149,23 @@ class Operand(object): self.constructor = self.makeConstructor() self.op_decl = self.makeDecl() + if self.isMem(): + self.is_src = '' + self.is_dest = '' + if self.is_src: self.op_rd = self.makeRead() + self.op_src_decl = self.makeDecl() else: self.op_rd = '' + self.op_src_decl = '' if self.is_dest: self.op_wb = self.makeWrite() + self.op_dest_decl = self.makeDecl() else: self.op_wb = '' + self.op_dest_decl = '' def isMem(self): return 0 @@ -1589,6 +1598,14 @@ class CodeBlock: self.op_decl = self.operands.concatAttrStrings('op_decl') + is_src = lambda op: op.is_src + is_dest = lambda op: op.is_dest + + self.op_src_decl = \ + self.operands.concatSomeAttrStrings(is_src, 'op_src_decl') + self.op_dest_decl = \ + self.operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') + self.op_rd = self.operands.concatAttrStrings('op_rd') self.op_wb = self.operands.concatAttrStrings('op_wb') @@ -1596,6 +1613,7 @@ class CodeBlock: if self.operands.memOperand: self.mem_acc_size = self.operands.memOperand.mem_acc_size + self.mem_acc_type = self.operands.memOperand.mem_acc_type # Make a basic guess on the operand class (function unit type). # These are good enough for most cases, and will be overridden -- cgit v1.2.3 From 485568efa972db7fc27f34708d9bc3a2f19871de Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Thu, 16 Feb 2006 11:55:28 -0500 Subject: Fixes to handle generating the initiateAcc and completeAcc functions a little more cleanly. arch/alpha/isa/mem.isa: Avoid explicitly declaring the Mem variable. Instead break up the code blocks used to generate the initiate and complete functions. The templates reflect which operands need to be declared for each function (src, dest, or both). Loads use both the EA code and mem acc code for the initiate, and memacc code and postacc code for the complete. Stores use both the EA code and mem acc code for the initiate, and only post acc code for the complete. arch/isa_parser.py: Remove hack for mem ops. --HG-- extra : convert_revision : a367797a2cb698762bfc27be1da00bcbe9367150 --- arch/isa_parser.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 96d3e8438..bcef77ddf 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -1149,10 +1149,6 @@ class Operand(object): self.constructor = self.makeConstructor() self.op_decl = self.makeDecl() - if self.isMem(): - self.is_src = '' - self.is_dest = '' - if self.is_src: self.op_rd = self.makeRead() self.op_src_decl = self.makeDecl() -- cgit v1.2.3 From a48c24b61eedf580645ff0294b225d1e69a9444b Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Sat, 18 Feb 2006 23:17:45 -0500 Subject: Support NNPC and branch instructions ... Outputs to decoder.cc correctly Edits to the CPU model may still need to be made to handle branch likely insts... arch/isa_parser.py: add a NNPC operand ... arch/mips/isa/base.isa: change SPARC to MIPS arch/mips/isa/decoder.isa: typo < to >= arch/mips/isa/formats/basic.isa: spacing arch/mips/isa/formats/branch.isa: add code for branch instructions (still need adjustments for the branch likely) arch/mips/isa/operands.isa: support for NNPC and R31 arch/mips/isa_traits.hh: NNPC Addr variable --HG-- extra : convert_revision : df03d2a71c36dbc00270c2e3d7882b4f09ed97ad --- arch/isa_parser.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 96d3e8438..606432e60 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -1355,6 +1355,7 @@ class MemOperand(Operand): def makeAccSize(self): return self.size + class NPCOperand(Operand): def makeConstructor(self): return '' @@ -1365,6 +1366,15 @@ class NPCOperand(Operand): def makeWrite(self): return 'xc->setNextPC(%s);\n' % self.base_name +class NNPCOperand(Operand): + def makeConstructor(self): + return '' + + def makeRead(self): + return '%s = xc->readPC() + 8;\n' % self.base_name + + def makeWrite(self): + return 'xc->setNextNPC(%s);\n' % self.base_name def buildOperandNameMap(userDict, lineno): global operandNameMap -- cgit v1.2.3 From 463aa6d49d49ba9c383f07207df57bad75c58ec9 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 19 Feb 2006 02:34:37 -0500 Subject: Changes to untemplate StaticInst and StaticInstPtr, change the isa to a namespace instead of a class, an improvement to the architecture specific header file selection system, and fixed up a few include paths. arch/alpha/alpha_linux_process.cc: Added using directive for AlphaISA namespace arch/alpha/alpha_memory.hh: arch/alpha/isa/branch.isa: cpu/pc_event.hh: Added typedefs for Addr arch/alpha/alpha_tru64_process.cc: arch/alpha/arguments.cc: Added using directive for AlphaISA arch/alpha/ev5.hh: Added an include of arch/alpha/isa_traits.hh, and a using directive for the AlphaISA namespace. arch/alpha/faults.hh: Added a typedef for the Addr type, and changed the formatting of the faults slightly. arch/alpha/isa/main.isa: Untemplatized StaticInst, added a using for namespace AlphaISA to show up in decoder.cc and the exec.ccs, relocated makeNop to decoder.hh arch/alpha/isa/mem.isa: Untemplatized StaticInst and StaticInstPtr arch/alpha/isa/pal.isa: cpu/base_dyn_inst.cc: Untemplatized StaticInstPtr arch/alpha/isa_traits.hh: Changed variables to be externs instead of static since they are part of a namespace and not a class. arch/alpha/stacktrace.cc: Untemplatized StaticInstPtr, and added a using directive for AlphaISA. arch/alpha/stacktrace.hh: Added some typedefs for Addr and MachInst, and untemplatized StaticInstPtr arch/alpha/vtophys.cc: Added a using directive for AlphaISA arch/alpha/vtophys.hh: Added the AlphaISA namespace specifier where needed arch/isa_parser.py: Changed the placement of the definition of the decodeInst function to be outside the namespaceInst namespace. base/loader/object_file.hh: cpu/o3/bpred_unit.hh: Added a typedef for Addr base/loader/symtab.hh: Added a typedef for Addr, and added a TheISA to Addr in another typedef base/remote_gdb.cc: Added a using namespace TheISA, and untemplatized StaticInstPtr base/remote_gdb.hh: Added typedefs for Addr and MachInst cpu/base.cc: Added TheISA specifier to some variables exported from the isa. cpu/base.hh: Added a typedef for Addr, and TheISA to some variables from the ISA cpu/base_dyn_inst.hh: Untemplatized StaticInstPtr, and added TheISA specifier to some variables from the ISA. cpu/exec_context.hh: Added some typedefs for types from the isa, and added TheISA specifier to some variables from the isa cpu/exetrace.hh: Added typedefs for some types from the ISA, and untemplatized StaticInstPtr cpu/memtest/memtest.cc: cpu/o3/btb.cc: dev/baddev.cc: dev/ide_ctrl.cc: dev/ide_disk.cc: dev/isa_fake.cc: dev/ns_gige.cc: dev/pciconfigall.cc: dev/platform.cc: dev/sinic.cc: dev/uart8250.cc: kern/freebsd/freebsd_system.cc: kern/linux/linux_system.cc: kern/system_events.cc: kern/tru64/dump_mbuf.cc: kern/tru64/tru64_events.cc: sim/process.cc: sim/pseudo_inst.cc: sim/system.cc: Added using namespace TheISA cpu/memtest/memtest.hh: cpu/trace/opt_cpu.hh: cpu/trace/reader/itx_reader.hh: dev/ide_disk.hh: dev/pcidev.hh: dev/platform.hh: dev/tsunami.hh: sim/system.hh: sim/vptr.hh: Added typedef for Addr cpu/o3/2bit_local_pred.hh: Changed the include to use arch/isa_traits.hh instead of arch/alpha/isa_traits.hh. Added typedef for Addr cpu/o3/alpha_cpu.hh: Added typedefs for Addr and IntReg cpu/o3/alpha_cpu_impl.hh: Added this-> to setNextPC to fix a problem since it didn't depend on template parameters any more. Removed "typename" where it was no longer needed. cpu/o3/alpha_dyn_inst.hh: Cleaned up some typedefs, and untemplatized StaticInst cpu/o3/alpha_dyn_inst_impl.hh: untemplatized StaticInstPtr cpu/o3/alpha_impl.hh: Fixed up a typedef of MachInst cpu/o3/bpred_unit_impl.hh: Added a using TheISA::MachInst to a function cpu/o3/btb.hh: Changed an include from arch/alpha/isa_traits.hh to arch/isa_traits.hh, and added a typedef for Addr cpu/o3/commit.hh: Removed a typedef of Impl::ISA as ISA, since TheISA takes care of this now. cpu/o3/cpu.cc: Cleaned up namespace issues cpu/o3/cpu.hh: Cleaned up namespace usage cpu/o3/decode.hh: Removed typedef of ISA, and changed it to TheISA cpu/o3/fetch.hh: Fized up typedefs, and changed ISA to TheISA cpu/o3/free_list.hh: Changed include of arch/alpha/isa_traits.hh to arch/isa_traits.hh cpu/o3/iew.hh: Removed typedef of ISA cpu/o3/iew_impl.hh: Added TheISA namespace specifier to MachInst cpu/o3/ras.hh: Changed include from arch/alpha/isa_traits.hh to arch/isa_traits.hh, and added a typedef for Addr. cpu/o3/regfile.hh: Changed ISA to TheISA, and added some typedefs for Addr, IntReg, FloatReg, and MiscRegFile cpu/o3/rename.hh: Changed ISA to TheISA, and added a typedef for RegIndex cpu/o3/rename_map.hh: Added an include for arch/isa_traits.hh, and a typedef for RegIndex cpu/o3/rob.hh: Added a typedef for RegIndex cpu/o3/store_set.hh: cpu/o3/tournament_pred.hh: Changed an include of arch/alpha/isa_traits.hh to arch/isa_traits.hh, and added a typedef of Addr cpu/ozone/cpu.hh: Changed ISA into TheISA, and untemplatized StaticInst cpu/pc_event.cc: Added namespace specifier TheISA to Addr types cpu/profile.hh: kern/kernel_stats.hh: Added typedef for Addr, and untemplatized StaticInstPtr cpu/simple/cpu.cc: Changed using directive from LittleEndianGuest to AlphaISA, which will contain both namespaces. Added TheISA where needed, and untemplatized StaticInst cpu/simple/cpu.hh: Added a typedef for MachInst, and untemplatized StaticInst cpu/static_inst.cc: Untemplatized StaticInst cpu/static_inst.hh: Untemplatized StaticInst by using the TheISA namespace dev/alpha_console.cc: Added using namespace AlphaISA dev/simple_disk.hh: Added typedef for Addr and fixed up some formatting dev/sinicreg.hh: Added TheISA namespace specifier where needed dev/tsunami.cc: dev/tsunami_io.cc: dev/tsunami_pchip.cc: Added using namespace TheISA. It might be better for it to be AlphaISA dev/tsunami_cchip.cc: Added typedef for TheISA. It might be better for it to be AlphaISA kern/linux/aligned.hh: sim/pseudo_inst.hh: Added TheISA namespace specifier to Addr kern/linux/linux_threadinfo.hh: Added typedef for Addr, and TheISA namespace specifier to StackPointerReg kern/tru64/mbuf.hh: Added TheISA to Addr type in structs sim/process.hh: Added typedefs of Addr, RegFile, and MachInst sim/syscall_emul.cc: Added using namespace TheISA, and a cast of VMPageSize to the int type sim/syscall_emul.hh: Added typecast for Addr, and TheISA namespace specifier for where needed --HG-- extra : convert_revision : 91d4f6ca33a73b21c1f1771d74bfdea3b80eff45 --- arch/isa_parser.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 96d3e8438..3fbb5276b 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -224,7 +224,7 @@ def p_specification(t): namespace = isa_name + "Inst" # wrap the decode block as a function definition t[4].wrap_decode_block(''' -StaticInstPtr<%(isa_name)s> +StaticInstPtr %(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst) { using namespace %(namespace)s; @@ -1690,6 +1690,8 @@ namespace %(namespace)s { %(namespace_output)s } // namespace %(namespace)s + +%(decode_function)s ''' @@ -1769,13 +1771,15 @@ def parse_isa_desc(isa_desc_file, output_dir, include_path): includes = '#include "base/bitfield.hh" // for bitfield support' global_output = global_code.header_output namespace_output = namespace_code.header_output + decode_function = '' update_if_needed(output_dir + '/decoder.hh', file_template % vars()) # generate decoder.cc includes = '#include "%s/decoder.hh"' % include_path global_output = global_code.decoder_output namespace_output = namespace_code.decoder_output - namespace_output += namespace_code.decode_block + # namespace_output += namespace_code.decode_block + decode_function = namespace_code.decode_block update_if_needed(output_dir + '/decoder.cc', file_template % vars()) # generate per-cpu exec files @@ -1784,6 +1788,7 @@ def parse_isa_desc(isa_desc_file, output_dir, include_path): includes += cpu.includes global_output = global_code.exec_output[cpu.name] namespace_output = namespace_code.exec_output[cpu.name] + decode_function = '' update_if_needed(output_dir + '/' + cpu.filename, file_template % vars()) -- cgit v1.2.3 From 99484cfae81f3f01ccdfcd273ddc2bdb41e6456b Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 23 Feb 2006 14:31:15 -0500 Subject: Create a Builder object for .isa files in arch/SConscript. Start using SCons File objects to avoid fixed paths in subordinate SConscripts. SConscript: Push isa_parser stuff (including .isa scanner) down into arch/SConscript. arch/SConscript: Create a Builder object for .isa files, including existing scanner. Return file objects generated by isa-specific SConscript back up to parent. arch/alpha/SConscript: arch/mips/SConscript: arch/sparc/SConscript: Convert sources to scons File objects, so file names can be specified relative to the current directory. Invoke new builder for isa description, and get generated sources from there (instead of listing them explicitly). arch/isa_parser.py: Get rid of third argument ("include_path"). It was a pain to generate this from scons, and it turned out it's not needed anyway, since the only included file (decoder.hh) will be in the same directory as the sources. --HG-- extra : convert_revision : 36861bcef36763f229704d8cb7a642b4486a3581 --- arch/isa_parser.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index b92d267c9..a2bf31a0c 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -1751,7 +1751,7 @@ def preprocess_isa_desc(isa_desc): # # Read in and parse the ISA description. # -def parse_isa_desc(isa_desc_file, output_dir, include_path): +def parse_isa_desc(isa_desc_file, output_dir): # set a global var for the input filename... used in error messages global input_filename input_filename = isa_desc_file @@ -1781,7 +1781,7 @@ def parse_isa_desc(isa_desc_file, output_dir, include_path): update_if_needed(output_dir + '/decoder.hh', file_template % vars()) # generate decoder.cc - includes = '#include "%s/decoder.hh"' % include_path + includes = '#include "decoder.hh"' global_output = global_code.decoder_output namespace_output = namespace_code.decoder_output # namespace_output += namespace_code.decode_block @@ -1790,7 +1790,7 @@ def parse_isa_desc(isa_desc_file, output_dir, include_path): # generate per-cpu exec files for cpu in CpuModel.list: - includes = '#include "%s/decoder.hh"\n' % include_path + includes = '#include "decoder.hh"\n' includes += cpu.includes global_output = global_code.exec_output[cpu.name] namespace_output = namespace_code.exec_output[cpu.name] @@ -1800,4 +1800,4 @@ def parse_isa_desc(isa_desc_file, output_dir, include_path): # Called as script: get args from command line. if __name__ == '__main__': - parse_isa_desc(sys.argv[1], sys.argv[2], sys.argv[3]) + parse_isa_desc(sys.argv[1], sys.argv[2]) -- cgit v1.2.3 From 51647e7bec8e8607fc5713b4ace2c24ce8a7455a Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 23 Feb 2006 17:00:29 -0500 Subject: Enable building only selected CPU models via new scons CPU_MODELS parameter. For example: scons CPU_MODELS="SimpleCPU,FullCPU" ALPHA_SE/m5.debug Unfortunately the option is not sticky due to a scons bug with saving & restoring ListOption parameters. SConscript: Separate out cpu-model-specific files so they can be conditionally included based on value of new CPU_MODELS parameter. Most of these are now handled in cpu/SConscript, except for FullCPU which is still in this file. arch/SConscript: The set of CPU-model-specific execute files must now be determined from the CPU_MODELS parameter, via the new cpu_models.py file. Also pass the list of configured CPU models to isa_parser.py. arch/isa_parser.py: Move CpuModel definition and objects out to a separate file so they can be shared with scons. Global list of CPU models to generate code for is now controlled by command-line parameters (so we can do only a subset of the available ones). build/SConstruct: Define new CPU_MODELS ListOption. cpu/static_inst.hh: Rename static_inst_impl.hh to static_inst_exec_sigs.hh. --HG-- extra : convert_revision : 163df32a76d4c05900490b2bce4c7962a5e3f614 --- arch/isa_parser.py | 53 +++++++++++------------------------------------------ 1 file changed, 11 insertions(+), 42 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index a2bf31a0c..6508ca02a 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -712,43 +712,6 @@ yacc.yacc() # ##################################################################### -################ -# CpuModel class -# -# The CpuModel class encapsulates everything we need to know about a -# particular CPU model. - -class CpuModel: - # List of all CPU models. Accessible as CpuModel.list. - list = [] - - # Constructor. Automatically adds models to CpuModel.list. - def __init__(self, name, filename, includes, strings): - self.name = name - self.filename = filename # filename for output exec code - self.includes = includes # include files needed in exec file - # The 'strings' dict holds all the per-CPU symbols we can - # substitute into templates etc. - self.strings = strings - # Add self to list. - CpuModel.list.append(self) - -# Define CPU models. The following lines should contain the only -# CPU-model-specific information in this file. Note that the ISA -# description itself should have *no* CPU-model-specific content. -CpuModel('SimpleCPU', 'simple_cpu_exec.cc', - '#include "cpu/simple/cpu.hh"', - { 'CPU_exec_context': 'SimpleCPU' }) -CpuModel('FastCPU', 'fast_cpu_exec.cc', - '#include "cpu/fast/cpu.hh"', - { 'CPU_exec_context': 'FastCPU' }) -CpuModel('FullCPU', 'full_cpu_exec.cc', - '#include "encumbered/cpu/full/dyn_inst.hh"', - { 'CPU_exec_context': 'DynInst' }) -CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc', - '#include "cpu/o3/alpha_dyn_inst.hh"', - { 'CPU_exec_context': 'AlphaDynInst' }) - # Expand template with CPU-specific references into a dictionary with # an entry for each CPU model name. The entry key is the model name # and the corresponding value is the template with the CPU-specific @@ -757,7 +720,7 @@ def expand_cpu_symbols_to_dict(template): # Protect '%'s that don't go with CPU-specific terms t = re.sub(r'%(?!\(CPU_)', '%%', template) result = {} - for cpu in CpuModel.list: + for cpu in cpu_models: result[cpu.name] = t % cpu.strings return result @@ -816,7 +779,7 @@ class GenCode: # concatenates all the individual strings in the operands. def __add__(self, other): exec_output = {} - for cpu in CpuModel.list: + for cpu in cpu_models: n = cpu.name exec_output[n] = self.exec_output[n] + other.exec_output[n] return GenCode(self.header_output + other.header_output, @@ -830,7 +793,7 @@ class GenCode: self.header_output = pre + self.header_output self.decoder_output = pre + self.decoder_output self.decode_block = pre + self.decode_block - for cpu in CpuModel.list: + for cpu in cpu_models: self.exec_output[cpu.name] = pre + self.exec_output[cpu.name] # Wrap the decode block in a pair of strings (e.g., 'case foo:' @@ -1789,7 +1752,7 @@ def parse_isa_desc(isa_desc_file, output_dir): update_if_needed(output_dir + '/decoder.cc', file_template % vars()) # generate per-cpu exec files - for cpu in CpuModel.list: + for cpu in cpu_models: includes = '#include "decoder.hh"\n' includes += cpu.includes global_output = global_code.exec_output[cpu.name] @@ -1798,6 +1761,12 @@ def parse_isa_desc(isa_desc_file, output_dir): update_if_needed(output_dir + '/' + cpu.filename, file_template % vars()) +# global list of CpuModel objects (see cpu_models.py) +cpu_models = [] + # Called as script: get args from command line. +# Args are: if __name__ == '__main__': - parse_isa_desc(sys.argv[1], sys.argv[2]) + execfile(sys.argv[1]) # read in CpuModel definitions + cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]] + parse_isa_desc(sys.argv[2], sys.argv[3]) -- cgit v1.2.3 From 70b35bab5778799805fe9b6040b23eb1885dbfc3 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Mon, 27 Feb 2006 11:44:35 -0500 Subject: Changes to put all the misc regs within the misc reg file. This includes the FPCR, Uniq, lock flag, lock addr, and IPRs. They are now accessed by calling readMiscReg()/setMiscReg() on the XC. Old IPR accesses are supported by using readMiscRegWithEffect() and setMiscRegWithEffect() (names may change in the future). arch/alpha/alpha_memory.cc: Change accesses to IPR to go through the XC. arch/alpha/ev5.cc: Change accesses for IPRs to go through the misc regs. arch/alpha/isa/decoder.isa: Change accesses to IPRs to go through the misc regs. readIpr() and setIpr() are now changed to calls to readMiscRegWithEffect() and setMiscRegWithEffect(). arch/alpha/isa/fp.isa: Change accesses to IPRs and Fpcr to go through the misc regs. arch/alpha/isa/main.isa: Add support for all misc regs being accessed through readMiscReg() and setMiscReg(). Instead of readUniq and readFpcr, they are replaced by calls with Uniq_DepTag and Fpcr_DepTag passed in as the register index. arch/alpha/isa_traits.hh: Change the MiscRegFile to a class that handles all accesses to MiscRegs, which in Alpha include the FPCR, Uniq, Lock Addr, Lock Flag, and IPRs. Two flavors of accesses are supported: normal register reads/writes, and reads/writes with effect. The latter are basically the original read/write IPR functions, while the former are normal reads/writes. The lock flag and lock addr registers are added to the dependence tags in order to support being accessed through the misc regs. arch/alpha/stacktrace.cc: cpu/simple/cpu.cc: dev/sinic.cc: Change accesses to the IPRs to go through the XC. arch/alpha/vtophys.cc: Change access to the IPR to go through the XC. arch/isa_parser.py: Change generation of code for control registers to use the readMiscReg and setMiscReg functions. base/remote_gdb.cc: Change accesses to the IPR to go through the XC. cpu/exec_context.hh: Use the miscRegs to access the lock addr, lock flag, and other misc registers. cpu/o3/alpha_cpu.hh: cpu/simple/cpu.hh: Support interface for reading and writing misc registers, which replaces readUniq, readFpcr, readIpr, and their set functions. cpu/o3/alpha_cpu_impl.hh: Change accesses to the IPRs to go through the miscRegs. For now comment out some of the accesses to the misc regs until the proxy exec context is completed. cpu/o3/alpha_dyn_inst.hh: Change accesses to misc regs to use readMiscReg and setMiscReg. cpu/o3/alpha_dyn_inst_impl.hh: Remove old misc reg accessors. cpu/o3/cpu.cc: Comment out old misc reg accesses until the proxy exec context is completed. cpu/o3/cpu.hh: Change accesses to the misc regs. cpu/o3/regfile.hh: Remove old access methods for the misc regs, replace them with readMiscReg and setMiscReg. They are dummy functions for now until the proxy exec context is completed. kern/kernel_stats.cc: kern/system_events.cc: Have accesses to the IPRs go through the XC. kern/tru64/tru64.hh: Have accesses to the misc regs use the new access methods. --HG-- extra : convert_revision : e32e0a3fe99522e17294bbe106ff5591cb1a9d76 --- arch/isa_parser.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 6508ca02a..5185ed573 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -1263,10 +1263,10 @@ class ControlRegOperand(Operand): def makeConstructor(self): c = '' if self.is_src: - c += '\n\t_srcRegIdx[%d] = %s_DepTag;' % \ + c += '\n\t_srcRegIdx[%d] = %s;' % \ (self.src_reg_idx, self.reg_spec) if self.is_dest: - c += '\n\t_destRegIdx[%d] = %s_DepTag;' % \ + c += '\n\t_destRegIdx[%d] = %s;' % \ (self.dest_reg_idx, self.reg_spec) return c @@ -1274,7 +1274,7 @@ 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->read%s()' % self.reg_spec + base = 'xc->readMiscReg(%s)' % self.reg_spec if self.size == self.dflt_size: return '%s = %s;\n' % (self.base_name, base) else: @@ -1284,7 +1284,7 @@ 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->set%s(%s);\n' % (self.reg_spec, self.base_name) + wb = 'xc->setMiscReg(%s, %s);\n' % (self.reg_spec, self.base_name) wb += 'if (traceData) { traceData->setData(%s); }' % \ self.base_name return wb -- cgit v1.2.3 From e7825aab59e03b9691d361338fba222f56446f77 Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Fri, 3 Mar 2006 15:28:25 -0500 Subject: Changes to support automatic renaming of the shadow registers at decode time. This requires using an ExtMachInst (uint64_t) instead of the normal MachInst; the ExtMachInst is packed with extra decode context information. In the case of Alpha, the PAL mode is included. The shadow registers are folded into the normal integer registers to ease renaming indexing. Include the removed Opcdec class of instructions for faulting when a pal mode only instruction is decoded in non-pal mode. arch/alpha/ev5.cc: Changes to automatically map the shadow registers if the instruction is in PAL mode. arch/alpha/isa/branch.isa: arch/alpha/isa/decoder.isa: arch/alpha/isa/fp.isa: arch/alpha/isa/int.isa: arch/alpha/isa/mem.isa: arch/alpha/isa/pal.isa: arch/alpha/isa/unimp.isa: Changes for automatically using the shadow registers. Now instructions must decode based on an ExtMachInst, which is a MachInst with any decode context information concatenated onto the higher order bits. arch/alpha/isa/main.isa: Changes for automatically using the shadow registers. Now instructions must decode based on an ExtMachInst, which is a MachInst with any decode context information concatenated onto the higher order bits. The decoder (for Alpha) uses the 32nd bit in order to determine if the machine is in PAL mode. If it is, then it refers to the reg_redir table to determine the true index of the register it is using. Also include the opcdec instruction definition. arch/alpha/isa_traits.hh: Define ExtMachInst type that is used by the static inst in order to decode the instruction, given the context of being in pal mode or not. Redefine the number of Int registers, splitting it into NumIntArchRegs (32) and NumIntRegs (32 + 8 shadow registers). Change the dependence tags to reflect the integer registers include the 8 shadow registers. Define function to make an ExtMachInst. Currently it is somewhat specific to Alpha; in the future it must be decided to make this more generic and possibly slower, or leave it specific to each architecture and ifdef it within the CPU. arch/isa_parser.py: Have static insts decode on the ExtMachInst. base/remote_gdb.cc: Support the automatic remapping of shadow registers. Remote GDB must now look at the PC being read in order to tell if it should use the normal register indices or the shadow register indices. cpu/o3/regfile.hh: Comment out the pal registers; they are now a part of the integer registers. cpu/simple/cpu.cc: Create an ExtMachInst to decode on, based on the normal MachInst and the PC of the instructoin. cpu/static_inst.hh: Change from MachInst to ExtMachInst to support shadow register renaming. --HG-- extra : convert_revision : 1d23eabf735e297068e1917445a6348e9f8c88d5 --- arch/isa_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/isa_parser.py') diff --git a/arch/isa_parser.py b/arch/isa_parser.py index 5185ed573..570110d84 100755 --- a/arch/isa_parser.py +++ b/arch/isa_parser.py @@ -225,7 +225,7 @@ def p_specification(t): # wrap the decode block as a function definition t[4].wrap_decode_block(''' StaticInstPtr -%(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst) +%(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst) { using namespace %(namespace)s; ''' % vars(), '}') -- cgit v1.2.3