1# Copyright (c) 2014 ARM Limited 2# All rights reserved 3# 4# The license below extends only to copyright in the software and shall 5# not be construed as granting a license to any other intellectual 6# property including but not limited to intellectual property relating 7# to a hardware implementation of the functionality of the software 8# licensed hereunder. You may use the software subject to the license 9# terms below provided that you ensure that this notice is replicated 10# unmodified and in its entirety in all distributions of the software, 11# modified or unmodified, in source code or in binary form. 12# 13# Copyright (c) 2003-2005 The Regents of The University of Michigan 14# Copyright (c) 2013 Advanced Micro Devices, Inc. 15# All rights reserved. 16# 17# Redistribution and use in source and binary forms, with or without 18# modification, are permitted provided that the following conditions are 19# met: redistributions of source code must retain the above copyright 20# notice, this list of conditions and the following disclaimer; 21# redistributions in binary form must reproduce the above copyright 22# notice, this list of conditions and the following disclaimer in the 23# documentation and/or other materials provided with the distribution; 24# neither the name of the copyright holders nor the names of its 25# contributors may be used to endorse or promote products derived from 26# this software without specific prior written permission. 27# 28# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39# 40# Authors: Steve Reinhardt 41 42from __future__ import with_statement 43import os 44import sys 45import re 46import string 47import inspect, traceback 48# get type names 49from types import * 50 51from m5.util.grammar import Grammar 52 53debug=False 54 55################### 56# Utility functions 57 58# 59# Indent every line in string 's' by two spaces 60# (except preprocessor directives). 61# Used to make nested code blocks look pretty. 62# 63def indent(s): 64 return re.sub(r'(?m)^(?!#)', ' ', s) 65 66# 67# Munge a somewhat arbitrarily formatted piece of Python code 68# (e.g. from a format 'let' block) into something whose indentation 69# will get by the Python parser. 70# 71# The two keys here are that Python will give a syntax error if 72# there's any whitespace at the beginning of the first line, and that 73# all lines at the same lexical nesting level must have identical 74# indentation. Unfortunately the way code literals work, an entire 75# let block tends to have some initial indentation. Rather than 76# trying to figure out what that is and strip it off, we prepend 'if 77# 1:' to make the let code the nested block inside the if (and have 78# the parser automatically deal with the indentation for us). 79# 80# We don't want to do this if (1) the code block is empty or (2) the 81# first line of the block doesn't have any whitespace at the front. 82 83def fixPythonIndentation(s): 84 # get rid of blank lines first 85 s = re.sub(r'(?m)^\s*\n', '', s); 86 if (s != '' and re.match(r'[ \t]', s[0])): 87 s = 'if 1:\n' + s 88 return s 89 90class ISAParserError(Exception): 91 """Error handler for parser errors""" 92 def __init__(self, first, second=None): 93 if second is None: 94 self.lineno = 0 95 self.string = first 96 else: 97 if hasattr(first, 'lexer'): 98 first = first.lexer.lineno 99 self.lineno = first 100 self.string = second 101 102 def display(self, filename_stack, print_traceback=debug): 103 # Output formatted to work under Emacs compile-mode. Optional 104 # 'print_traceback' arg, if set to True, prints a Python stack 105 # backtrace too (can be handy when trying to debug the parser 106 # itself). 107 108 spaces = "" 109 for (filename, line) in filename_stack[:-1]: 110 print "%sIn file included from %s:" % (spaces, filename) 111 spaces += " " 112 113 # Print a Python stack backtrace if requested. 114 if print_traceback or not self.lineno: 115 traceback.print_exc() 116 117 line_str = "%s:" % (filename_stack[-1][0], ) 118 if self.lineno: 119 line_str += "%d:" % (self.lineno, ) 120 121 return "%s%s %s" % (spaces, line_str, self.string) 122 123 def exit(self, filename_stack, print_traceback=debug): 124 # Just call exit. 125 126 sys.exit(self.display(filename_stack, print_traceback)) 127 128def error(*args): 129 raise ISAParserError(*args) 130 131#################### 132# Template objects. 133# 134# Template objects are format strings that allow substitution from 135# the attribute spaces of other objects (e.g. InstObjParams instances). 136 137labelRE = re.compile(r'(?<!%)%\(([^\)]+)\)[sd]') 138 139class Template(object): 140 def __init__(self, parser, t): 141 self.parser = parser 142 self.template = t 143 144 def subst(self, d): 145 myDict = None 146 147 # Protect non-Python-dict substitutions (e.g. if there's a printf 148 # in the templated C++ code) 149 template = self.parser.protectNonSubstPercents(self.template) 150 # CPU-model-specific substitutions are handled later (in GenCode). 151 template = self.parser.protectCpuSymbols(template) 152 153 # Build a dict ('myDict') to use for the template substitution. 154 # Start with the template namespace. Make a copy since we're 155 # going to modify it. 156 myDict = self.parser.templateMap.copy() 157 158 if isinstance(d, InstObjParams): 159 # If we're dealing with an InstObjParams object, we need 160 # to be a little more sophisticated. The instruction-wide 161 # parameters are already formed, but the parameters which 162 # are only function wide still need to be generated. 163 compositeCode = '' 164 165 myDict.update(d.__dict__) 166 # The "operands" and "snippets" attributes of the InstObjParams 167 # objects are for internal use and not substitution. 168 del myDict['operands'] 169 del myDict['snippets'] 170 171 snippetLabels = [l for l in labelRE.findall(template) 172 if d.snippets.has_key(l)] 173 174 snippets = dict([(s, self.parser.mungeSnippet(d.snippets[s])) 175 for s in snippetLabels]) 176 177 myDict.update(snippets) 178 179 compositeCode = ' '.join(map(str, snippets.values())) 180 181 # Add in template itself in case it references any 182 # operands explicitly (like Mem) 183 compositeCode += ' ' + template 184 185 operands = SubOperandList(self.parser, compositeCode, d.operands) 186 187 myDict['op_decl'] = operands.concatAttrStrings('op_decl') 188 if operands.readPC or operands.setPC: 189 myDict['op_decl'] += 'TheISA::PCState __parserAutoPCState;\n' 190 191 # In case there are predicated register reads and write, declare 192 # the variables for register indicies. It is being assumed that 193 # all the operands in the OperandList are also in the 194 # SubOperandList and in the same order. Otherwise, it is 195 # expected that predication would not be used for the operands. 196 if operands.predRead: 197 myDict['op_decl'] += 'uint8_t _sourceIndex = 0;\n' 198 if operands.predWrite: 199 myDict['op_decl'] += 'uint8_t M5_VAR_USED _destIndex = 0;\n' 200 201 is_src = lambda op: op.is_src 202 is_dest = lambda op: op.is_dest 203 204 myDict['op_src_decl'] = \ 205 operands.concatSomeAttrStrings(is_src, 'op_src_decl') 206 myDict['op_dest_decl'] = \ 207 operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') 208 if operands.readPC: 209 myDict['op_src_decl'] += \ 210 'TheISA::PCState __parserAutoPCState;\n' 211 if operands.setPC: 212 myDict['op_dest_decl'] += \ 213 'TheISA::PCState __parserAutoPCState;\n' 214 215 myDict['op_rd'] = operands.concatAttrStrings('op_rd') 216 if operands.readPC: 217 myDict['op_rd'] = '__parserAutoPCState = xc->pcState();\n' + \ 218 myDict['op_rd'] 219 220 # Compose the op_wb string. If we're going to write back the 221 # PC state because we changed some of its elements, we'll need to 222 # do that as early as possible. That allows later uncoordinated 223 # modifications to the PC to layer appropriately. 224 reordered = list(operands.items) 225 reordered.reverse() 226 op_wb_str = '' 227 pcWbStr = 'xc->pcState(__parserAutoPCState);\n' 228 for op_desc in reordered: 229 if op_desc.isPCPart() and op_desc.is_dest: 230 op_wb_str = op_desc.op_wb + pcWbStr + op_wb_str 231 pcWbStr = '' 232 else: 233 op_wb_str = op_desc.op_wb + op_wb_str 234 myDict['op_wb'] = op_wb_str 235 236 elif isinstance(d, dict): 237 # if the argument is a dictionary, we just use it. 238 myDict.update(d) 239 elif hasattr(d, '__dict__'): 240 # if the argument is an object, we use its attribute map. 241 myDict.update(d.__dict__) 242 else: 243 raise TypeError, "Template.subst() arg must be or have dictionary" 244 return template % myDict 245 246 # Convert to string. This handles the case when a template with a 247 # CPU-specific term gets interpolated into another template or into 248 # an output block. 249 def __str__(self): 250 return self.parser.expandCpuSymbolsToString(self.template) 251 252################ 253# Format object. 254# 255# A format object encapsulates an instruction format. It must provide 256# a defineInst() method that generates the code for an instruction 257# definition. 258 259class Format(object): 260 def __init__(self, id, params, code): 261 self.id = id 262 self.params = params 263 label = 'def format ' + id 264 self.user_code = compile(fixPythonIndentation(code), label, 'exec') 265 param_list = string.join(params, ", ") 266 f = '''def defInst(_code, _context, %s): 267 my_locals = vars().copy() 268 exec _code in _context, my_locals 269 return my_locals\n''' % param_list 270 c = compile(f, label + ' wrapper', 'exec') 271 exec c 272 self.func = defInst 273 274 def defineInst(self, parser, name, args, lineno): 275 parser.updateExportContext() 276 context = parser.exportContext.copy() 277 if len(name): 278 Name = name[0].upper() 279 if len(name) > 1: 280 Name += name[1:] 281 context.update({ 'name' : name, 'Name' : Name }) 282 try: 283 vars = self.func(self.user_code, context, *args[0], **args[1]) 284 except Exception, exc: 285 if debug: 286 raise 287 error(lineno, 'error defining "%s": %s.' % (name, exc)) 288 for k in vars.keys(): 289 if k not in ('header_output', 'decoder_output', 290 'exec_output', 'decode_block'): 291 del vars[k] 292 return GenCode(parser, **vars) 293 294# Special null format to catch an implicit-format instruction 295# definition outside of any format block. 296class NoFormat(object): 297 def __init__(self): 298 self.defaultInst = '' 299 300 def defineInst(self, parser, name, args, lineno): 301 error(lineno, 302 'instruction definition "%s" with no active format!' % name) 303 304############### 305# GenCode class 306# 307# The GenCode class encapsulates generated code destined for various 308# output files. The header_output and decoder_output attributes are 309# strings containing code destined for decoder.hh and decoder.cc 310# respectively. The decode_block attribute contains code to be 311# incorporated in the decode function itself (that will also end up in 312# decoder.cc). The exec_output attribute is a dictionary with a key 313# for each CPU model name; the value associated with a particular key 314# is the string of code for that CPU model's exec.cc file. The 315# has_decode_default attribute is used in the decode block to allow 316# explicit default clauses to override default default clauses. 317 318class GenCode(object): 319 # Constructor. At this point we substitute out all CPU-specific 320 # symbols. For the exec output, these go into the per-model 321 # dictionary. For all other output types they get collapsed into 322 # a single string. 323 def __init__(self, parser, 324 header_output = '', decoder_output = '', exec_output = '', 325 decode_block = '', has_decode_default = False): 326 self.parser = parser 327 self.header_output = parser.expandCpuSymbolsToString(header_output) 328 self.decoder_output = parser.expandCpuSymbolsToString(decoder_output) 329 self.exec_output = exec_output 330 self.decode_block = decode_block 331 self.has_decode_default = has_decode_default 332 333 # Write these code chunks out to the filesystem. They will be properly 334 # interwoven by the write_top_level_files(). 335 def emit(self): 336 if self.header_output: 337 self.parser.get_file('header').write(self.header_output) 338 if self.decoder_output: 339 self.parser.get_file('decoder').write(self.decoder_output) 340 if self.exec_output: 341 self.parser.get_file('exec').write(self.exec_output) 342 if self.decode_block: 343 self.parser.get_file('decode_block').write(self.decode_block) 344 345 # Override '+' operator: generate a new GenCode object that 346 # concatenates all the individual strings in the operands. 347 def __add__(self, other): 348 return GenCode(self.parser, 349 self.header_output + other.header_output, 350 self.decoder_output + other.decoder_output, 351 self.exec_output + other.exec_output, 352 self.decode_block + other.decode_block, 353 self.has_decode_default or other.has_decode_default) 354 355 # Prepend a string (typically a comment) to all the strings. 356 def prepend_all(self, pre): 357 self.header_output = pre + self.header_output 358 self.decoder_output = pre + self.decoder_output 359 self.decode_block = pre + self.decode_block 360 self.exec_output = pre + self.exec_output 361 362 # Wrap the decode block in a pair of strings (e.g., 'case foo:' 363 # and 'break;'). Used to build the big nested switch statement. 364 def wrap_decode_block(self, pre, post = ''): 365 self.decode_block = pre + indent(self.decode_block) + post 366 367##################################################################### 368# 369# Bitfield Operator Support 370# 371##################################################################### 372 373bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>') 374 375bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>') 376bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>') 377 378def substBitOps(code): 379 # first convert single-bit selectors to two-index form 380 # i.e., <n> --> <n:n> 381 code = bitOp1ArgRE.sub(r'<\1:\1>', code) 382 # simple case: selector applied to ID (name) 383 # i.e., foo<a:b> --> bits(foo, a, b) 384 code = bitOpWordRE.sub(r'bits(\1, \2, \3)', code) 385 # if selector is applied to expression (ending in ')'), 386 # we need to search backward for matching '(' 387 match = bitOpExprRE.search(code) 388 while match: 389 exprEnd = match.start() 390 here = exprEnd - 1 391 nestLevel = 1 392 while nestLevel > 0: 393 if code[here] == '(': 394 nestLevel -= 1 395 elif code[here] == ')': 396 nestLevel += 1 397 here -= 1 398 if here < 0: 399 sys.exit("Didn't find '('!") 400 exprStart = here+1 401 newExpr = r'bits(%s, %s, %s)' % (code[exprStart:exprEnd+1], 402 match.group(1), match.group(2)) 403 code = code[:exprStart] + newExpr + code[match.end():] 404 match = bitOpExprRE.search(code) 405 return code 406 407 408##################################################################### 409# 410# Code Parser 411# 412# The remaining code is the support for automatically extracting 413# instruction characteristics from pseudocode. 414# 415##################################################################### 416 417# Force the argument to be a list. Useful for flags, where a caller 418# can specify a singleton flag or a list of flags. Also usful for 419# converting tuples to lists so they can be modified. 420def makeList(arg): 421 if isinstance(arg, list): 422 return arg 423 elif isinstance(arg, tuple): 424 return list(arg) 425 elif not arg: 426 return [] 427 else: 428 return [ arg ] 429 430class Operand(object): 431 '''Base class for operand descriptors. An instance of this class 432 (or actually a class derived from this one) represents a specific 433 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate 434 derived classes encapsulates the traits of a particular operand 435 type (e.g., "32-bit integer register").''' 436 437 def buildReadCode(self, func = None): 438 subst_dict = {"name": self.base_name, 439 "func": func, 440 "reg_idx": self.reg_spec, 441 "ctype": self.ctype} 442 if hasattr(self, 'src_reg_idx'): 443 subst_dict['op_idx'] = self.src_reg_idx 444 code = self.read_code % subst_dict 445 return '%s = %s;\n' % (self.base_name, code) 446 447 def buildWriteCode(self, func = None): 448 subst_dict = {"name": self.base_name, 449 "func": func, 450 "reg_idx": self.reg_spec, 451 "ctype": self.ctype, 452 "final_val": self.base_name} 453 if hasattr(self, 'dest_reg_idx'): 454 subst_dict['op_idx'] = self.dest_reg_idx 455 code = self.write_code % subst_dict 456 return ''' 457 { 458 %s final_val = %s; 459 %s; 460 if (traceData) { traceData->setData(final_val); } 461 }''' % (self.dflt_ctype, self.base_name, code) 462 463 def __init__(self, parser, full_name, ext, is_src, is_dest): 464 self.full_name = full_name 465 self.ext = ext 466 self.is_src = is_src 467 self.is_dest = is_dest 468 # The 'effective extension' (eff_ext) is either the actual 469 # extension, if one was explicitly provided, or the default. 470 if ext: 471 self.eff_ext = ext 472 elif hasattr(self, 'dflt_ext'): 473 self.eff_ext = self.dflt_ext 474 475 if hasattr(self, 'eff_ext'): 476 self.ctype = parser.operandTypeMap[self.eff_ext] 477 478 # Finalize additional fields (primarily code fields). This step 479 # is done separately since some of these fields may depend on the 480 # register index enumeration that hasn't been performed yet at the 481 # time of __init__(). The register index enumeration is affected 482 # by predicated register reads/writes. Hence, we forward the flags 483 # that indicate whether or not predication is in use. 484 def finalize(self, predRead, predWrite): 485 self.flags = self.getFlags() 486 self.constructor = self.makeConstructor(predRead, predWrite) 487 self.op_decl = self.makeDecl() 488 489 if self.is_src: 490 self.op_rd = self.makeRead(predRead) 491 self.op_src_decl = self.makeDecl() 492 else: 493 self.op_rd = '' 494 self.op_src_decl = '' 495 496 if self.is_dest: 497 self.op_wb = self.makeWrite(predWrite) 498 self.op_dest_decl = self.makeDecl() 499 else: 500 self.op_wb = '' 501 self.op_dest_decl = '' 502 503 def isMem(self): 504 return 0 505 506 def isReg(self): 507 return 0 508 509 def isFloatReg(self): 510 return 0 511 512 def isIntReg(self): 513 return 0 514 515 def isCCReg(self): 516 return 0 517
| 1# Copyright (c) 2014 ARM Limited 2# All rights reserved 3# 4# The license below extends only to copyright in the software and shall 5# not be construed as granting a license to any other intellectual 6# property including but not limited to intellectual property relating 7# to a hardware implementation of the functionality of the software 8# licensed hereunder. You may use the software subject to the license 9# terms below provided that you ensure that this notice is replicated 10# unmodified and in its entirety in all distributions of the software, 11# modified or unmodified, in source code or in binary form. 12# 13# Copyright (c) 2003-2005 The Regents of The University of Michigan 14# Copyright (c) 2013 Advanced Micro Devices, Inc. 15# All rights reserved. 16# 17# Redistribution and use in source and binary forms, with or without 18# modification, are permitted provided that the following conditions are 19# met: redistributions of source code must retain the above copyright 20# notice, this list of conditions and the following disclaimer; 21# redistributions in binary form must reproduce the above copyright 22# notice, this list of conditions and the following disclaimer in the 23# documentation and/or other materials provided with the distribution; 24# neither the name of the copyright holders nor the names of its 25# contributors may be used to endorse or promote products derived from 26# this software without specific prior written permission. 27# 28# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39# 40# Authors: Steve Reinhardt 41 42from __future__ import with_statement 43import os 44import sys 45import re 46import string 47import inspect, traceback 48# get type names 49from types import * 50 51from m5.util.grammar import Grammar 52 53debug=False 54 55################### 56# Utility functions 57 58# 59# Indent every line in string 's' by two spaces 60# (except preprocessor directives). 61# Used to make nested code blocks look pretty. 62# 63def indent(s): 64 return re.sub(r'(?m)^(?!#)', ' ', s) 65 66# 67# Munge a somewhat arbitrarily formatted piece of Python code 68# (e.g. from a format 'let' block) into something whose indentation 69# will get by the Python parser. 70# 71# The two keys here are that Python will give a syntax error if 72# there's any whitespace at the beginning of the first line, and that 73# all lines at the same lexical nesting level must have identical 74# indentation. Unfortunately the way code literals work, an entire 75# let block tends to have some initial indentation. Rather than 76# trying to figure out what that is and strip it off, we prepend 'if 77# 1:' to make the let code the nested block inside the if (and have 78# the parser automatically deal with the indentation for us). 79# 80# We don't want to do this if (1) the code block is empty or (2) the 81# first line of the block doesn't have any whitespace at the front. 82 83def fixPythonIndentation(s): 84 # get rid of blank lines first 85 s = re.sub(r'(?m)^\s*\n', '', s); 86 if (s != '' and re.match(r'[ \t]', s[0])): 87 s = 'if 1:\n' + s 88 return s 89 90class ISAParserError(Exception): 91 """Error handler for parser errors""" 92 def __init__(self, first, second=None): 93 if second is None: 94 self.lineno = 0 95 self.string = first 96 else: 97 if hasattr(first, 'lexer'): 98 first = first.lexer.lineno 99 self.lineno = first 100 self.string = second 101 102 def display(self, filename_stack, print_traceback=debug): 103 # Output formatted to work under Emacs compile-mode. Optional 104 # 'print_traceback' arg, if set to True, prints a Python stack 105 # backtrace too (can be handy when trying to debug the parser 106 # itself). 107 108 spaces = "" 109 for (filename, line) in filename_stack[:-1]: 110 print "%sIn file included from %s:" % (spaces, filename) 111 spaces += " " 112 113 # Print a Python stack backtrace if requested. 114 if print_traceback or not self.lineno: 115 traceback.print_exc() 116 117 line_str = "%s:" % (filename_stack[-1][0], ) 118 if self.lineno: 119 line_str += "%d:" % (self.lineno, ) 120 121 return "%s%s %s" % (spaces, line_str, self.string) 122 123 def exit(self, filename_stack, print_traceback=debug): 124 # Just call exit. 125 126 sys.exit(self.display(filename_stack, print_traceback)) 127 128def error(*args): 129 raise ISAParserError(*args) 130 131#################### 132# Template objects. 133# 134# Template objects are format strings that allow substitution from 135# the attribute spaces of other objects (e.g. InstObjParams instances). 136 137labelRE = re.compile(r'(?<!%)%\(([^\)]+)\)[sd]') 138 139class Template(object): 140 def __init__(self, parser, t): 141 self.parser = parser 142 self.template = t 143 144 def subst(self, d): 145 myDict = None 146 147 # Protect non-Python-dict substitutions (e.g. if there's a printf 148 # in the templated C++ code) 149 template = self.parser.protectNonSubstPercents(self.template) 150 # CPU-model-specific substitutions are handled later (in GenCode). 151 template = self.parser.protectCpuSymbols(template) 152 153 # Build a dict ('myDict') to use for the template substitution. 154 # Start with the template namespace. Make a copy since we're 155 # going to modify it. 156 myDict = self.parser.templateMap.copy() 157 158 if isinstance(d, InstObjParams): 159 # If we're dealing with an InstObjParams object, we need 160 # to be a little more sophisticated. The instruction-wide 161 # parameters are already formed, but the parameters which 162 # are only function wide still need to be generated. 163 compositeCode = '' 164 165 myDict.update(d.__dict__) 166 # The "operands" and "snippets" attributes of the InstObjParams 167 # objects are for internal use and not substitution. 168 del myDict['operands'] 169 del myDict['snippets'] 170 171 snippetLabels = [l for l in labelRE.findall(template) 172 if d.snippets.has_key(l)] 173 174 snippets = dict([(s, self.parser.mungeSnippet(d.snippets[s])) 175 for s in snippetLabels]) 176 177 myDict.update(snippets) 178 179 compositeCode = ' '.join(map(str, snippets.values())) 180 181 # Add in template itself in case it references any 182 # operands explicitly (like Mem) 183 compositeCode += ' ' + template 184 185 operands = SubOperandList(self.parser, compositeCode, d.operands) 186 187 myDict['op_decl'] = operands.concatAttrStrings('op_decl') 188 if operands.readPC or operands.setPC: 189 myDict['op_decl'] += 'TheISA::PCState __parserAutoPCState;\n' 190 191 # In case there are predicated register reads and write, declare 192 # the variables for register indicies. It is being assumed that 193 # all the operands in the OperandList are also in the 194 # SubOperandList and in the same order. Otherwise, it is 195 # expected that predication would not be used for the operands. 196 if operands.predRead: 197 myDict['op_decl'] += 'uint8_t _sourceIndex = 0;\n' 198 if operands.predWrite: 199 myDict['op_decl'] += 'uint8_t M5_VAR_USED _destIndex = 0;\n' 200 201 is_src = lambda op: op.is_src 202 is_dest = lambda op: op.is_dest 203 204 myDict['op_src_decl'] = \ 205 operands.concatSomeAttrStrings(is_src, 'op_src_decl') 206 myDict['op_dest_decl'] = \ 207 operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') 208 if operands.readPC: 209 myDict['op_src_decl'] += \ 210 'TheISA::PCState __parserAutoPCState;\n' 211 if operands.setPC: 212 myDict['op_dest_decl'] += \ 213 'TheISA::PCState __parserAutoPCState;\n' 214 215 myDict['op_rd'] = operands.concatAttrStrings('op_rd') 216 if operands.readPC: 217 myDict['op_rd'] = '__parserAutoPCState = xc->pcState();\n' + \ 218 myDict['op_rd'] 219 220 # Compose the op_wb string. If we're going to write back the 221 # PC state because we changed some of its elements, we'll need to 222 # do that as early as possible. That allows later uncoordinated 223 # modifications to the PC to layer appropriately. 224 reordered = list(operands.items) 225 reordered.reverse() 226 op_wb_str = '' 227 pcWbStr = 'xc->pcState(__parserAutoPCState);\n' 228 for op_desc in reordered: 229 if op_desc.isPCPart() and op_desc.is_dest: 230 op_wb_str = op_desc.op_wb + pcWbStr + op_wb_str 231 pcWbStr = '' 232 else: 233 op_wb_str = op_desc.op_wb + op_wb_str 234 myDict['op_wb'] = op_wb_str 235 236 elif isinstance(d, dict): 237 # if the argument is a dictionary, we just use it. 238 myDict.update(d) 239 elif hasattr(d, '__dict__'): 240 # if the argument is an object, we use its attribute map. 241 myDict.update(d.__dict__) 242 else: 243 raise TypeError, "Template.subst() arg must be or have dictionary" 244 return template % myDict 245 246 # Convert to string. This handles the case when a template with a 247 # CPU-specific term gets interpolated into another template or into 248 # an output block. 249 def __str__(self): 250 return self.parser.expandCpuSymbolsToString(self.template) 251 252################ 253# Format object. 254# 255# A format object encapsulates an instruction format. It must provide 256# a defineInst() method that generates the code for an instruction 257# definition. 258 259class Format(object): 260 def __init__(self, id, params, code): 261 self.id = id 262 self.params = params 263 label = 'def format ' + id 264 self.user_code = compile(fixPythonIndentation(code), label, 'exec') 265 param_list = string.join(params, ", ") 266 f = '''def defInst(_code, _context, %s): 267 my_locals = vars().copy() 268 exec _code in _context, my_locals 269 return my_locals\n''' % param_list 270 c = compile(f, label + ' wrapper', 'exec') 271 exec c 272 self.func = defInst 273 274 def defineInst(self, parser, name, args, lineno): 275 parser.updateExportContext() 276 context = parser.exportContext.copy() 277 if len(name): 278 Name = name[0].upper() 279 if len(name) > 1: 280 Name += name[1:] 281 context.update({ 'name' : name, 'Name' : Name }) 282 try: 283 vars = self.func(self.user_code, context, *args[0], **args[1]) 284 except Exception, exc: 285 if debug: 286 raise 287 error(lineno, 'error defining "%s": %s.' % (name, exc)) 288 for k in vars.keys(): 289 if k not in ('header_output', 'decoder_output', 290 'exec_output', 'decode_block'): 291 del vars[k] 292 return GenCode(parser, **vars) 293 294# Special null format to catch an implicit-format instruction 295# definition outside of any format block. 296class NoFormat(object): 297 def __init__(self): 298 self.defaultInst = '' 299 300 def defineInst(self, parser, name, args, lineno): 301 error(lineno, 302 'instruction definition "%s" with no active format!' % name) 303 304############### 305# GenCode class 306# 307# The GenCode class encapsulates generated code destined for various 308# output files. The header_output and decoder_output attributes are 309# strings containing code destined for decoder.hh and decoder.cc 310# respectively. The decode_block attribute contains code to be 311# incorporated in the decode function itself (that will also end up in 312# decoder.cc). The exec_output attribute is a dictionary with a key 313# for each CPU model name; the value associated with a particular key 314# is the string of code for that CPU model's exec.cc file. The 315# has_decode_default attribute is used in the decode block to allow 316# explicit default clauses to override default default clauses. 317 318class GenCode(object): 319 # Constructor. At this point we substitute out all CPU-specific 320 # symbols. For the exec output, these go into the per-model 321 # dictionary. For all other output types they get collapsed into 322 # a single string. 323 def __init__(self, parser, 324 header_output = '', decoder_output = '', exec_output = '', 325 decode_block = '', has_decode_default = False): 326 self.parser = parser 327 self.header_output = parser.expandCpuSymbolsToString(header_output) 328 self.decoder_output = parser.expandCpuSymbolsToString(decoder_output) 329 self.exec_output = exec_output 330 self.decode_block = decode_block 331 self.has_decode_default = has_decode_default 332 333 # Write these code chunks out to the filesystem. They will be properly 334 # interwoven by the write_top_level_files(). 335 def emit(self): 336 if self.header_output: 337 self.parser.get_file('header').write(self.header_output) 338 if self.decoder_output: 339 self.parser.get_file('decoder').write(self.decoder_output) 340 if self.exec_output: 341 self.parser.get_file('exec').write(self.exec_output) 342 if self.decode_block: 343 self.parser.get_file('decode_block').write(self.decode_block) 344 345 # Override '+' operator: generate a new GenCode object that 346 # concatenates all the individual strings in the operands. 347 def __add__(self, other): 348 return GenCode(self.parser, 349 self.header_output + other.header_output, 350 self.decoder_output + other.decoder_output, 351 self.exec_output + other.exec_output, 352 self.decode_block + other.decode_block, 353 self.has_decode_default or other.has_decode_default) 354 355 # Prepend a string (typically a comment) to all the strings. 356 def prepend_all(self, pre): 357 self.header_output = pre + self.header_output 358 self.decoder_output = pre + self.decoder_output 359 self.decode_block = pre + self.decode_block 360 self.exec_output = pre + self.exec_output 361 362 # Wrap the decode block in a pair of strings (e.g., 'case foo:' 363 # and 'break;'). Used to build the big nested switch statement. 364 def wrap_decode_block(self, pre, post = ''): 365 self.decode_block = pre + indent(self.decode_block) + post 366 367##################################################################### 368# 369# Bitfield Operator Support 370# 371##################################################################### 372 373bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>') 374 375bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>') 376bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>') 377 378def substBitOps(code): 379 # first convert single-bit selectors to two-index form 380 # i.e., <n> --> <n:n> 381 code = bitOp1ArgRE.sub(r'<\1:\1>', code) 382 # simple case: selector applied to ID (name) 383 # i.e., foo<a:b> --> bits(foo, a, b) 384 code = bitOpWordRE.sub(r'bits(\1, \2, \3)', code) 385 # if selector is applied to expression (ending in ')'), 386 # we need to search backward for matching '(' 387 match = bitOpExprRE.search(code) 388 while match: 389 exprEnd = match.start() 390 here = exprEnd - 1 391 nestLevel = 1 392 while nestLevel > 0: 393 if code[here] == '(': 394 nestLevel -= 1 395 elif code[here] == ')': 396 nestLevel += 1 397 here -= 1 398 if here < 0: 399 sys.exit("Didn't find '('!") 400 exprStart = here+1 401 newExpr = r'bits(%s, %s, %s)' % (code[exprStart:exprEnd+1], 402 match.group(1), match.group(2)) 403 code = code[:exprStart] + newExpr + code[match.end():] 404 match = bitOpExprRE.search(code) 405 return code 406 407 408##################################################################### 409# 410# Code Parser 411# 412# The remaining code is the support for automatically extracting 413# instruction characteristics from pseudocode. 414# 415##################################################################### 416 417# Force the argument to be a list. Useful for flags, where a caller 418# can specify a singleton flag or a list of flags. Also usful for 419# converting tuples to lists so they can be modified. 420def makeList(arg): 421 if isinstance(arg, list): 422 return arg 423 elif isinstance(arg, tuple): 424 return list(arg) 425 elif not arg: 426 return [] 427 else: 428 return [ arg ] 429 430class Operand(object): 431 '''Base class for operand descriptors. An instance of this class 432 (or actually a class derived from this one) represents a specific 433 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate 434 derived classes encapsulates the traits of a particular operand 435 type (e.g., "32-bit integer register").''' 436 437 def buildReadCode(self, func = None): 438 subst_dict = {"name": self.base_name, 439 "func": func, 440 "reg_idx": self.reg_spec, 441 "ctype": self.ctype} 442 if hasattr(self, 'src_reg_idx'): 443 subst_dict['op_idx'] = self.src_reg_idx 444 code = self.read_code % subst_dict 445 return '%s = %s;\n' % (self.base_name, code) 446 447 def buildWriteCode(self, func = None): 448 subst_dict = {"name": self.base_name, 449 "func": func, 450 "reg_idx": self.reg_spec, 451 "ctype": self.ctype, 452 "final_val": self.base_name} 453 if hasattr(self, 'dest_reg_idx'): 454 subst_dict['op_idx'] = self.dest_reg_idx 455 code = self.write_code % subst_dict 456 return ''' 457 { 458 %s final_val = %s; 459 %s; 460 if (traceData) { traceData->setData(final_val); } 461 }''' % (self.dflt_ctype, self.base_name, code) 462 463 def __init__(self, parser, full_name, ext, is_src, is_dest): 464 self.full_name = full_name 465 self.ext = ext 466 self.is_src = is_src 467 self.is_dest = is_dest 468 # The 'effective extension' (eff_ext) is either the actual 469 # extension, if one was explicitly provided, or the default. 470 if ext: 471 self.eff_ext = ext 472 elif hasattr(self, 'dflt_ext'): 473 self.eff_ext = self.dflt_ext 474 475 if hasattr(self, 'eff_ext'): 476 self.ctype = parser.operandTypeMap[self.eff_ext] 477 478 # Finalize additional fields (primarily code fields). This step 479 # is done separately since some of these fields may depend on the 480 # register index enumeration that hasn't been performed yet at the 481 # time of __init__(). The register index enumeration is affected 482 # by predicated register reads/writes. Hence, we forward the flags 483 # that indicate whether or not predication is in use. 484 def finalize(self, predRead, predWrite): 485 self.flags = self.getFlags() 486 self.constructor = self.makeConstructor(predRead, predWrite) 487 self.op_decl = self.makeDecl() 488 489 if self.is_src: 490 self.op_rd = self.makeRead(predRead) 491 self.op_src_decl = self.makeDecl() 492 else: 493 self.op_rd = '' 494 self.op_src_decl = '' 495 496 if self.is_dest: 497 self.op_wb = self.makeWrite(predWrite) 498 self.op_dest_decl = self.makeDecl() 499 else: 500 self.op_wb = '' 501 self.op_dest_decl = '' 502 503 def isMem(self): 504 return 0 505 506 def isReg(self): 507 return 0 508 509 def isFloatReg(self): 510 return 0 511 512 def isIntReg(self): 513 return 0 514 515 def isCCReg(self): 516 return 0 517
|
518 def isVectorReg(self): 519 return 0 520
| |
521 def isControlReg(self): 522 return 0 523 524 def isPCState(self): 525 return 0 526 527 def isPCPart(self): 528 return self.isPCState() and self.reg_spec 529 530 def hasReadPred(self): 531 return self.read_predicate != None 532 533 def hasWritePred(self): 534 return self.write_predicate != None 535 536 def getFlags(self): 537 # note the empty slice '[:]' gives us a copy of self.flags[0] 538 # instead of a reference to it 539 my_flags = self.flags[0][:] 540 if self.is_src: 541 my_flags += self.flags[1] 542 if self.is_dest: 543 my_flags += self.flags[2] 544 return my_flags 545 546 def makeDecl(self): 547 # Note that initializations in the declarations are solely 548 # to avoid 'uninitialized variable' errors from the compiler. 549 return self.ctype + ' ' + self.base_name + ' = 0;\n'; 550 551class IntRegOperand(Operand): 552 def isReg(self): 553 return 1 554 555 def isIntReg(self): 556 return 1 557 558 def makeConstructor(self, predRead, predWrite): 559 c_src = '' 560 c_dest = '' 561 562 if self.is_src: 563 c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s;' % (self.reg_spec) 564 if self.hasReadPred(): 565 c_src = '\n\tif (%s) {%s\n\t}' % \ 566 (self.read_predicate, c_src) 567 568 if self.is_dest: 569 c_dest = '\n\t_destRegIdx[_numDestRegs++] = %s;' % \ 570 (self.reg_spec) 571 c_dest += '\n\t_numIntDestRegs++;' 572 if self.hasWritePred(): 573 c_dest = '\n\tif (%s) {%s\n\t}' % \ 574 (self.write_predicate, c_dest) 575 576 return c_src + c_dest 577 578 def makeRead(self, predRead): 579 if (self.ctype == 'float' or self.ctype == 'double'): 580 error('Attempt to read integer register as FP') 581 if self.read_code != None: 582 return self.buildReadCode('readIntRegOperand') 583 584 int_reg_val = '' 585 if predRead: 586 int_reg_val = 'xc->readIntRegOperand(this, _sourceIndex++)' 587 if self.hasReadPred(): 588 int_reg_val = '(%s) ? %s : 0' % \ 589 (self.read_predicate, int_reg_val) 590 else: 591 int_reg_val = 'xc->readIntRegOperand(this, %d)' % self.src_reg_idx 592 593 return '%s = %s;\n' % (self.base_name, int_reg_val) 594 595 def makeWrite(self, predWrite): 596 if (self.ctype == 'float' or self.ctype == 'double'): 597 error('Attempt to write integer register as FP') 598 if self.write_code != None: 599 return self.buildWriteCode('setIntRegOperand') 600 601 if predWrite: 602 wp = 'true' 603 if self.hasWritePred(): 604 wp = self.write_predicate 605 606 wcond = 'if (%s)' % (wp) 607 windex = '_destIndex++' 608 else: 609 wcond = '' 610 windex = '%d' % self.dest_reg_idx 611 612 wb = ''' 613 %s 614 { 615 %s final_val = %s; 616 xc->setIntRegOperand(this, %s, final_val);\n 617 if (traceData) { traceData->setData(final_val); } 618 }''' % (wcond, self.ctype, self.base_name, windex) 619 620 return wb 621 622class FloatRegOperand(Operand): 623 def isReg(self): 624 return 1 625 626 def isFloatReg(self): 627 return 1 628 629 def makeConstructor(self, predRead, predWrite): 630 c_src = '' 631 c_dest = '' 632 633 if self.is_src: 634 c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s + FP_Reg_Base;' % \ 635 (self.reg_spec) 636 637 if self.is_dest: 638 c_dest = \ 639 '\n\t_destRegIdx[_numDestRegs++] = %s + FP_Reg_Base;' % \ 640 (self.reg_spec) 641 c_dest += '\n\t_numFPDestRegs++;' 642 643 return c_src + c_dest 644 645 def makeRead(self, predRead): 646 bit_select = 0 647 if (self.ctype == 'float' or self.ctype == 'double'): 648 func = 'readFloatRegOperand' 649 else: 650 func = 'readFloatRegOperandBits' 651 if self.read_code != None: 652 return self.buildReadCode(func) 653 654 if predRead: 655 rindex = '_sourceIndex++' 656 else: 657 rindex = '%d' % self.src_reg_idx 658 659 return '%s = xc->%s(this, %s);\n' % \ 660 (self.base_name, func, rindex) 661 662 def makeWrite(self, predWrite): 663 if (self.ctype == 'float' or self.ctype == 'double'): 664 func = 'setFloatRegOperand' 665 else: 666 func = 'setFloatRegOperandBits' 667 if self.write_code != None: 668 return self.buildWriteCode(func) 669 670 if predWrite: 671 wp = '_destIndex++' 672 else: 673 wp = '%d' % self.dest_reg_idx 674 wp = 'xc->%s(this, %s, final_val);' % (func, wp) 675 676 wb = ''' 677 { 678 %s final_val = %s; 679 %s\n 680 if (traceData) { traceData->setData(final_val); } 681 }''' % (self.ctype, self.base_name, wp) 682 return wb 683 684class CCRegOperand(Operand): 685 def isReg(self): 686 return 1 687 688 def isCCReg(self): 689 return 1 690 691 def makeConstructor(self, predRead, predWrite): 692 c_src = '' 693 c_dest = '' 694 695 if self.is_src: 696 c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s + CC_Reg_Base;' % \ 697 (self.reg_spec) 698 if self.hasReadPred(): 699 c_src = '\n\tif (%s) {%s\n\t}' % \ 700 (self.read_predicate, c_src) 701 702 if self.is_dest: 703 c_dest = \ 704 '\n\t_destRegIdx[_numDestRegs++] = %s + CC_Reg_Base;' % \ 705 (self.reg_spec) 706 c_dest += '\n\t_numCCDestRegs++;' 707 if self.hasWritePred(): 708 c_dest = '\n\tif (%s) {%s\n\t}' % \ 709 (self.write_predicate, c_dest) 710 711 return c_src + c_dest 712 713 def makeRead(self, predRead): 714 if (self.ctype == 'float' or self.ctype == 'double'): 715 error('Attempt to read condition-code register as FP') 716 if self.read_code != None: 717 return self.buildReadCode('readCCRegOperand') 718 719 int_reg_val = '' 720 if predRead: 721 int_reg_val = 'xc->readCCRegOperand(this, _sourceIndex++)' 722 if self.hasReadPred(): 723 int_reg_val = '(%s) ? %s : 0' % \ 724 (self.read_predicate, int_reg_val) 725 else: 726 int_reg_val = 'xc->readCCRegOperand(this, %d)' % self.src_reg_idx 727 728 return '%s = %s;\n' % (self.base_name, int_reg_val) 729 730 def makeWrite(self, predWrite): 731 if (self.ctype == 'float' or self.ctype == 'double'): 732 error('Attempt to write condition-code register as FP') 733 if self.write_code != None: 734 return self.buildWriteCode('setCCRegOperand') 735 736 if predWrite: 737 wp = 'true' 738 if self.hasWritePred(): 739 wp = self.write_predicate 740 741 wcond = 'if (%s)' % (wp) 742 windex = '_destIndex++' 743 else: 744 wcond = '' 745 windex = '%d' % self.dest_reg_idx 746 747 wb = ''' 748 %s 749 { 750 %s final_val = %s; 751 xc->setCCRegOperand(this, %s, final_val);\n 752 if (traceData) { traceData->setData(final_val); } 753 }''' % (wcond, self.ctype, self.base_name, windex) 754 755 return wb 756
| 518 def isControlReg(self): 519 return 0 520 521 def isPCState(self): 522 return 0 523 524 def isPCPart(self): 525 return self.isPCState() and self.reg_spec 526 527 def hasReadPred(self): 528 return self.read_predicate != None 529 530 def hasWritePred(self): 531 return self.write_predicate != None 532 533 def getFlags(self): 534 # note the empty slice '[:]' gives us a copy of self.flags[0] 535 # instead of a reference to it 536 my_flags = self.flags[0][:] 537 if self.is_src: 538 my_flags += self.flags[1] 539 if self.is_dest: 540 my_flags += self.flags[2] 541 return my_flags 542 543 def makeDecl(self): 544 # Note that initializations in the declarations are solely 545 # to avoid 'uninitialized variable' errors from the compiler. 546 return self.ctype + ' ' + self.base_name + ' = 0;\n'; 547 548class IntRegOperand(Operand): 549 def isReg(self): 550 return 1 551 552 def isIntReg(self): 553 return 1 554 555 def makeConstructor(self, predRead, predWrite): 556 c_src = '' 557 c_dest = '' 558 559 if self.is_src: 560 c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s;' % (self.reg_spec) 561 if self.hasReadPred(): 562 c_src = '\n\tif (%s) {%s\n\t}' % \ 563 (self.read_predicate, c_src) 564 565 if self.is_dest: 566 c_dest = '\n\t_destRegIdx[_numDestRegs++] = %s;' % \ 567 (self.reg_spec) 568 c_dest += '\n\t_numIntDestRegs++;' 569 if self.hasWritePred(): 570 c_dest = '\n\tif (%s) {%s\n\t}' % \ 571 (self.write_predicate, c_dest) 572 573 return c_src + c_dest 574 575 def makeRead(self, predRead): 576 if (self.ctype == 'float' or self.ctype == 'double'): 577 error('Attempt to read integer register as FP') 578 if self.read_code != None: 579 return self.buildReadCode('readIntRegOperand') 580 581 int_reg_val = '' 582 if predRead: 583 int_reg_val = 'xc->readIntRegOperand(this, _sourceIndex++)' 584 if self.hasReadPred(): 585 int_reg_val = '(%s) ? %s : 0' % \ 586 (self.read_predicate, int_reg_val) 587 else: 588 int_reg_val = 'xc->readIntRegOperand(this, %d)' % self.src_reg_idx 589 590 return '%s = %s;\n' % (self.base_name, int_reg_val) 591 592 def makeWrite(self, predWrite): 593 if (self.ctype == 'float' or self.ctype == 'double'): 594 error('Attempt to write integer register as FP') 595 if self.write_code != None: 596 return self.buildWriteCode('setIntRegOperand') 597 598 if predWrite: 599 wp = 'true' 600 if self.hasWritePred(): 601 wp = self.write_predicate 602 603 wcond = 'if (%s)' % (wp) 604 windex = '_destIndex++' 605 else: 606 wcond = '' 607 windex = '%d' % self.dest_reg_idx 608 609 wb = ''' 610 %s 611 { 612 %s final_val = %s; 613 xc->setIntRegOperand(this, %s, final_val);\n 614 if (traceData) { traceData->setData(final_val); } 615 }''' % (wcond, self.ctype, self.base_name, windex) 616 617 return wb 618 619class FloatRegOperand(Operand): 620 def isReg(self): 621 return 1 622 623 def isFloatReg(self): 624 return 1 625 626 def makeConstructor(self, predRead, predWrite): 627 c_src = '' 628 c_dest = '' 629 630 if self.is_src: 631 c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s + FP_Reg_Base;' % \ 632 (self.reg_spec) 633 634 if self.is_dest: 635 c_dest = \ 636 '\n\t_destRegIdx[_numDestRegs++] = %s + FP_Reg_Base;' % \ 637 (self.reg_spec) 638 c_dest += '\n\t_numFPDestRegs++;' 639 640 return c_src + c_dest 641 642 def makeRead(self, predRead): 643 bit_select = 0 644 if (self.ctype == 'float' or self.ctype == 'double'): 645 func = 'readFloatRegOperand' 646 else: 647 func = 'readFloatRegOperandBits' 648 if self.read_code != None: 649 return self.buildReadCode(func) 650 651 if predRead: 652 rindex = '_sourceIndex++' 653 else: 654 rindex = '%d' % self.src_reg_idx 655 656 return '%s = xc->%s(this, %s);\n' % \ 657 (self.base_name, func, rindex) 658 659 def makeWrite(self, predWrite): 660 if (self.ctype == 'float' or self.ctype == 'double'): 661 func = 'setFloatRegOperand' 662 else: 663 func = 'setFloatRegOperandBits' 664 if self.write_code != None: 665 return self.buildWriteCode(func) 666 667 if predWrite: 668 wp = '_destIndex++' 669 else: 670 wp = '%d' % self.dest_reg_idx 671 wp = 'xc->%s(this, %s, final_val);' % (func, wp) 672 673 wb = ''' 674 { 675 %s final_val = %s; 676 %s\n 677 if (traceData) { traceData->setData(final_val); } 678 }''' % (self.ctype, self.base_name, wp) 679 return wb 680 681class CCRegOperand(Operand): 682 def isReg(self): 683 return 1 684 685 def isCCReg(self): 686 return 1 687 688 def makeConstructor(self, predRead, predWrite): 689 c_src = '' 690 c_dest = '' 691 692 if self.is_src: 693 c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s + CC_Reg_Base;' % \ 694 (self.reg_spec) 695 if self.hasReadPred(): 696 c_src = '\n\tif (%s) {%s\n\t}' % \ 697 (self.read_predicate, c_src) 698 699 if self.is_dest: 700 c_dest = \ 701 '\n\t_destRegIdx[_numDestRegs++] = %s + CC_Reg_Base;' % \ 702 (self.reg_spec) 703 c_dest += '\n\t_numCCDestRegs++;' 704 if self.hasWritePred(): 705 c_dest = '\n\tif (%s) {%s\n\t}' % \ 706 (self.write_predicate, c_dest) 707 708 return c_src + c_dest 709 710 def makeRead(self, predRead): 711 if (self.ctype == 'float' or self.ctype == 'double'): 712 error('Attempt to read condition-code register as FP') 713 if self.read_code != None: 714 return self.buildReadCode('readCCRegOperand') 715 716 int_reg_val = '' 717 if predRead: 718 int_reg_val = 'xc->readCCRegOperand(this, _sourceIndex++)' 719 if self.hasReadPred(): 720 int_reg_val = '(%s) ? %s : 0' % \ 721 (self.read_predicate, int_reg_val) 722 else: 723 int_reg_val = 'xc->readCCRegOperand(this, %d)' % self.src_reg_idx 724 725 return '%s = %s;\n' % (self.base_name, int_reg_val) 726 727 def makeWrite(self, predWrite): 728 if (self.ctype == 'float' or self.ctype == 'double'): 729 error('Attempt to write condition-code register as FP') 730 if self.write_code != None: 731 return self.buildWriteCode('setCCRegOperand') 732 733 if predWrite: 734 wp = 'true' 735 if self.hasWritePred(): 736 wp = self.write_predicate 737 738 wcond = 'if (%s)' % (wp) 739 windex = '_destIndex++' 740 else: 741 wcond = '' 742 windex = '%d' % self.dest_reg_idx 743 744 wb = ''' 745 %s 746 { 747 %s final_val = %s; 748 xc->setCCRegOperand(this, %s, final_val);\n 749 if (traceData) { traceData->setData(final_val); } 750 }''' % (wcond, self.ctype, self.base_name, windex) 751 752 return wb 753
|
757class VectorRegOperand(Operand): 758 def isReg(self): 759 return 1 760 761 def isVectorReg(self): 762 return 1 763 764 def __init__(self, parser, full_name, ext, is_src, is_dest): 765 ## Vector registers are always treated as source registers since 766 ## not the whole of them might be written, in which case we need 767 ## to retain the earlier value. 768 super(VectorRegOperand, self).__init__(parser, full_name, ext, 769 True, is_dest) 770 self.size = 0 771 772 def finalize(self, predRead, predWrite): 773 self.flags = self.getFlags() 774 self.constructor = self.makeConstructor(predRead, predWrite) 775 self.op_decl = self.makeDecl() 776 777 if self.is_src: 778 self.op_rd = self.makeRead(predRead) 779 self.op_src_decl = self.makeDecl() 780 else: 781 self.op_rd = '' 782 self.op_src_decl = '' 783 784 if self.is_dest: 785 self.op_wb = self.makeWrite(predWrite) 786 self.op_dest_decl = self.makeDecl() 787 else: 788 self.op_wb = '' 789 self.op_dest_decl = '' 790 791 def makeConstructor(self, predRead, predWrite): 792 c_src = '' 793 c_dest = '' 794 795 if self.is_src: 796 c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s + Vector_Reg_Base;' % \ 797 (self.reg_spec) 798 if self.hasReadPred(): 799 c_src = '\n\tif (%s) {%s\n\t}' % \ 800 (self.read_predicate, c_src) 801 802 if self.is_dest: 803 c_dest = '\n\t_destRegIdx[_numDestRegs++] = %s + Vector_Reg_Base;' % \ 804 (self.reg_spec) 805 c_dest += '\n\t_numVectorDestRegs++;' 806 if self.hasWritePred(): 807 c_dest = '\n\tif (%s) {%s\n\t}' % \ 808 (self.write_predicate, c_dest) 809 810 return c_src + c_dest 811 812 def makeRead(self, predRead): 813 if self.read_code != None: 814 return self.buildReadCode('readVectorRegOperand') 815 816 vector_reg_val = '' 817 if predRead: 818 vector_reg_val = 'xc->readVectorRegOperand(this, _sourceIndex++)' 819 if self.hasReadPred(): 820 vector_reg_val = '(%s) ? %s : 0' % \ 821 (self.read_predicate, vector_reg_val) 822 else: 823 vector_reg_val = 'xc->readVectorRegOperand(this, %d)' % \ 824 self.src_reg_idx 825 826 return '%s = %s;\n' % (self.base_name, vector_reg_val) 827 828 def makeWrite(self, predWrite): 829 if self.write_code != None: 830 return self.buildWriteCode('setVectorRegOperand') 831 832 if predWrite: 833 wp = 'true' 834 if self.hasWritePred(): 835 wp = self.write_predicate 836 837 wcond = 'if (%s)' % (wp) 838 windex = '_destIndex++' 839 else: 840 wcond = '' 841 windex = '%d' % self.dest_reg_idx 842 843 wb = ''' 844 %s 845 { 846 TheISA::VectorReg final_val = %s; 847 xc->setVectorRegOperand(this, %s, final_val);\n 848 if (traceData) { traceData->setData(final_val); } 849 }''' % (wcond, self.base_name, windex) 850 851 return wb 852 853 def makeDecl(self): 854 ctype = 'TheISA::VectorReg' 855 return '%s %s;\n' % (ctype, self.base_name) 856
| |
857class ControlRegOperand(Operand): 858 def isReg(self): 859 return 1 860 861 def isControlReg(self): 862 return 1 863 864 def makeConstructor(self, predRead, predWrite): 865 c_src = '' 866 c_dest = '' 867 868 if self.is_src: 869 c_src = \ 870 '\n\t_srcRegIdx[_numSrcRegs++] = %s + Misc_Reg_Base;' % \ 871 (self.reg_spec) 872 873 if self.is_dest: 874 c_dest = \ 875 '\n\t_destRegIdx[_numDestRegs++] = %s + Misc_Reg_Base;' % \ 876 (self.reg_spec) 877 878 return c_src + c_dest 879 880 def makeRead(self, predRead): 881 bit_select = 0 882 if (self.ctype == 'float' or self.ctype == 'double'): 883 error('Attempt to read control register as FP') 884 if self.read_code != None: 885 return self.buildReadCode('readMiscRegOperand') 886 887 if predRead: 888 rindex = '_sourceIndex++' 889 else: 890 rindex = '%d' % self.src_reg_idx 891 892 return '%s = xc->readMiscRegOperand(this, %s);\n' % \ 893 (self.base_name, rindex) 894 895 def makeWrite(self, predWrite): 896 if (self.ctype == 'float' or self.ctype == 'double'): 897 error('Attempt to write control register as FP') 898 if self.write_code != None: 899 return self.buildWriteCode('setMiscRegOperand') 900 901 if predWrite: 902 windex = '_destIndex++' 903 else: 904 windex = '%d' % self.dest_reg_idx 905 906 wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \ 907 (windex, self.base_name) 908 wb += 'if (traceData) { traceData->setData(%s); }' % \ 909 self.base_name 910 911 return wb 912 913class MemOperand(Operand): 914 def isMem(self): 915 return 1 916 917 def makeConstructor(self, predRead, predWrite): 918 return '' 919 920 def makeDecl(self): 921 # Note that initializations in the declarations are solely 922 # to avoid 'uninitialized variable' errors from the compiler. 923 # Declare memory data variable.
| 754class ControlRegOperand(Operand): 755 def isReg(self): 756 return 1 757 758 def isControlReg(self): 759 return 1 760 761 def makeConstructor(self, predRead, predWrite): 762 c_src = '' 763 c_dest = '' 764 765 if self.is_src: 766 c_src = \ 767 '\n\t_srcRegIdx[_numSrcRegs++] = %s + Misc_Reg_Base;' % \ 768 (self.reg_spec) 769 770 if self.is_dest: 771 c_dest = \ 772 '\n\t_destRegIdx[_numDestRegs++] = %s + Misc_Reg_Base;' % \ 773 (self.reg_spec) 774 775 return c_src + c_dest 776 777 def makeRead(self, predRead): 778 bit_select = 0 779 if (self.ctype == 'float' or self.ctype == 'double'): 780 error('Attempt to read control register as FP') 781 if self.read_code != None: 782 return self.buildReadCode('readMiscRegOperand') 783 784 if predRead: 785 rindex = '_sourceIndex++' 786 else: 787 rindex = '%d' % self.src_reg_idx 788 789 return '%s = xc->readMiscRegOperand(this, %s);\n' % \ 790 (self.base_name, rindex) 791 792 def makeWrite(self, predWrite): 793 if (self.ctype == 'float' or self.ctype == 'double'): 794 error('Attempt to write control register as FP') 795 if self.write_code != None: 796 return self.buildWriteCode('setMiscRegOperand') 797 798 if predWrite: 799 windex = '_destIndex++' 800 else: 801 windex = '%d' % self.dest_reg_idx 802 803 wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \ 804 (windex, self.base_name) 805 wb += 'if (traceData) { traceData->setData(%s); }' % \ 806 self.base_name 807 808 return wb 809 810class MemOperand(Operand): 811 def isMem(self): 812 return 1 813 814 def makeConstructor(self, predRead, predWrite): 815 return '' 816 817 def makeDecl(self): 818 # Note that initializations in the declarations are solely 819 # to avoid 'uninitialized variable' errors from the compiler. 820 # Declare memory data variable.
|
924 if 'IsVector' in self.flags: 925 return 'TheISA::VectorReg %s;\n' % self.base_name 926 else: 927 return '%s %s = 0;\n' % (self.ctype, self.base_name)
| 821 return '%s %s = 0;\n' % (self.ctype, self.base_name)
|
928 929 def makeRead(self, predRead): 930 if self.read_code != None: 931 return self.buildReadCode() 932 return '' 933 934 def makeWrite(self, predWrite): 935 if self.write_code != None: 936 return self.buildWriteCode() 937 return '' 938 939class PCStateOperand(Operand): 940 def makeConstructor(self, predRead, predWrite): 941 return '' 942 943 def makeRead(self, predRead): 944 if self.reg_spec: 945 # A component of the PC state. 946 return '%s = __parserAutoPCState.%s();\n' % \ 947 (self.base_name, self.reg_spec) 948 else: 949 # The whole PC state itself. 950 return '%s = xc->pcState();\n' % self.base_name 951 952 def makeWrite(self, predWrite): 953 if self.reg_spec: 954 # A component of the PC state. 955 return '__parserAutoPCState.%s(%s);\n' % \ 956 (self.reg_spec, self.base_name) 957 else: 958 # The whole PC state itself. 959 return 'xc->pcState(%s);\n' % self.base_name 960 961 def makeDecl(self): 962 ctype = 'TheISA::PCState' 963 if self.isPCPart(): 964 ctype = self.ctype 965 # Note that initializations in the declarations are solely 966 # to avoid 'uninitialized variable' errors from the compiler. 967 return '%s %s = 0;\n' % (ctype, self.base_name) 968 969 def isPCState(self): 970 return 1 971 972class OperandList(object): 973 '''Find all the operands in the given code block. Returns an operand 974 descriptor list (instance of class OperandList).''' 975 def __init__(self, parser, code): 976 self.items = [] 977 self.bases = {} 978 # delete strings and comments so we don't match on operands inside 979 for regEx in (stringRE, commentRE): 980 code = regEx.sub('', code) 981 # search for operands 982 next_pos = 0 983 while 1: 984 match = parser.operandsRE.search(code, next_pos) 985 if not match: 986 # no more matches: we're done 987 break 988 op = match.groups() 989 # regexp groups are operand full name, base, and extension 990 (op_full, op_base, op_ext) = op 991 # if the token following the operand is an assignment, this is 992 # a destination (LHS), else it's a source (RHS) 993 is_dest = (assignRE.match(code, match.end()) != None) 994 is_src = not is_dest 995 # see if we've already seen this one 996 op_desc = self.find_base(op_base) 997 if op_desc: 998 if op_desc.ext != op_ext: 999 error('Inconsistent extensions for operand %s' % \ 1000 op_base) 1001 op_desc.is_src = op_desc.is_src or is_src 1002 op_desc.is_dest = op_desc.is_dest or is_dest 1003 else: 1004 # new operand: create new descriptor 1005 op_desc = parser.operandNameMap[op_base](parser, 1006 op_full, op_ext, is_src, is_dest) 1007 self.append(op_desc) 1008 # start next search after end of current match 1009 next_pos = match.end() 1010 self.sort() 1011 # enumerate source & dest register operands... used in building 1012 # constructor later 1013 self.numSrcRegs = 0 1014 self.numDestRegs = 0 1015 self.numFPDestRegs = 0 1016 self.numIntDestRegs = 0 1017 self.numCCDestRegs = 0
| 822 823 def makeRead(self, predRead): 824 if self.read_code != None: 825 return self.buildReadCode() 826 return '' 827 828 def makeWrite(self, predWrite): 829 if self.write_code != None: 830 return self.buildWriteCode() 831 return '' 832 833class PCStateOperand(Operand): 834 def makeConstructor(self, predRead, predWrite): 835 return '' 836 837 def makeRead(self, predRead): 838 if self.reg_spec: 839 # A component of the PC state. 840 return '%s = __parserAutoPCState.%s();\n' % \ 841 (self.base_name, self.reg_spec) 842 else: 843 # The whole PC state itself. 844 return '%s = xc->pcState();\n' % self.base_name 845 846 def makeWrite(self, predWrite): 847 if self.reg_spec: 848 # A component of the PC state. 849 return '__parserAutoPCState.%s(%s);\n' % \ 850 (self.reg_spec, self.base_name) 851 else: 852 # The whole PC state itself. 853 return 'xc->pcState(%s);\n' % self.base_name 854 855 def makeDecl(self): 856 ctype = 'TheISA::PCState' 857 if self.isPCPart(): 858 ctype = self.ctype 859 # Note that initializations in the declarations are solely 860 # to avoid 'uninitialized variable' errors from the compiler. 861 return '%s %s = 0;\n' % (ctype, self.base_name) 862 863 def isPCState(self): 864 return 1 865 866class OperandList(object): 867 '''Find all the operands in the given code block. Returns an operand 868 descriptor list (instance of class OperandList).''' 869 def __init__(self, parser, code): 870 self.items = [] 871 self.bases = {} 872 # delete strings and comments so we don't match on operands inside 873 for regEx in (stringRE, commentRE): 874 code = regEx.sub('', code) 875 # search for operands 876 next_pos = 0 877 while 1: 878 match = parser.operandsRE.search(code, next_pos) 879 if not match: 880 # no more matches: we're done 881 break 882 op = match.groups() 883 # regexp groups are operand full name, base, and extension 884 (op_full, op_base, op_ext) = op 885 # if the token following the operand is an assignment, this is 886 # a destination (LHS), else it's a source (RHS) 887 is_dest = (assignRE.match(code, match.end()) != None) 888 is_src = not is_dest 889 # see if we've already seen this one 890 op_desc = self.find_base(op_base) 891 if op_desc: 892 if op_desc.ext != op_ext: 893 error('Inconsistent extensions for operand %s' % \ 894 op_base) 895 op_desc.is_src = op_desc.is_src or is_src 896 op_desc.is_dest = op_desc.is_dest or is_dest 897 else: 898 # new operand: create new descriptor 899 op_desc = parser.operandNameMap[op_base](parser, 900 op_full, op_ext, is_src, is_dest) 901 self.append(op_desc) 902 # start next search after end of current match 903 next_pos = match.end() 904 self.sort() 905 # enumerate source & dest register operands... used in building 906 # constructor later 907 self.numSrcRegs = 0 908 self.numDestRegs = 0 909 self.numFPDestRegs = 0 910 self.numIntDestRegs = 0 911 self.numCCDestRegs = 0
|
1018 self.numVectorDestRegs = 0
| |
1019 self.numMiscDestRegs = 0 1020 self.memOperand = None 1021 1022 # Flags to keep track if one or more operands are to be read/written 1023 # conditionally. 1024 self.predRead = False 1025 self.predWrite = False 1026 1027 for op_desc in self.items: 1028 if op_desc.isReg(): 1029 if op_desc.is_src: 1030 op_desc.src_reg_idx = self.numSrcRegs 1031 self.numSrcRegs += 1 1032 if op_desc.is_dest: 1033 op_desc.dest_reg_idx = self.numDestRegs 1034 self.numDestRegs += 1 1035 if op_desc.isFloatReg(): 1036 self.numFPDestRegs += 1 1037 elif op_desc.isIntReg(): 1038 self.numIntDestRegs += 1 1039 elif op_desc.isCCReg(): 1040 self.numCCDestRegs += 1
| 912 self.numMiscDestRegs = 0 913 self.memOperand = None 914 915 # Flags to keep track if one or more operands are to be read/written 916 # conditionally. 917 self.predRead = False 918 self.predWrite = False 919 920 for op_desc in self.items: 921 if op_desc.isReg(): 922 if op_desc.is_src: 923 op_desc.src_reg_idx = self.numSrcRegs 924 self.numSrcRegs += 1 925 if op_desc.is_dest: 926 op_desc.dest_reg_idx = self.numDestRegs 927 self.numDestRegs += 1 928 if op_desc.isFloatReg(): 929 self.numFPDestRegs += 1 930 elif op_desc.isIntReg(): 931 self.numIntDestRegs += 1 932 elif op_desc.isCCReg(): 933 self.numCCDestRegs += 1
|
1041 elif op_desc.isVectorReg(): 1042 self.numVectorDestRegs += 1
| |
1043 elif op_desc.isControlReg(): 1044 self.numMiscDestRegs += 1 1045 elif op_desc.isMem(): 1046 if self.memOperand: 1047 error("Code block has more than one memory operand.") 1048 self.memOperand = op_desc 1049 1050 # Check if this operand has read/write predication. If true, then 1051 # the microop will dynamically index source/dest registers. 1052 self.predRead = self.predRead or op_desc.hasReadPred() 1053 self.predWrite = self.predWrite or op_desc.hasWritePred() 1054 1055 if parser.maxInstSrcRegs < self.numSrcRegs: 1056 parser.maxInstSrcRegs = self.numSrcRegs 1057 if parser.maxInstDestRegs < self.numDestRegs: 1058 parser.maxInstDestRegs = self.numDestRegs 1059 if parser.maxMiscDestRegs < self.numMiscDestRegs: 1060 parser.maxMiscDestRegs = self.numMiscDestRegs 1061 1062 # now make a final pass to finalize op_desc fields that may depend 1063 # on the register enumeration 1064 for op_desc in self.items: 1065 op_desc.finalize(self.predRead, self.predWrite) 1066 1067 def __len__(self): 1068 return len(self.items) 1069 1070 def __getitem__(self, index): 1071 return self.items[index] 1072 1073 def append(self, op_desc): 1074 self.items.append(op_desc) 1075 self.bases[op_desc.base_name] = op_desc 1076 1077 def find_base(self, base_name): 1078 # like self.bases[base_name], but returns None if not found 1079 # (rather than raising exception) 1080 return self.bases.get(base_name) 1081 1082 # internal helper function for concat[Some]Attr{Strings|Lists} 1083 def __internalConcatAttrs(self, attr_name, filter, result): 1084 for op_desc in self.items: 1085 if filter(op_desc): 1086 result += getattr(op_desc, attr_name) 1087 return result 1088 1089 # return a single string that is the concatenation of the (string) 1090 # values of the specified attribute for all operands 1091 def concatAttrStrings(self, attr_name): 1092 return self.__internalConcatAttrs(attr_name, lambda x: 1, '') 1093 1094 # like concatAttrStrings, but only include the values for the operands 1095 # for which the provided filter function returns true 1096 def concatSomeAttrStrings(self, filter, attr_name): 1097 return self.__internalConcatAttrs(attr_name, filter, '') 1098 1099 # return a single list that is the concatenation of the (list) 1100 # values of the specified attribute for all operands 1101 def concatAttrLists(self, attr_name): 1102 return self.__internalConcatAttrs(attr_name, lambda x: 1, []) 1103 1104 # like concatAttrLists, but only include the values for the operands 1105 # for which the provided filter function returns true 1106 def concatSomeAttrLists(self, filter, attr_name): 1107 return self.__internalConcatAttrs(attr_name, filter, []) 1108 1109 def sort(self): 1110 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri) 1111 1112class SubOperandList(OperandList): 1113 '''Find all the operands in the given code block. Returns an operand 1114 descriptor list (instance of class OperandList).''' 1115 def __init__(self, parser, code, master_list): 1116 self.items = [] 1117 self.bases = {} 1118 # delete strings and comments so we don't match on operands inside 1119 for regEx in (stringRE, commentRE): 1120 code = regEx.sub('', code) 1121 # search for operands 1122 next_pos = 0 1123 while 1: 1124 match = parser.operandsRE.search(code, next_pos) 1125 if not match: 1126 # no more matches: we're done 1127 break 1128 op = match.groups() 1129 # regexp groups are operand full name, base, and extension 1130 (op_full, op_base, op_ext) = op 1131 # find this op in the master list 1132 op_desc = master_list.find_base(op_base) 1133 if not op_desc: 1134 error('Found operand %s which is not in the master list!' \ 1135 ' This is an internal error' % op_base) 1136 else: 1137 # See if we've already found this operand 1138 op_desc = self.find_base(op_base) 1139 if not op_desc: 1140 # if not, add a reference to it to this sub list 1141 self.append(master_list.bases[op_base]) 1142 1143 # start next search after end of current match 1144 next_pos = match.end() 1145 self.sort() 1146 self.memOperand = None 1147 # Whether the whole PC needs to be read so parts of it can be accessed 1148 self.readPC = False 1149 # Whether the whole PC needs to be written after parts of it were 1150 # changed 1151 self.setPC = False 1152 # Whether this instruction manipulates the whole PC or parts of it. 1153 # Mixing the two is a bad idea and flagged as an error. 1154 self.pcPart = None 1155 1156 # Flags to keep track if one or more operands are to be read/written 1157 # conditionally. 1158 self.predRead = False 1159 self.predWrite = False 1160 1161 for op_desc in self.items: 1162 if op_desc.isPCPart(): 1163 self.readPC = True 1164 if op_desc.is_dest: 1165 self.setPC = True 1166 1167 if op_desc.isPCState(): 1168 if self.pcPart is not None: 1169 if self.pcPart and not op_desc.isPCPart() or \ 1170 not self.pcPart and op_desc.isPCPart(): 1171 error("Mixed whole and partial PC state operands.") 1172 self.pcPart = op_desc.isPCPart() 1173 1174 if op_desc.isMem(): 1175 if self.memOperand: 1176 error("Code block has more than one memory operand.") 1177 self.memOperand = op_desc 1178 1179 # Check if this operand has read/write predication. If true, then 1180 # the microop will dynamically index source/dest registers. 1181 self.predRead = self.predRead or op_desc.hasReadPred() 1182 self.predWrite = self.predWrite or op_desc.hasWritePred() 1183 1184# Regular expression object to match C++ strings 1185stringRE = re.compile(r'"([^"\\]|\\.)*"') 1186 1187# Regular expression object to match C++ comments 1188# (used in findOperands()) 1189commentRE = re.compile(r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?', 1190 re.DOTALL | re.MULTILINE) 1191 1192# Regular expression object to match assignment statements 1193# (used in findOperands()) 1194assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) 1195 1196def makeFlagConstructor(flag_list): 1197 if len(flag_list) == 0: 1198 return '' 1199 # filter out repeated flags 1200 flag_list.sort() 1201 i = 1 1202 while i < len(flag_list): 1203 if flag_list[i] == flag_list[i-1]: 1204 del flag_list[i] 1205 else: 1206 i += 1 1207 pre = '\n\tflags[' 1208 post = '] = true;' 1209 code = pre + string.join(flag_list, post + pre) + post 1210 return code 1211 1212# Assume all instruction flags are of the form 'IsFoo' 1213instFlagRE = re.compile(r'Is.*') 1214 1215# OpClass constants end in 'Op' except No_OpClass 1216opClassRE = re.compile(r'.*Op|No_OpClass') 1217 1218class InstObjParams(object): 1219 def __init__(self, parser, mnem, class_name, base_class = '', 1220 snippets = {}, opt_args = []): 1221 self.mnemonic = mnem 1222 self.class_name = class_name 1223 self.base_class = base_class 1224 if not isinstance(snippets, dict): 1225 snippets = {'code' : snippets} 1226 compositeCode = ' '.join(map(str, snippets.values())) 1227 self.snippets = snippets 1228 1229 self.operands = OperandList(parser, compositeCode) 1230 1231 # The header of the constructor declares the variables to be used 1232 # in the body of the constructor. 1233 header = '' 1234 header += '\n\t_numSrcRegs = 0;' 1235 header += '\n\t_numDestRegs = 0;' 1236 header += '\n\t_numFPDestRegs = 0;' 1237 header += '\n\t_numIntDestRegs = 0;' 1238 header += '\n\t_numCCDestRegs = 0;'
| 934 elif op_desc.isControlReg(): 935 self.numMiscDestRegs += 1 936 elif op_desc.isMem(): 937 if self.memOperand: 938 error("Code block has more than one memory operand.") 939 self.memOperand = op_desc 940 941 # Check if this operand has read/write predication. If true, then 942 # the microop will dynamically index source/dest registers. 943 self.predRead = self.predRead or op_desc.hasReadPred() 944 self.predWrite = self.predWrite or op_desc.hasWritePred() 945 946 if parser.maxInstSrcRegs < self.numSrcRegs: 947 parser.maxInstSrcRegs = self.numSrcRegs 948 if parser.maxInstDestRegs < self.numDestRegs: 949 parser.maxInstDestRegs = self.numDestRegs 950 if parser.maxMiscDestRegs < self.numMiscDestRegs: 951 parser.maxMiscDestRegs = self.numMiscDestRegs 952 953 # now make a final pass to finalize op_desc fields that may depend 954 # on the register enumeration 955 for op_desc in self.items: 956 op_desc.finalize(self.predRead, self.predWrite) 957 958 def __len__(self): 959 return len(self.items) 960 961 def __getitem__(self, index): 962 return self.items[index] 963 964 def append(self, op_desc): 965 self.items.append(op_desc) 966 self.bases[op_desc.base_name] = op_desc 967 968 def find_base(self, base_name): 969 # like self.bases[base_name], but returns None if not found 970 # (rather than raising exception) 971 return self.bases.get(base_name) 972 973 # internal helper function for concat[Some]Attr{Strings|Lists} 974 def __internalConcatAttrs(self, attr_name, filter, result): 975 for op_desc in self.items: 976 if filter(op_desc): 977 result += getattr(op_desc, attr_name) 978 return result 979 980 # return a single string that is the concatenation of the (string) 981 # values of the specified attribute for all operands 982 def concatAttrStrings(self, attr_name): 983 return self.__internalConcatAttrs(attr_name, lambda x: 1, '') 984 985 # like concatAttrStrings, but only include the values for the operands 986 # for which the provided filter function returns true 987 def concatSomeAttrStrings(self, filter, attr_name): 988 return self.__internalConcatAttrs(attr_name, filter, '') 989 990 # return a single list that is the concatenation of the (list) 991 # values of the specified attribute for all operands 992 def concatAttrLists(self, attr_name): 993 return self.__internalConcatAttrs(attr_name, lambda x: 1, []) 994 995 # like concatAttrLists, but only include the values for the operands 996 # for which the provided filter function returns true 997 def concatSomeAttrLists(self, filter, attr_name): 998 return self.__internalConcatAttrs(attr_name, filter, []) 999 1000 def sort(self): 1001 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri) 1002 1003class SubOperandList(OperandList): 1004 '''Find all the operands in the given code block. Returns an operand 1005 descriptor list (instance of class OperandList).''' 1006 def __init__(self, parser, code, master_list): 1007 self.items = [] 1008 self.bases = {} 1009 # delete strings and comments so we don't match on operands inside 1010 for regEx in (stringRE, commentRE): 1011 code = regEx.sub('', code) 1012 # search for operands 1013 next_pos = 0 1014 while 1: 1015 match = parser.operandsRE.search(code, next_pos) 1016 if not match: 1017 # no more matches: we're done 1018 break 1019 op = match.groups() 1020 # regexp groups are operand full name, base, and extension 1021 (op_full, op_base, op_ext) = op 1022 # find this op in the master list 1023 op_desc = master_list.find_base(op_base) 1024 if not op_desc: 1025 error('Found operand %s which is not in the master list!' \ 1026 ' This is an internal error' % op_base) 1027 else: 1028 # See if we've already found this operand 1029 op_desc = self.find_base(op_base) 1030 if not op_desc: 1031 # if not, add a reference to it to this sub list 1032 self.append(master_list.bases[op_base]) 1033 1034 # start next search after end of current match 1035 next_pos = match.end() 1036 self.sort() 1037 self.memOperand = None 1038 # Whether the whole PC needs to be read so parts of it can be accessed 1039 self.readPC = False 1040 # Whether the whole PC needs to be written after parts of it were 1041 # changed 1042 self.setPC = False 1043 # Whether this instruction manipulates the whole PC or parts of it. 1044 # Mixing the two is a bad idea and flagged as an error. 1045 self.pcPart = None 1046 1047 # Flags to keep track if one or more operands are to be read/written 1048 # conditionally. 1049 self.predRead = False 1050 self.predWrite = False 1051 1052 for op_desc in self.items: 1053 if op_desc.isPCPart(): 1054 self.readPC = True 1055 if op_desc.is_dest: 1056 self.setPC = True 1057 1058 if op_desc.isPCState(): 1059 if self.pcPart is not None: 1060 if self.pcPart and not op_desc.isPCPart() or \ 1061 not self.pcPart and op_desc.isPCPart(): 1062 error("Mixed whole and partial PC state operands.") 1063 self.pcPart = op_desc.isPCPart() 1064 1065 if op_desc.isMem(): 1066 if self.memOperand: 1067 error("Code block has more than one memory operand.") 1068 self.memOperand = op_desc 1069 1070 # Check if this operand has read/write predication. If true, then 1071 # the microop will dynamically index source/dest registers. 1072 self.predRead = self.predRead or op_desc.hasReadPred() 1073 self.predWrite = self.predWrite or op_desc.hasWritePred() 1074 1075# Regular expression object to match C++ strings 1076stringRE = re.compile(r'"([^"\\]|\\.)*"') 1077 1078# Regular expression object to match C++ comments 1079# (used in findOperands()) 1080commentRE = re.compile(r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?', 1081 re.DOTALL | re.MULTILINE) 1082 1083# Regular expression object to match assignment statements 1084# (used in findOperands()) 1085assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) 1086 1087def makeFlagConstructor(flag_list): 1088 if len(flag_list) == 0: 1089 return '' 1090 # filter out repeated flags 1091 flag_list.sort() 1092 i = 1 1093 while i < len(flag_list): 1094 if flag_list[i] == flag_list[i-1]: 1095 del flag_list[i] 1096 else: 1097 i += 1 1098 pre = '\n\tflags[' 1099 post = '] = true;' 1100 code = pre + string.join(flag_list, post + pre) + post 1101 return code 1102 1103# Assume all instruction flags are of the form 'IsFoo' 1104instFlagRE = re.compile(r'Is.*') 1105 1106# OpClass constants end in 'Op' except No_OpClass 1107opClassRE = re.compile(r'.*Op|No_OpClass') 1108 1109class InstObjParams(object): 1110 def __init__(self, parser, mnem, class_name, base_class = '', 1111 snippets = {}, opt_args = []): 1112 self.mnemonic = mnem 1113 self.class_name = class_name 1114 self.base_class = base_class 1115 if not isinstance(snippets, dict): 1116 snippets = {'code' : snippets} 1117 compositeCode = ' '.join(map(str, snippets.values())) 1118 self.snippets = snippets 1119 1120 self.operands = OperandList(parser, compositeCode) 1121 1122 # The header of the constructor declares the variables to be used 1123 # in the body of the constructor. 1124 header = '' 1125 header += '\n\t_numSrcRegs = 0;' 1126 header += '\n\t_numDestRegs = 0;' 1127 header += '\n\t_numFPDestRegs = 0;' 1128 header += '\n\t_numIntDestRegs = 0;' 1129 header += '\n\t_numCCDestRegs = 0;'
|
1239 header += '\n\t_numVectorDestRegs = 0;'
| |
1240 1241 self.constructor = header + \ 1242 self.operands.concatAttrStrings('constructor') 1243 1244 self.flags = self.operands.concatAttrLists('flags') 1245 1246 self.op_class = None 1247 1248 # Optional arguments are assumed to be either StaticInst flags 1249 # or an OpClass value. To avoid having to import a complete 1250 # list of these values to match against, we do it ad-hoc 1251 # with regexps. 1252 for oa in opt_args: 1253 if instFlagRE.match(oa): 1254 self.flags.append(oa) 1255 elif opClassRE.match(oa): 1256 self.op_class = oa 1257 else: 1258 error('InstObjParams: optional arg "%s" not recognized ' 1259 'as StaticInst::Flag or OpClass.' % oa) 1260 1261 # Make a basic guess on the operand class if not set. 1262 # These are good enough for most cases. 1263 if not self.op_class: 1264 if 'IsStore' in self.flags: 1265 self.op_class = 'MemWriteOp' 1266 elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags: 1267 self.op_class = 'MemReadOp' 1268 elif 'IsFloating' in self.flags: 1269 self.op_class = 'FloatAddOp' 1270 else: 1271 self.op_class = 'IntAluOp' 1272 1273 # add flag initialization to contructor here to include 1274 # any flags added via opt_args 1275 self.constructor += makeFlagConstructor(self.flags) 1276 1277 # if 'IsFloating' is set, add call to the FP enable check 1278 # function (which should be provided by isa_desc via a declare) 1279 if 'IsFloating' in self.flags: 1280 self.fp_enable_check = 'fault = checkFpEnableFault(xc);' 1281 else: 1282 self.fp_enable_check = '' 1283 1284############## 1285# Stack: a simple stack object. Used for both formats (formatStack) 1286# and default cases (defaultStack). Simply wraps a list to give more 1287# stack-like syntax and enable initialization with an argument list 1288# (as opposed to an argument that's a list). 1289 1290class Stack(list): 1291 def __init__(self, *items): 1292 list.__init__(self, items) 1293 1294 def push(self, item): 1295 self.append(item); 1296 1297 def top(self): 1298 return self[-1] 1299 1300####################### 1301# 1302# ISA Parser 1303# parses ISA DSL and emits C++ headers and source 1304# 1305 1306class ISAParser(Grammar): 1307 class CpuModel(object): 1308 def __init__(self, name, filename, includes, strings): 1309 self.name = name 1310 self.filename = filename 1311 self.includes = includes 1312 self.strings = strings 1313 1314 def __init__(self, output_dir): 1315 super(ISAParser, self).__init__() 1316 self.output_dir = output_dir 1317 1318 self.filename = None # for output file watermarking/scaremongering 1319 1320 self.cpuModels = [ 1321 ISAParser.CpuModel('ExecContext', 1322 'generic_cpu_exec.cc', 1323 '#include "cpu/exec_context.hh"', 1324 { "CPU_exec_context" : "ExecContext" }), 1325 ] 1326 1327 # variable to hold templates 1328 self.templateMap = {} 1329 1330 # This dictionary maps format name strings to Format objects. 1331 self.formatMap = {} 1332 1333 # Track open files and, if applicable, how many chunks it has been 1334 # split into so far. 1335 self.files = {} 1336 self.splits = {} 1337 1338 # isa_name / namespace identifier from namespace declaration. 1339 # before the namespace declaration, None. 1340 self.isa_name = None 1341 self.namespace = None 1342 1343 # The format stack. 1344 self.formatStack = Stack(NoFormat()) 1345 1346 # The default case stack. 1347 self.defaultStack = Stack(None) 1348 1349 # Stack that tracks current file and line number. Each 1350 # element is a tuple (filename, lineno) that records the 1351 # *current* filename and the line number in the *previous* 1352 # file where it was included. 1353 self.fileNameStack = Stack() 1354 1355 symbols = ('makeList', 're', 'string') 1356 self.exportContext = dict([(s, eval(s)) for s in symbols]) 1357 1358 self.maxInstSrcRegs = 0 1359 self.maxInstDestRegs = 0 1360 self.maxMiscDestRegs = 0 1361 1362 def __getitem__(self, i): # Allow object (self) to be 1363 return getattr(self, i) # passed to %-substitutions 1364 1365 # Change the file suffix of a base filename: 1366 # (e.g.) decoder.cc -> decoder-g.cc.inc for 'global' outputs 1367 def suffixize(self, s, sec): 1368 extn = re.compile('(\.[^\.]+)$') # isolate extension 1369 if self.namespace: 1370 return extn.sub(r'-ns\1.inc', s) # insert some text on either side 1371 else: 1372 return extn.sub(r'-g\1.inc', s) 1373 1374 # Get the file object for emitting code into the specified section 1375 # (header, decoder, exec, decode_block). 1376 def get_file(self, section): 1377 if section == 'decode_block': 1378 filename = 'decode-method.cc.inc' 1379 else: 1380 if section == 'header': 1381 file = 'decoder.hh' 1382 else: 1383 file = '%s.cc' % section 1384 filename = self.suffixize(file, section) 1385 try: 1386 return self.files[filename] 1387 except KeyError: pass 1388 1389 f = self.open(filename) 1390 self.files[filename] = f 1391 1392 # The splittable files are the ones with many independent 1393 # per-instruction functions - the decoder's instruction constructors 1394 # and the instruction execution (execute()) methods. These both have 1395 # the suffix -ns.cc.inc, meaning they are within the namespace part 1396 # of the ISA, contain object-emitting C++ source, and are included 1397 # into other top-level files. These are the files that need special 1398 # #define's to allow parts of them to be compiled separately. Rather 1399 # than splitting the emissions into separate files, the monolithic 1400 # output of the ISA parser is maintained, but the value (or lack 1401 # thereof) of the __SPLIT definition during C preprocessing will 1402 # select the different chunks. If no 'split' directives are used, 1403 # the cpp emissions have no effect. 1404 if re.search('-ns.cc.inc$', filename): 1405 print >>f, '#if !defined(__SPLIT) || (__SPLIT == 1)' 1406 self.splits[f] = 1 1407 # ensure requisite #include's 1408 elif filename in ['decoder-g.cc.inc', 'exec-g.cc.inc']: 1409 print >>f, '#include "decoder.hh"' 1410 elif filename == 'decoder-g.hh.inc': 1411 print >>f, '#include "base/bitfield.hh"' 1412 1413 return f 1414 1415 # Weave together the parts of the different output sections by 1416 # #include'ing them into some very short top-level .cc/.hh files. 1417 # These small files make it much clearer how this tool works, since 1418 # you directly see the chunks emitted as files that are #include'd. 1419 def write_top_level_files(self): 1420 dep = self.open('inc.d', bare=True) 1421 1422 # decoder header - everything depends on this 1423 file = 'decoder.hh' 1424 with self.open(file) as f: 1425 inc = [] 1426 1427 fn = 'decoder-g.hh.inc' 1428 assert(fn in self.files) 1429 f.write('#include "%s"\n' % fn) 1430 inc.append(fn) 1431 1432 fn = 'decoder-ns.hh.inc' 1433 assert(fn in self.files) 1434 f.write('namespace %s {\n#include "%s"\n}\n' 1435 % (self.namespace, fn)) 1436 inc.append(fn) 1437 1438 print >>dep, file+':', ' '.join(inc) 1439 1440 # decoder method - cannot be split 1441 file = 'decoder.cc' 1442 with self.open(file) as f: 1443 inc = [] 1444 1445 fn = 'decoder-g.cc.inc' 1446 assert(fn in self.files) 1447 f.write('#include "%s"\n' % fn) 1448 inc.append(fn) 1449 1450 fn = 'decode-method.cc.inc' 1451 # is guaranteed to have been written for parse to complete 1452 f.write('#include "%s"\n' % fn) 1453 inc.append(fn) 1454 1455 inc.append("decoder.hh") 1456 print >>dep, file+':', ' '.join(inc) 1457 1458 extn = re.compile('(\.[^\.]+)$') 1459 1460 # instruction constructors 1461 splits = self.splits[self.get_file('decoder')] 1462 file_ = 'inst-constrs.cc' 1463 for i in range(1, splits+1): 1464 if splits > 1: 1465 file = extn.sub(r'-%d\1' % i, file_) 1466 else: 1467 file = file_ 1468 with self.open(file) as f: 1469 inc = [] 1470 1471 fn = 'decoder-g.cc.inc' 1472 assert(fn in self.files) 1473 f.write('#include "%s"\n' % fn) 1474 inc.append(fn) 1475 1476 fn = 'decoder-ns.cc.inc' 1477 assert(fn in self.files) 1478 print >>f, 'namespace %s {' % self.namespace 1479 if splits > 1: 1480 print >>f, '#define __SPLIT %u' % i 1481 print >>f, '#include "%s"' % fn 1482 print >>f, '}' 1483 inc.append(fn) 1484 1485 inc.append("decoder.hh") 1486 print >>dep, file+':', ' '.join(inc) 1487 1488 # instruction execution per-CPU model 1489 splits = self.splits[self.get_file('exec')] 1490 for cpu in self.cpuModels: 1491 for i in range(1, splits+1): 1492 if splits > 1: 1493 file = extn.sub(r'_%d\1' % i, cpu.filename) 1494 else: 1495 file = cpu.filename 1496 with self.open(file) as f: 1497 inc = [] 1498 1499 fn = 'exec-g.cc.inc' 1500 assert(fn in self.files) 1501 f.write('#include "%s"\n' % fn) 1502 inc.append(fn) 1503 1504 f.write(cpu.includes+"\n") 1505 1506 fn = 'exec-ns.cc.inc' 1507 assert(fn in self.files) 1508 print >>f, 'namespace %s {' % self.namespace 1509 print >>f, '#define CPU_EXEC_CONTEXT %s' \ 1510 % cpu.strings['CPU_exec_context'] 1511 if splits > 1: 1512 print >>f, '#define __SPLIT %u' % i 1513 print >>f, '#include "%s"' % fn 1514 print >>f, '}' 1515 inc.append(fn) 1516 1517 inc.append("decoder.hh") 1518 print >>dep, file+':', ' '.join(inc) 1519 1520 # max_inst_regs.hh 1521 self.update('max_inst_regs.hh', 1522 '''namespace %(namespace)s { 1523 const int MaxInstSrcRegs = %(maxInstSrcRegs)d; 1524 const int MaxInstDestRegs = %(maxInstDestRegs)d; 1525 const int MaxMiscDestRegs = %(maxMiscDestRegs)d;\n}\n''' % self) 1526 print >>dep, 'max_inst_regs.hh:' 1527 1528 dep.close() 1529 1530 1531 scaremonger_template ='''// DO NOT EDIT 1532// This file was automatically generated from an ISA description: 1533// %(filename)s 1534 1535'''; 1536 1537 ##################################################################### 1538 # 1539 # Lexer 1540 # 1541 # The PLY lexer module takes two things as input: 1542 # - A list of token names (the string list 'tokens') 1543 # - A regular expression describing a match for each token. The 1544 # regexp for token FOO can be provided in two ways: 1545 # - as a string variable named t_FOO 1546 # - as the doc string for a function named t_FOO. In this case, 1547 # the function is also executed, allowing an action to be 1548 # associated with each token match. 1549 # 1550 ##################################################################### 1551 1552 # Reserved words. These are listed separately as they are matched 1553 # using the same regexp as generic IDs, but distinguished in the 1554 # t_ID() function. The PLY documentation suggests this approach. 1555 reserved = ( 1556 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT', 1557 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS', 1558 'OUTPUT', 'SIGNED', 'SPLIT', 'TEMPLATE' 1559 ) 1560 1561 # List of tokens. The lex module requires this. 1562 tokens = reserved + ( 1563 # identifier 1564 'ID', 1565 1566 # integer literal 1567 'INTLIT', 1568 1569 # string literal 1570 'STRLIT', 1571 1572 # code literal 1573 'CODELIT', 1574 1575 # ( ) [ ] { } < > , ; . : :: * 1576 'LPAREN', 'RPAREN', 1577 'LBRACKET', 'RBRACKET', 1578 'LBRACE', 'RBRACE', 1579 'LESS', 'GREATER', 'EQUALS', 1580 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON', 1581 'ASTERISK', 1582 1583 # C preprocessor directives 1584 'CPPDIRECTIVE' 1585 1586 # The following are matched but never returned. commented out to 1587 # suppress PLY warning 1588 # newfile directive 1589 # 'NEWFILE', 1590 1591 # endfile directive 1592 # 'ENDFILE' 1593 ) 1594 1595 # Regular expressions for token matching 1596 t_LPAREN = r'\(' 1597 t_RPAREN = r'\)' 1598 t_LBRACKET = r'\[' 1599 t_RBRACKET = r'\]' 1600 t_LBRACE = r'\{' 1601 t_RBRACE = r'\}' 1602 t_LESS = r'\<' 1603 t_GREATER = r'\>' 1604 t_EQUALS = r'=' 1605 t_COMMA = r',' 1606 t_SEMI = r';' 1607 t_DOT = r'\.' 1608 t_COLON = r':' 1609 t_DBLCOLON = r'::' 1610 t_ASTERISK = r'\*' 1611 1612 # Identifiers and reserved words 1613 reserved_map = { } 1614 for r in reserved: 1615 reserved_map[r.lower()] = r 1616 1617 def t_ID(self, t): 1618 r'[A-Za-z_]\w*' 1619 t.type = self.reserved_map.get(t.value, 'ID') 1620 return t 1621 1622 # Integer literal 1623 def t_INTLIT(self, t): 1624 r'-?(0x[\da-fA-F]+)|\d+' 1625 try: 1626 t.value = int(t.value,0) 1627 except ValueError: 1628 error(t, 'Integer value "%s" too large' % t.value) 1629 t.value = 0 1630 return t 1631 1632 # String literal. Note that these use only single quotes, and 1633 # can span multiple lines. 1634 def t_STRLIT(self, t): 1635 r"(?m)'([^'])+'" 1636 # strip off quotes 1637 t.value = t.value[1:-1] 1638 t.lexer.lineno += t.value.count('\n') 1639 return t 1640 1641 1642 # "Code literal"... like a string literal, but delimiters are 1643 # '{{' and '}}' so they get formatted nicely under emacs c-mode 1644 def t_CODELIT(self, t): 1645 r"(?m)\{\{([^\}]|}(?!\}))+\}\}" 1646 # strip off {{ & }} 1647 t.value = t.value[2:-2] 1648 t.lexer.lineno += t.value.count('\n') 1649 return t 1650 1651 def t_CPPDIRECTIVE(self, t): 1652 r'^\#[^\#].*\n' 1653 t.lexer.lineno += t.value.count('\n') 1654 return t 1655 1656 def t_NEWFILE(self, t): 1657 r'^\#\#newfile\s+"[^"]*"' 1658 self.fileNameStack.push((t.value[11:-1], t.lexer.lineno)) 1659 t.lexer.lineno = 0 1660 1661 def t_ENDFILE(self, t): 1662 r'^\#\#endfile' 1663 (old_filename, t.lexer.lineno) = self.fileNameStack.pop() 1664 1665 # 1666 # The functions t_NEWLINE, t_ignore, and t_error are 1667 # special for the lex module. 1668 # 1669 1670 # Newlines 1671 def t_NEWLINE(self, t): 1672 r'\n+' 1673 t.lexer.lineno += t.value.count('\n') 1674 1675 # Comments 1676 def t_comment(self, t): 1677 r'//.*' 1678 1679 # Completely ignored characters 1680 t_ignore = ' \t\x0c' 1681 1682 # Error handler 1683 def t_error(self, t): 1684 error(t, "illegal character '%s'" % t.value[0]) 1685 t.skip(1) 1686 1687 ##################################################################### 1688 # 1689 # Parser 1690 # 1691 # Every function whose name starts with 'p_' defines a grammar 1692 # rule. The rule is encoded in the function's doc string, while 1693 # the function body provides the action taken when the rule is 1694 # matched. The argument to each function is a list of the values 1695 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the 1696 # symbols on the RHS. For tokens, the value is copied from the 1697 # t.value attribute provided by the lexer. For non-terminals, the 1698 # value is assigned by the producing rule; i.e., the job of the 1699 # grammar rule function is to set the value for the non-terminal 1700 # on the LHS (by assigning to t[0]). 1701 ##################################################################### 1702 1703 # The LHS of the first grammar rule is used as the start symbol 1704 # (in this case, 'specification'). Note that this rule enforces 1705 # that there will be exactly one namespace declaration, with 0 or 1706 # more global defs/decls before and after it. The defs & decls 1707 # before the namespace decl will be outside the namespace; those 1708 # after will be inside. The decoder function is always inside the 1709 # namespace. 1710 def p_specification(self, t): 1711 'specification : opt_defs_and_outputs top_level_decode_block' 1712 1713 for f in self.splits.iterkeys(): 1714 f.write('\n#endif\n') 1715 1716 for f in self.files.itervalues(): # close ALL the files; 1717 f.close() # not doing so can cause compilation to fail 1718 1719 self.write_top_level_files() 1720 1721 t[0] = True 1722 1723 # 'opt_defs_and_outputs' is a possibly empty sequence of def and/or 1724 # output statements. Its productions do the hard work of eventually 1725 # instantiating a GenCode, which are generally emitted (written to disk) 1726 # as soon as possible, except for the decode_block, which has to be 1727 # accumulated into one large function of nested switch/case blocks. 1728 def p_opt_defs_and_outputs_0(self, t): 1729 'opt_defs_and_outputs : empty' 1730 1731 def p_opt_defs_and_outputs_1(self, t): 1732 'opt_defs_and_outputs : defs_and_outputs' 1733 1734 def p_defs_and_outputs_0(self, t): 1735 'defs_and_outputs : def_or_output' 1736 1737 def p_defs_and_outputs_1(self, t): 1738 'defs_and_outputs : defs_and_outputs def_or_output' 1739 1740 # The list of possible definition/output statements. 1741 # They are all processed as they are seen. 1742 def p_def_or_output(self, t): 1743 '''def_or_output : name_decl 1744 | def_format 1745 | def_bitfield 1746 | def_bitfield_struct 1747 | def_template 1748 | def_operand_types 1749 | def_operands 1750 | output 1751 | global_let 1752 | split''' 1753 1754 # Utility function used by both invocations of splitting - explicit 1755 # 'split' keyword and split() function inside "let {{ }};" blocks. 1756 def split(self, sec, write=False): 1757 assert(sec != 'header' and "header cannot be split") 1758 1759 f = self.get_file(sec) 1760 self.splits[f] += 1 1761 s = '\n#endif\n#if __SPLIT == %u\n' % self.splits[f] 1762 if write: 1763 f.write(s) 1764 else: 1765 return s 1766 1767 # split output file to reduce compilation time 1768 def p_split(self, t): 1769 'split : SPLIT output_type SEMI' 1770 assert(self.isa_name and "'split' not allowed before namespace decl") 1771 1772 self.split(t[2], True) 1773 1774 def p_output_type(self, t): 1775 '''output_type : DECODER 1776 | HEADER 1777 | EXEC''' 1778 t[0] = t[1] 1779 1780 # ISA name declaration looks like "namespace <foo>;" 1781 def p_name_decl(self, t): 1782 'name_decl : NAMESPACE ID SEMI' 1783 assert(self.isa_name == None and "Only 1 namespace decl permitted") 1784 self.isa_name = t[2] 1785 self.namespace = t[2] + 'Inst' 1786 1787 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied 1788 # directly to the appropriate output section. 1789 1790 # Massage output block by substituting in template definitions and 1791 # bit operators. We handle '%'s embedded in the string that don't 1792 # indicate template substitutions (or CPU-specific symbols, which 1793 # get handled in GenCode) by doubling them first so that the 1794 # format operation will reduce them back to single '%'s. 1795 def process_output(self, s): 1796 s = self.protectNonSubstPercents(s) 1797 # protects cpu-specific symbols too 1798 s = self.protectCpuSymbols(s) 1799 return substBitOps(s % self.templateMap) 1800 1801 def p_output(self, t): 1802 'output : OUTPUT output_type CODELIT SEMI' 1803 kwargs = { t[2]+'_output' : self.process_output(t[3]) } 1804 GenCode(self, **kwargs).emit() 1805 1806 # global let blocks 'let {{...}}' (Python code blocks) are 1807 # executed directly when seen. Note that these execute in a 1808 # special variable context 'exportContext' to prevent the code 1809 # from polluting this script's namespace. 1810 def p_global_let(self, t): 1811 'global_let : LET CODELIT SEMI' 1812 def _split(sec): 1813 return self.split(sec) 1814 self.updateExportContext() 1815 self.exportContext["header_output"] = '' 1816 self.exportContext["decoder_output"] = '' 1817 self.exportContext["exec_output"] = '' 1818 self.exportContext["decode_block"] = '' 1819 self.exportContext["split"] = _split 1820 split_setup = ''' 1821def wrap(func): 1822 def split(sec): 1823 globals()[sec + '_output'] += func(sec) 1824 return split 1825split = wrap(split) 1826del wrap 1827''' 1828 # This tricky setup (immediately above) allows us to just write 1829 # (e.g.) "split('exec')" in the Python code and the split #ifdef's 1830 # will automatically be added to the exec_output variable. The inner 1831 # Python execution environment doesn't know about the split points, 1832 # so we carefully inject and wrap a closure that can retrieve the 1833 # next split's #define from the parser and add it to the current 1834 # emission-in-progress. 1835 try: 1836 exec split_setup+fixPythonIndentation(t[2]) in self.exportContext 1837 except Exception, exc: 1838 if debug: 1839 raise 1840 error(t, 'error: %s in global let block "%s".' % (exc, t[2])) 1841 GenCode(self, 1842 header_output=self.exportContext["header_output"], 1843 decoder_output=self.exportContext["decoder_output"], 1844 exec_output=self.exportContext["exec_output"], 1845 decode_block=self.exportContext["decode_block"]).emit() 1846 1847 # Define the mapping from operand type extensions to C++ types and 1848 # bit widths (stored in operandTypeMap). 1849 def p_def_operand_types(self, t): 1850 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' 1851 try: 1852 self.operandTypeMap = eval('{' + t[3] + '}') 1853 except Exception, exc: 1854 if debug: 1855 raise 1856 error(t, 1857 'error: %s in def operand_types block "%s".' % (exc, t[3])) 1858 1859 # Define the mapping from operand names to operand classes and 1860 # other traits. Stored in operandNameMap. 1861 def p_def_operands(self, t): 1862 'def_operands : DEF OPERANDS CODELIT SEMI' 1863 if not hasattr(self, 'operandTypeMap'): 1864 error(t, 'error: operand types must be defined before operands') 1865 try: 1866 user_dict = eval('{' + t[3] + '}', self.exportContext) 1867 except Exception, exc: 1868 if debug: 1869 raise 1870 error(t, 'error: %s in def operands block "%s".' % (exc, t[3])) 1871 self.buildOperandNameMap(user_dict, t.lexer.lineno) 1872 1873 # A bitfield definition looks like: 1874 # 'def [signed] bitfield <ID> [<first>:<last>]' 1875 # This generates a preprocessor macro in the output file. 1876 def p_def_bitfield_0(self, t): 1877 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' 1878 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) 1879 if (t[2] == 'signed'): 1880 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr) 1881 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 1882 GenCode(self, header_output=hash_define).emit() 1883 1884 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]' 1885 def p_def_bitfield_1(self, t): 1886 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI' 1887 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6]) 1888 if (t[2] == 'signed'): 1889 expr = 'sext<%d>(%s)' % (1, expr) 1890 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 1891 GenCode(self, header_output=hash_define).emit() 1892 1893 # alternate form for structure member: 'def bitfield <ID> <ID>' 1894 def p_def_bitfield_struct(self, t): 1895 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' 1896 if (t[2] != ''): 1897 error(t, 'error: structure bitfields are always unsigned.') 1898 expr = 'machInst.%s' % t[5] 1899 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 1900 GenCode(self, header_output=hash_define).emit() 1901 1902 def p_id_with_dot_0(self, t): 1903 'id_with_dot : ID' 1904 t[0] = t[1] 1905 1906 def p_id_with_dot_1(self, t): 1907 'id_with_dot : ID DOT id_with_dot' 1908 t[0] = t[1] + t[2] + t[3] 1909 1910 def p_opt_signed_0(self, t): 1911 'opt_signed : SIGNED' 1912 t[0] = t[1] 1913 1914 def p_opt_signed_1(self, t): 1915 'opt_signed : empty' 1916 t[0] = '' 1917 1918 def p_def_template(self, t): 1919 'def_template : DEF TEMPLATE ID CODELIT SEMI' 1920 if t[3] in self.templateMap: 1921 print "warning: template %s already defined" % t[3] 1922 self.templateMap[t[3]] = Template(self, t[4]) 1923 1924 # An instruction format definition looks like 1925 # "def format <fmt>(<params>) {{...}};" 1926 def p_def_format(self, t): 1927 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' 1928 (id, params, code) = (t[3], t[5], t[7]) 1929 self.defFormat(id, params, code, t.lexer.lineno) 1930 1931 # The formal parameter list for an instruction format is a 1932 # possibly empty list of comma-separated parameters. Positional 1933 # (standard, non-keyword) parameters must come first, followed by 1934 # keyword parameters, followed by a '*foo' parameter that gets 1935 # excess positional arguments (as in Python). Each of these three 1936 # parameter categories is optional. 1937 # 1938 # Note that we do not support the '**foo' parameter for collecting 1939 # otherwise undefined keyword args. Otherwise the parameter list 1940 # is (I believe) identical to what is supported in Python. 1941 # 1942 # The param list generates a tuple, where the first element is a 1943 # list of the positional params and the second element is a dict 1944 # containing the keyword params. 1945 def p_param_list_0(self, t): 1946 'param_list : positional_param_list COMMA nonpositional_param_list' 1947 t[0] = t[1] + t[3] 1948 1949 def p_param_list_1(self, t): 1950 '''param_list : positional_param_list 1951 | nonpositional_param_list''' 1952 t[0] = t[1] 1953 1954 def p_positional_param_list_0(self, t): 1955 'positional_param_list : empty' 1956 t[0] = [] 1957 1958 def p_positional_param_list_1(self, t): 1959 'positional_param_list : ID' 1960 t[0] = [t[1]] 1961 1962 def p_positional_param_list_2(self, t): 1963 'positional_param_list : positional_param_list COMMA ID' 1964 t[0] = t[1] + [t[3]] 1965 1966 def p_nonpositional_param_list_0(self, t): 1967 'nonpositional_param_list : keyword_param_list COMMA excess_args_param' 1968 t[0] = t[1] + t[3] 1969 1970 def p_nonpositional_param_list_1(self, t): 1971 '''nonpositional_param_list : keyword_param_list 1972 | excess_args_param''' 1973 t[0] = t[1] 1974 1975 def p_keyword_param_list_0(self, t): 1976 'keyword_param_list : keyword_param' 1977 t[0] = [t[1]] 1978 1979 def p_keyword_param_list_1(self, t): 1980 'keyword_param_list : keyword_param_list COMMA keyword_param' 1981 t[0] = t[1] + [t[3]] 1982 1983 def p_keyword_param(self, t): 1984 'keyword_param : ID EQUALS expr' 1985 t[0] = t[1] + ' = ' + t[3].__repr__() 1986 1987 def p_excess_args_param(self, t): 1988 'excess_args_param : ASTERISK ID' 1989 # Just concatenate them: '*ID'. Wrap in list to be consistent 1990 # with positional_param_list and keyword_param_list. 1991 t[0] = [t[1] + t[2]] 1992 1993 # End of format definition-related rules. 1994 ############## 1995 1996 # 1997 # A decode block looks like: 1998 # decode <field1> [, <field2>]* [default <inst>] { ... } 1999 # 2000 def p_top_level_decode_block(self, t): 2001 'top_level_decode_block : decode_block' 2002 codeObj = t[1] 2003 codeObj.wrap_decode_block(''' 2004StaticInstPtr 2005%(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst) 2006{ 2007 using namespace %(namespace)s; 2008''' % self, '}') 2009 2010 codeObj.emit() 2011 2012 def p_decode_block(self, t): 2013 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' 2014 default_defaults = self.defaultStack.pop() 2015 codeObj = t[5] 2016 # use the "default defaults" only if there was no explicit 2017 # default statement in decode_stmt_list 2018 if not codeObj.has_decode_default: 2019 codeObj += default_defaults 2020 codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n') 2021 t[0] = codeObj 2022 2023 # The opt_default statement serves only to push the "default 2024 # defaults" onto defaultStack. This value will be used by nested 2025 # decode blocks, and used and popped off when the current 2026 # decode_block is processed (in p_decode_block() above). 2027 def p_opt_default_0(self, t): 2028 'opt_default : empty' 2029 # no default specified: reuse the one currently at the top of 2030 # the stack 2031 self.defaultStack.push(self.defaultStack.top()) 2032 # no meaningful value returned 2033 t[0] = None 2034 2035 def p_opt_default_1(self, t): 2036 'opt_default : DEFAULT inst' 2037 # push the new default 2038 codeObj = t[2] 2039 codeObj.wrap_decode_block('\ndefault:\n', 'break;\n') 2040 self.defaultStack.push(codeObj) 2041 # no meaningful value returned 2042 t[0] = None 2043 2044 def p_decode_stmt_list_0(self, t): 2045 'decode_stmt_list : decode_stmt' 2046 t[0] = t[1] 2047 2048 def p_decode_stmt_list_1(self, t): 2049 'decode_stmt_list : decode_stmt decode_stmt_list' 2050 if (t[1].has_decode_default and t[2].has_decode_default): 2051 error(t, 'Two default cases in decode block') 2052 t[0] = t[1] + t[2] 2053 2054 # 2055 # Decode statement rules 2056 # 2057 # There are four types of statements allowed in a decode block: 2058 # 1. Format blocks 'format <foo> { ... }' 2059 # 2. Nested decode blocks 2060 # 3. Instruction definitions. 2061 # 4. C preprocessor directives. 2062 2063 2064 # Preprocessor directives found in a decode statement list are 2065 # passed through to the output, replicated to all of the output 2066 # code streams. This works well for ifdefs, so we can ifdef out 2067 # both the declarations and the decode cases generated by an 2068 # instruction definition. Handling them as part of the grammar 2069 # makes it easy to keep them in the right place with respect to 2070 # the code generated by the other statements. 2071 def p_decode_stmt_cpp(self, t): 2072 'decode_stmt : CPPDIRECTIVE' 2073 t[0] = GenCode(self, t[1], t[1], t[1], t[1]) 2074 2075 # A format block 'format <foo> { ... }' sets the default 2076 # instruction format used to handle instruction definitions inside 2077 # the block. This format can be overridden by using an explicit 2078 # format on the instruction definition or with a nested format 2079 # block. 2080 def p_decode_stmt_format(self, t): 2081 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE' 2082 # The format will be pushed on the stack when 'push_format_id' 2083 # is processed (see below). Once the parser has recognized 2084 # the full production (though the right brace), we're done 2085 # with the format, so now we can pop it. 2086 self.formatStack.pop() 2087 t[0] = t[4] 2088 2089 # This rule exists so we can set the current format (& push the 2090 # stack) when we recognize the format name part of the format 2091 # block. 2092 def p_push_format_id(self, t): 2093 'push_format_id : ID' 2094 try: 2095 self.formatStack.push(self.formatMap[t[1]]) 2096 t[0] = ('', '// format %s' % t[1]) 2097 except KeyError: 2098 error(t, 'instruction format "%s" not defined.' % t[1]) 2099 2100 # Nested decode block: if the value of the current field matches 2101 # the specified constant(s), do a nested decode on some other field. 2102 def p_decode_stmt_decode(self, t): 2103 'decode_stmt : case_list COLON decode_block' 2104 case_list = t[1] 2105 codeObj = t[3] 2106 # just wrap the decoding code from the block as a case in the 2107 # outer switch statement. 2108 codeObj.wrap_decode_block('\n%s\n' % ''.join(case_list)) 2109 codeObj.has_decode_default = (case_list == ['default:']) 2110 t[0] = codeObj 2111 2112 # Instruction definition (finally!). 2113 def p_decode_stmt_inst(self, t): 2114 'decode_stmt : case_list COLON inst SEMI' 2115 case_list = t[1] 2116 codeObj = t[3] 2117 codeObj.wrap_decode_block('\n%s' % ''.join(case_list), 'break;\n') 2118 codeObj.has_decode_default = (case_list == ['default:']) 2119 t[0] = codeObj 2120 2121 # The constant list for a decode case label must be non-empty, and must 2122 # either be the keyword 'default', or made up of one or more 2123 # comma-separated integer literals or strings which evaluate to 2124 # constants when compiled as C++. 2125 def p_case_list_0(self, t): 2126 'case_list : DEFAULT' 2127 t[0] = ['default:'] 2128 2129 def prep_int_lit_case_label(self, lit): 2130 if lit >= 2**32: 2131 return 'case ULL(%#x): ' % lit 2132 else: 2133 return 'case %#x: ' % lit 2134 2135 def prep_str_lit_case_label(self, lit): 2136 return 'case %s: ' % lit 2137 2138 def p_case_list_1(self, t): 2139 'case_list : INTLIT' 2140 t[0] = [self.prep_int_lit_case_label(t[1])] 2141 2142 def p_case_list_2(self, t): 2143 'case_list : STRLIT' 2144 t[0] = [self.prep_str_lit_case_label(t[1])] 2145 2146 def p_case_list_3(self, t): 2147 'case_list : case_list COMMA INTLIT' 2148 t[0] = t[1] 2149 t[0].append(self.prep_int_lit_case_label(t[3])) 2150 2151 def p_case_list_4(self, t): 2152 'case_list : case_list COMMA STRLIT' 2153 t[0] = t[1] 2154 t[0].append(self.prep_str_lit_case_label(t[3])) 2155 2156 # Define an instruction using the current instruction format 2157 # (specified by an enclosing format block). 2158 # "<mnemonic>(<args>)" 2159 def p_inst_0(self, t): 2160 'inst : ID LPAREN arg_list RPAREN' 2161 # Pass the ID and arg list to the current format class to deal with. 2162 currentFormat = self.formatStack.top() 2163 codeObj = currentFormat.defineInst(self, t[1], t[3], t.lexer.lineno) 2164 args = ','.join(map(str, t[3])) 2165 args = re.sub('(?m)^', '//', args) 2166 args = re.sub('^//', '', args) 2167 comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args) 2168 codeObj.prepend_all(comment) 2169 t[0] = codeObj 2170 2171 # Define an instruction using an explicitly specified format: 2172 # "<fmt>::<mnemonic>(<args>)" 2173 def p_inst_1(self, t): 2174 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN' 2175 try: 2176 format = self.formatMap[t[1]] 2177 except KeyError: 2178 error(t, 'instruction format "%s" not defined.' % t[1]) 2179 2180 codeObj = format.defineInst(self, t[3], t[5], t.lexer.lineno) 2181 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5]) 2182 codeObj.prepend_all(comment) 2183 t[0] = codeObj 2184 2185 # The arg list generates a tuple, where the first element is a 2186 # list of the positional args and the second element is a dict 2187 # containing the keyword args. 2188 def p_arg_list_0(self, t): 2189 'arg_list : positional_arg_list COMMA keyword_arg_list' 2190 t[0] = ( t[1], t[3] ) 2191 2192 def p_arg_list_1(self, t): 2193 'arg_list : positional_arg_list' 2194 t[0] = ( t[1], {} ) 2195 2196 def p_arg_list_2(self, t): 2197 'arg_list : keyword_arg_list' 2198 t[0] = ( [], t[1] ) 2199 2200 def p_positional_arg_list_0(self, t): 2201 'positional_arg_list : empty' 2202 t[0] = [] 2203 2204 def p_positional_arg_list_1(self, t): 2205 'positional_arg_list : expr' 2206 t[0] = [t[1]] 2207 2208 def p_positional_arg_list_2(self, t): 2209 'positional_arg_list : positional_arg_list COMMA expr' 2210 t[0] = t[1] + [t[3]] 2211 2212 def p_keyword_arg_list_0(self, t): 2213 'keyword_arg_list : keyword_arg' 2214 t[0] = t[1] 2215 2216 def p_keyword_arg_list_1(self, t): 2217 'keyword_arg_list : keyword_arg_list COMMA keyword_arg' 2218 t[0] = t[1] 2219 t[0].update(t[3]) 2220 2221 def p_keyword_arg(self, t): 2222 'keyword_arg : ID EQUALS expr' 2223 t[0] = { t[1] : t[3] } 2224 2225 # 2226 # Basic expressions. These constitute the argument values of 2227 # "function calls" (i.e. instruction definitions in the decode 2228 # block) and default values for formal parameters of format 2229 # functions. 2230 # 2231 # Right now, these are either strings, integers, or (recursively) 2232 # lists of exprs (using Python square-bracket list syntax). Note 2233 # that bare identifiers are trated as string constants here (since 2234 # there isn't really a variable namespace to refer to). 2235 # 2236 def p_expr_0(self, t): 2237 '''expr : ID 2238 | INTLIT 2239 | STRLIT 2240 | CODELIT''' 2241 t[0] = t[1] 2242 2243 def p_expr_1(self, t): 2244 '''expr : LBRACKET list_expr RBRACKET''' 2245 t[0] = t[2] 2246 2247 def p_list_expr_0(self, t): 2248 'list_expr : expr' 2249 t[0] = [t[1]] 2250 2251 def p_list_expr_1(self, t): 2252 'list_expr : list_expr COMMA expr' 2253 t[0] = t[1] + [t[3]] 2254 2255 def p_list_expr_2(self, t): 2256 'list_expr : empty' 2257 t[0] = [] 2258 2259 # 2260 # Empty production... use in other rules for readability. 2261 # 2262 def p_empty(self, t): 2263 'empty :' 2264 pass 2265 2266 # Parse error handler. Note that the argument here is the 2267 # offending *token*, not a grammar symbol (hence the need to use 2268 # t.value) 2269 def p_error(self, t): 2270 if t: 2271 error(t, "syntax error at '%s'" % t.value) 2272 else: 2273 error("unknown syntax error") 2274 2275 # END OF GRAMMAR RULES 2276 2277 def updateExportContext(self): 2278 2279 # create a continuation that allows us to grab the current parser 2280 def wrapInstObjParams(*args): 2281 return InstObjParams(self, *args) 2282 self.exportContext['InstObjParams'] = wrapInstObjParams 2283 self.exportContext.update(self.templateMap) 2284 2285 def defFormat(self, id, params, code, lineno): 2286 '''Define a new format''' 2287 2288 # make sure we haven't already defined this one 2289 if id in self.formatMap: 2290 error(lineno, 'format %s redefined.' % id) 2291 2292 # create new object and store in global map 2293 self.formatMap[id] = Format(id, params, code) 2294 2295 def expandCpuSymbolsToDict(self, template): 2296 '''Expand template with CPU-specific references into a 2297 dictionary with an entry for each CPU model name. The entry 2298 key is the model name and the corresponding value is the 2299 template with the CPU-specific refs substituted for that 2300 model.''' 2301 2302 # Protect '%'s that don't go with CPU-specific terms 2303 t = re.sub(r'%(?!\(CPU_)', '%%', template) 2304 result = {} 2305 for cpu in self.cpuModels: 2306 result[cpu.name] = t % cpu.strings 2307 return result 2308 2309 def expandCpuSymbolsToString(self, template): 2310 '''*If* the template has CPU-specific references, return a 2311 single string containing a copy of the template for each CPU 2312 model with the corresponding values substituted in. If the 2313 template has no CPU-specific references, it is returned 2314 unmodified.''' 2315 2316 if template.find('%(CPU_') != -1: 2317 return reduce(lambda x,y: x+y, 2318 self.expandCpuSymbolsToDict(template).values()) 2319 else: 2320 return template 2321 2322 def protectCpuSymbols(self, template): 2323 '''Protect CPU-specific references by doubling the 2324 corresponding '%'s (in preparation for substituting a different 2325 set of references into the template).''' 2326 2327 return re.sub(r'%(?=\(CPU_)', '%%', template) 2328 2329 def protectNonSubstPercents(self, s): 2330 '''Protect any non-dict-substitution '%'s in a format string 2331 (i.e. those not followed by '(')''' 2332 2333 return re.sub(r'%(?!\()', '%%', s) 2334 2335 def buildOperandNameMap(self, user_dict, lineno): 2336 operand_name = {} 2337 for op_name, val in user_dict.iteritems(): 2338 2339 # Check if extra attributes have been specified. 2340 if len(val) > 9: 2341 error(lineno, 'error: too many attributes for operand "%s"' % 2342 base_cls_name) 2343 2344 # Pad val with None in case optional args are missing 2345 val += (None, None, None, None) 2346 base_cls_name, dflt_ext, reg_spec, flags, sort_pri, \ 2347 read_code, write_code, read_predicate, write_predicate = val[:9] 2348 2349 # Canonical flag structure is a triple of lists, where each list 2350 # indicates the set of flags implied by this operand always, when 2351 # used as a source, and when used as a dest, respectively. 2352 # For simplicity this can be initialized using a variety of fairly 2353 # obvious shortcuts; we convert these to canonical form here. 2354 if not flags: 2355 # no flags specified (e.g., 'None') 2356 flags = ( [], [], [] ) 2357 elif isinstance(flags, str): 2358 # a single flag: assumed to be unconditional 2359 flags = ( [ flags ], [], [] ) 2360 elif isinstance(flags, list): 2361 # a list of flags: also assumed to be unconditional 2362 flags = ( flags, [], [] ) 2363 elif isinstance(flags, tuple): 2364 # it's a tuple: it should be a triple, 2365 # but each item could be a single string or a list 2366 (uncond_flags, src_flags, dest_flags) = flags 2367 flags = (makeList(uncond_flags), 2368 makeList(src_flags), makeList(dest_flags)) 2369 2370 # Accumulate attributes of new operand class in tmp_dict 2371 tmp_dict = {} 2372 attrList = ['reg_spec', 'flags', 'sort_pri', 2373 'read_code', 'write_code', 2374 'read_predicate', 'write_predicate'] 2375 if dflt_ext: 2376 dflt_ctype = self.operandTypeMap[dflt_ext] 2377 attrList.extend(['dflt_ctype', 'dflt_ext']) 2378 for attr in attrList: 2379 tmp_dict[attr] = eval(attr) 2380 tmp_dict['base_name'] = op_name 2381 2382 # New class name will be e.g. "IntReg_Ra" 2383 cls_name = base_cls_name + '_' + op_name 2384 # Evaluate string arg to get class object. Note that the 2385 # actual base class for "IntReg" is "IntRegOperand", i.e. we 2386 # have to append "Operand". 2387 try: 2388 base_cls = eval(base_cls_name + 'Operand') 2389 except NameError: 2390 error(lineno, 2391 'error: unknown operand base class "%s"' % base_cls_name) 2392 # The following statement creates a new class called 2393 # <cls_name> as a subclass of <base_cls> with the attributes 2394 # in tmp_dict, just as if we evaluated a class declaration. 2395 operand_name[op_name] = type(cls_name, (base_cls,), tmp_dict) 2396 2397 self.operandNameMap = operand_name 2398 2399 # Define operand variables. 2400 operands = user_dict.keys() 2401 extensions = self.operandTypeMap.keys() 2402 2403 operandsREString = r''' 2404 (?<!\w) # neg. lookbehind assertion: prevent partial matches
| 1130 1131 self.constructor = header + \ 1132 self.operands.concatAttrStrings('constructor') 1133 1134 self.flags = self.operands.concatAttrLists('flags') 1135 1136 self.op_class = None 1137 1138 # Optional arguments are assumed to be either StaticInst flags 1139 # or an OpClass value. To avoid having to import a complete 1140 # list of these values to match against, we do it ad-hoc 1141 # with regexps. 1142 for oa in opt_args: 1143 if instFlagRE.match(oa): 1144 self.flags.append(oa) 1145 elif opClassRE.match(oa): 1146 self.op_class = oa 1147 else: 1148 error('InstObjParams: optional arg "%s" not recognized ' 1149 'as StaticInst::Flag or OpClass.' % oa) 1150 1151 # Make a basic guess on the operand class if not set. 1152 # These are good enough for most cases. 1153 if not self.op_class: 1154 if 'IsStore' in self.flags: 1155 self.op_class = 'MemWriteOp' 1156 elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags: 1157 self.op_class = 'MemReadOp' 1158 elif 'IsFloating' in self.flags: 1159 self.op_class = 'FloatAddOp' 1160 else: 1161 self.op_class = 'IntAluOp' 1162 1163 # add flag initialization to contructor here to include 1164 # any flags added via opt_args 1165 self.constructor += makeFlagConstructor(self.flags) 1166 1167 # if 'IsFloating' is set, add call to the FP enable check 1168 # function (which should be provided by isa_desc via a declare) 1169 if 'IsFloating' in self.flags: 1170 self.fp_enable_check = 'fault = checkFpEnableFault(xc);' 1171 else: 1172 self.fp_enable_check = '' 1173 1174############## 1175# Stack: a simple stack object. Used for both formats (formatStack) 1176# and default cases (defaultStack). Simply wraps a list to give more 1177# stack-like syntax and enable initialization with an argument list 1178# (as opposed to an argument that's a list). 1179 1180class Stack(list): 1181 def __init__(self, *items): 1182 list.__init__(self, items) 1183 1184 def push(self, item): 1185 self.append(item); 1186 1187 def top(self): 1188 return self[-1] 1189 1190####################### 1191# 1192# ISA Parser 1193# parses ISA DSL and emits C++ headers and source 1194# 1195 1196class ISAParser(Grammar): 1197 class CpuModel(object): 1198 def __init__(self, name, filename, includes, strings): 1199 self.name = name 1200 self.filename = filename 1201 self.includes = includes 1202 self.strings = strings 1203 1204 def __init__(self, output_dir): 1205 super(ISAParser, self).__init__() 1206 self.output_dir = output_dir 1207 1208 self.filename = None # for output file watermarking/scaremongering 1209 1210 self.cpuModels = [ 1211 ISAParser.CpuModel('ExecContext', 1212 'generic_cpu_exec.cc', 1213 '#include "cpu/exec_context.hh"', 1214 { "CPU_exec_context" : "ExecContext" }), 1215 ] 1216 1217 # variable to hold templates 1218 self.templateMap = {} 1219 1220 # This dictionary maps format name strings to Format objects. 1221 self.formatMap = {} 1222 1223 # Track open files and, if applicable, how many chunks it has been 1224 # split into so far. 1225 self.files = {} 1226 self.splits = {} 1227 1228 # isa_name / namespace identifier from namespace declaration. 1229 # before the namespace declaration, None. 1230 self.isa_name = None 1231 self.namespace = None 1232 1233 # The format stack. 1234 self.formatStack = Stack(NoFormat()) 1235 1236 # The default case stack. 1237 self.defaultStack = Stack(None) 1238 1239 # Stack that tracks current file and line number. Each 1240 # element is a tuple (filename, lineno) that records the 1241 # *current* filename and the line number in the *previous* 1242 # file where it was included. 1243 self.fileNameStack = Stack() 1244 1245 symbols = ('makeList', 're', 'string') 1246 self.exportContext = dict([(s, eval(s)) for s in symbols]) 1247 1248 self.maxInstSrcRegs = 0 1249 self.maxInstDestRegs = 0 1250 self.maxMiscDestRegs = 0 1251 1252 def __getitem__(self, i): # Allow object (self) to be 1253 return getattr(self, i) # passed to %-substitutions 1254 1255 # Change the file suffix of a base filename: 1256 # (e.g.) decoder.cc -> decoder-g.cc.inc for 'global' outputs 1257 def suffixize(self, s, sec): 1258 extn = re.compile('(\.[^\.]+)$') # isolate extension 1259 if self.namespace: 1260 return extn.sub(r'-ns\1.inc', s) # insert some text on either side 1261 else: 1262 return extn.sub(r'-g\1.inc', s) 1263 1264 # Get the file object for emitting code into the specified section 1265 # (header, decoder, exec, decode_block). 1266 def get_file(self, section): 1267 if section == 'decode_block': 1268 filename = 'decode-method.cc.inc' 1269 else: 1270 if section == 'header': 1271 file = 'decoder.hh' 1272 else: 1273 file = '%s.cc' % section 1274 filename = self.suffixize(file, section) 1275 try: 1276 return self.files[filename] 1277 except KeyError: pass 1278 1279 f = self.open(filename) 1280 self.files[filename] = f 1281 1282 # The splittable files are the ones with many independent 1283 # per-instruction functions - the decoder's instruction constructors 1284 # and the instruction execution (execute()) methods. These both have 1285 # the suffix -ns.cc.inc, meaning they are within the namespace part 1286 # of the ISA, contain object-emitting C++ source, and are included 1287 # into other top-level files. These are the files that need special 1288 # #define's to allow parts of them to be compiled separately. Rather 1289 # than splitting the emissions into separate files, the monolithic 1290 # output of the ISA parser is maintained, but the value (or lack 1291 # thereof) of the __SPLIT definition during C preprocessing will 1292 # select the different chunks. If no 'split' directives are used, 1293 # the cpp emissions have no effect. 1294 if re.search('-ns.cc.inc$', filename): 1295 print >>f, '#if !defined(__SPLIT) || (__SPLIT == 1)' 1296 self.splits[f] = 1 1297 # ensure requisite #include's 1298 elif filename in ['decoder-g.cc.inc', 'exec-g.cc.inc']: 1299 print >>f, '#include "decoder.hh"' 1300 elif filename == 'decoder-g.hh.inc': 1301 print >>f, '#include "base/bitfield.hh"' 1302 1303 return f 1304 1305 # Weave together the parts of the different output sections by 1306 # #include'ing them into some very short top-level .cc/.hh files. 1307 # These small files make it much clearer how this tool works, since 1308 # you directly see the chunks emitted as files that are #include'd. 1309 def write_top_level_files(self): 1310 dep = self.open('inc.d', bare=True) 1311 1312 # decoder header - everything depends on this 1313 file = 'decoder.hh' 1314 with self.open(file) as f: 1315 inc = [] 1316 1317 fn = 'decoder-g.hh.inc' 1318 assert(fn in self.files) 1319 f.write('#include "%s"\n' % fn) 1320 inc.append(fn) 1321 1322 fn = 'decoder-ns.hh.inc' 1323 assert(fn in self.files) 1324 f.write('namespace %s {\n#include "%s"\n}\n' 1325 % (self.namespace, fn)) 1326 inc.append(fn) 1327 1328 print >>dep, file+':', ' '.join(inc) 1329 1330 # decoder method - cannot be split 1331 file = 'decoder.cc' 1332 with self.open(file) as f: 1333 inc = [] 1334 1335 fn = 'decoder-g.cc.inc' 1336 assert(fn in self.files) 1337 f.write('#include "%s"\n' % fn) 1338 inc.append(fn) 1339 1340 fn = 'decode-method.cc.inc' 1341 # is guaranteed to have been written for parse to complete 1342 f.write('#include "%s"\n' % fn) 1343 inc.append(fn) 1344 1345 inc.append("decoder.hh") 1346 print >>dep, file+':', ' '.join(inc) 1347 1348 extn = re.compile('(\.[^\.]+)$') 1349 1350 # instruction constructors 1351 splits = self.splits[self.get_file('decoder')] 1352 file_ = 'inst-constrs.cc' 1353 for i in range(1, splits+1): 1354 if splits > 1: 1355 file = extn.sub(r'-%d\1' % i, file_) 1356 else: 1357 file = file_ 1358 with self.open(file) as f: 1359 inc = [] 1360 1361 fn = 'decoder-g.cc.inc' 1362 assert(fn in self.files) 1363 f.write('#include "%s"\n' % fn) 1364 inc.append(fn) 1365 1366 fn = 'decoder-ns.cc.inc' 1367 assert(fn in self.files) 1368 print >>f, 'namespace %s {' % self.namespace 1369 if splits > 1: 1370 print >>f, '#define __SPLIT %u' % i 1371 print >>f, '#include "%s"' % fn 1372 print >>f, '}' 1373 inc.append(fn) 1374 1375 inc.append("decoder.hh") 1376 print >>dep, file+':', ' '.join(inc) 1377 1378 # instruction execution per-CPU model 1379 splits = self.splits[self.get_file('exec')] 1380 for cpu in self.cpuModels: 1381 for i in range(1, splits+1): 1382 if splits > 1: 1383 file = extn.sub(r'_%d\1' % i, cpu.filename) 1384 else: 1385 file = cpu.filename 1386 with self.open(file) as f: 1387 inc = [] 1388 1389 fn = 'exec-g.cc.inc' 1390 assert(fn in self.files) 1391 f.write('#include "%s"\n' % fn) 1392 inc.append(fn) 1393 1394 f.write(cpu.includes+"\n") 1395 1396 fn = 'exec-ns.cc.inc' 1397 assert(fn in self.files) 1398 print >>f, 'namespace %s {' % self.namespace 1399 print >>f, '#define CPU_EXEC_CONTEXT %s' \ 1400 % cpu.strings['CPU_exec_context'] 1401 if splits > 1: 1402 print >>f, '#define __SPLIT %u' % i 1403 print >>f, '#include "%s"' % fn 1404 print >>f, '}' 1405 inc.append(fn) 1406 1407 inc.append("decoder.hh") 1408 print >>dep, file+':', ' '.join(inc) 1409 1410 # max_inst_regs.hh 1411 self.update('max_inst_regs.hh', 1412 '''namespace %(namespace)s { 1413 const int MaxInstSrcRegs = %(maxInstSrcRegs)d; 1414 const int MaxInstDestRegs = %(maxInstDestRegs)d; 1415 const int MaxMiscDestRegs = %(maxMiscDestRegs)d;\n}\n''' % self) 1416 print >>dep, 'max_inst_regs.hh:' 1417 1418 dep.close() 1419 1420 1421 scaremonger_template ='''// DO NOT EDIT 1422// This file was automatically generated from an ISA description: 1423// %(filename)s 1424 1425'''; 1426 1427 ##################################################################### 1428 # 1429 # Lexer 1430 # 1431 # The PLY lexer module takes two things as input: 1432 # - A list of token names (the string list 'tokens') 1433 # - A regular expression describing a match for each token. The 1434 # regexp for token FOO can be provided in two ways: 1435 # - as a string variable named t_FOO 1436 # - as the doc string for a function named t_FOO. In this case, 1437 # the function is also executed, allowing an action to be 1438 # associated with each token match. 1439 # 1440 ##################################################################### 1441 1442 # Reserved words. These are listed separately as they are matched 1443 # using the same regexp as generic IDs, but distinguished in the 1444 # t_ID() function. The PLY documentation suggests this approach. 1445 reserved = ( 1446 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT', 1447 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS', 1448 'OUTPUT', 'SIGNED', 'SPLIT', 'TEMPLATE' 1449 ) 1450 1451 # List of tokens. The lex module requires this. 1452 tokens = reserved + ( 1453 # identifier 1454 'ID', 1455 1456 # integer literal 1457 'INTLIT', 1458 1459 # string literal 1460 'STRLIT', 1461 1462 # code literal 1463 'CODELIT', 1464 1465 # ( ) [ ] { } < > , ; . : :: * 1466 'LPAREN', 'RPAREN', 1467 'LBRACKET', 'RBRACKET', 1468 'LBRACE', 'RBRACE', 1469 'LESS', 'GREATER', 'EQUALS', 1470 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON', 1471 'ASTERISK', 1472 1473 # C preprocessor directives 1474 'CPPDIRECTIVE' 1475 1476 # The following are matched but never returned. commented out to 1477 # suppress PLY warning 1478 # newfile directive 1479 # 'NEWFILE', 1480 1481 # endfile directive 1482 # 'ENDFILE' 1483 ) 1484 1485 # Regular expressions for token matching 1486 t_LPAREN = r'\(' 1487 t_RPAREN = r'\)' 1488 t_LBRACKET = r'\[' 1489 t_RBRACKET = r'\]' 1490 t_LBRACE = r'\{' 1491 t_RBRACE = r'\}' 1492 t_LESS = r'\<' 1493 t_GREATER = r'\>' 1494 t_EQUALS = r'=' 1495 t_COMMA = r',' 1496 t_SEMI = r';' 1497 t_DOT = r'\.' 1498 t_COLON = r':' 1499 t_DBLCOLON = r'::' 1500 t_ASTERISK = r'\*' 1501 1502 # Identifiers and reserved words 1503 reserved_map = { } 1504 for r in reserved: 1505 reserved_map[r.lower()] = r 1506 1507 def t_ID(self, t): 1508 r'[A-Za-z_]\w*' 1509 t.type = self.reserved_map.get(t.value, 'ID') 1510 return t 1511 1512 # Integer literal 1513 def t_INTLIT(self, t): 1514 r'-?(0x[\da-fA-F]+)|\d+' 1515 try: 1516 t.value = int(t.value,0) 1517 except ValueError: 1518 error(t, 'Integer value "%s" too large' % t.value) 1519 t.value = 0 1520 return t 1521 1522 # String literal. Note that these use only single quotes, and 1523 # can span multiple lines. 1524 def t_STRLIT(self, t): 1525 r"(?m)'([^'])+'" 1526 # strip off quotes 1527 t.value = t.value[1:-1] 1528 t.lexer.lineno += t.value.count('\n') 1529 return t 1530 1531 1532 # "Code literal"... like a string literal, but delimiters are 1533 # '{{' and '}}' so they get formatted nicely under emacs c-mode 1534 def t_CODELIT(self, t): 1535 r"(?m)\{\{([^\}]|}(?!\}))+\}\}" 1536 # strip off {{ & }} 1537 t.value = t.value[2:-2] 1538 t.lexer.lineno += t.value.count('\n') 1539 return t 1540 1541 def t_CPPDIRECTIVE(self, t): 1542 r'^\#[^\#].*\n' 1543 t.lexer.lineno += t.value.count('\n') 1544 return t 1545 1546 def t_NEWFILE(self, t): 1547 r'^\#\#newfile\s+"[^"]*"' 1548 self.fileNameStack.push((t.value[11:-1], t.lexer.lineno)) 1549 t.lexer.lineno = 0 1550 1551 def t_ENDFILE(self, t): 1552 r'^\#\#endfile' 1553 (old_filename, t.lexer.lineno) = self.fileNameStack.pop() 1554 1555 # 1556 # The functions t_NEWLINE, t_ignore, and t_error are 1557 # special for the lex module. 1558 # 1559 1560 # Newlines 1561 def t_NEWLINE(self, t): 1562 r'\n+' 1563 t.lexer.lineno += t.value.count('\n') 1564 1565 # Comments 1566 def t_comment(self, t): 1567 r'//.*' 1568 1569 # Completely ignored characters 1570 t_ignore = ' \t\x0c' 1571 1572 # Error handler 1573 def t_error(self, t): 1574 error(t, "illegal character '%s'" % t.value[0]) 1575 t.skip(1) 1576 1577 ##################################################################### 1578 # 1579 # Parser 1580 # 1581 # Every function whose name starts with 'p_' defines a grammar 1582 # rule. The rule is encoded in the function's doc string, while 1583 # the function body provides the action taken when the rule is 1584 # matched. The argument to each function is a list of the values 1585 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the 1586 # symbols on the RHS. For tokens, the value is copied from the 1587 # t.value attribute provided by the lexer. For non-terminals, the 1588 # value is assigned by the producing rule; i.e., the job of the 1589 # grammar rule function is to set the value for the non-terminal 1590 # on the LHS (by assigning to t[0]). 1591 ##################################################################### 1592 1593 # The LHS of the first grammar rule is used as the start symbol 1594 # (in this case, 'specification'). Note that this rule enforces 1595 # that there will be exactly one namespace declaration, with 0 or 1596 # more global defs/decls before and after it. The defs & decls 1597 # before the namespace decl will be outside the namespace; those 1598 # after will be inside. The decoder function is always inside the 1599 # namespace. 1600 def p_specification(self, t): 1601 'specification : opt_defs_and_outputs top_level_decode_block' 1602 1603 for f in self.splits.iterkeys(): 1604 f.write('\n#endif\n') 1605 1606 for f in self.files.itervalues(): # close ALL the files; 1607 f.close() # not doing so can cause compilation to fail 1608 1609 self.write_top_level_files() 1610 1611 t[0] = True 1612 1613 # 'opt_defs_and_outputs' is a possibly empty sequence of def and/or 1614 # output statements. Its productions do the hard work of eventually 1615 # instantiating a GenCode, which are generally emitted (written to disk) 1616 # as soon as possible, except for the decode_block, which has to be 1617 # accumulated into one large function of nested switch/case blocks. 1618 def p_opt_defs_and_outputs_0(self, t): 1619 'opt_defs_and_outputs : empty' 1620 1621 def p_opt_defs_and_outputs_1(self, t): 1622 'opt_defs_and_outputs : defs_and_outputs' 1623 1624 def p_defs_and_outputs_0(self, t): 1625 'defs_and_outputs : def_or_output' 1626 1627 def p_defs_and_outputs_1(self, t): 1628 'defs_and_outputs : defs_and_outputs def_or_output' 1629 1630 # The list of possible definition/output statements. 1631 # They are all processed as they are seen. 1632 def p_def_or_output(self, t): 1633 '''def_or_output : name_decl 1634 | def_format 1635 | def_bitfield 1636 | def_bitfield_struct 1637 | def_template 1638 | def_operand_types 1639 | def_operands 1640 | output 1641 | global_let 1642 | split''' 1643 1644 # Utility function used by both invocations of splitting - explicit 1645 # 'split' keyword and split() function inside "let {{ }};" blocks. 1646 def split(self, sec, write=False): 1647 assert(sec != 'header' and "header cannot be split") 1648 1649 f = self.get_file(sec) 1650 self.splits[f] += 1 1651 s = '\n#endif\n#if __SPLIT == %u\n' % self.splits[f] 1652 if write: 1653 f.write(s) 1654 else: 1655 return s 1656 1657 # split output file to reduce compilation time 1658 def p_split(self, t): 1659 'split : SPLIT output_type SEMI' 1660 assert(self.isa_name and "'split' not allowed before namespace decl") 1661 1662 self.split(t[2], True) 1663 1664 def p_output_type(self, t): 1665 '''output_type : DECODER 1666 | HEADER 1667 | EXEC''' 1668 t[0] = t[1] 1669 1670 # ISA name declaration looks like "namespace <foo>;" 1671 def p_name_decl(self, t): 1672 'name_decl : NAMESPACE ID SEMI' 1673 assert(self.isa_name == None and "Only 1 namespace decl permitted") 1674 self.isa_name = t[2] 1675 self.namespace = t[2] + 'Inst' 1676 1677 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied 1678 # directly to the appropriate output section. 1679 1680 # Massage output block by substituting in template definitions and 1681 # bit operators. We handle '%'s embedded in the string that don't 1682 # indicate template substitutions (or CPU-specific symbols, which 1683 # get handled in GenCode) by doubling them first so that the 1684 # format operation will reduce them back to single '%'s. 1685 def process_output(self, s): 1686 s = self.protectNonSubstPercents(s) 1687 # protects cpu-specific symbols too 1688 s = self.protectCpuSymbols(s) 1689 return substBitOps(s % self.templateMap) 1690 1691 def p_output(self, t): 1692 'output : OUTPUT output_type CODELIT SEMI' 1693 kwargs = { t[2]+'_output' : self.process_output(t[3]) } 1694 GenCode(self, **kwargs).emit() 1695 1696 # global let blocks 'let {{...}}' (Python code blocks) are 1697 # executed directly when seen. Note that these execute in a 1698 # special variable context 'exportContext' to prevent the code 1699 # from polluting this script's namespace. 1700 def p_global_let(self, t): 1701 'global_let : LET CODELIT SEMI' 1702 def _split(sec): 1703 return self.split(sec) 1704 self.updateExportContext() 1705 self.exportContext["header_output"] = '' 1706 self.exportContext["decoder_output"] = '' 1707 self.exportContext["exec_output"] = '' 1708 self.exportContext["decode_block"] = '' 1709 self.exportContext["split"] = _split 1710 split_setup = ''' 1711def wrap(func): 1712 def split(sec): 1713 globals()[sec + '_output'] += func(sec) 1714 return split 1715split = wrap(split) 1716del wrap 1717''' 1718 # This tricky setup (immediately above) allows us to just write 1719 # (e.g.) "split('exec')" in the Python code and the split #ifdef's 1720 # will automatically be added to the exec_output variable. The inner 1721 # Python execution environment doesn't know about the split points, 1722 # so we carefully inject and wrap a closure that can retrieve the 1723 # next split's #define from the parser and add it to the current 1724 # emission-in-progress. 1725 try: 1726 exec split_setup+fixPythonIndentation(t[2]) in self.exportContext 1727 except Exception, exc: 1728 if debug: 1729 raise 1730 error(t, 'error: %s in global let block "%s".' % (exc, t[2])) 1731 GenCode(self, 1732 header_output=self.exportContext["header_output"], 1733 decoder_output=self.exportContext["decoder_output"], 1734 exec_output=self.exportContext["exec_output"], 1735 decode_block=self.exportContext["decode_block"]).emit() 1736 1737 # Define the mapping from operand type extensions to C++ types and 1738 # bit widths (stored in operandTypeMap). 1739 def p_def_operand_types(self, t): 1740 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' 1741 try: 1742 self.operandTypeMap = eval('{' + t[3] + '}') 1743 except Exception, exc: 1744 if debug: 1745 raise 1746 error(t, 1747 'error: %s in def operand_types block "%s".' % (exc, t[3])) 1748 1749 # Define the mapping from operand names to operand classes and 1750 # other traits. Stored in operandNameMap. 1751 def p_def_operands(self, t): 1752 'def_operands : DEF OPERANDS CODELIT SEMI' 1753 if not hasattr(self, 'operandTypeMap'): 1754 error(t, 'error: operand types must be defined before operands') 1755 try: 1756 user_dict = eval('{' + t[3] + '}', self.exportContext) 1757 except Exception, exc: 1758 if debug: 1759 raise 1760 error(t, 'error: %s in def operands block "%s".' % (exc, t[3])) 1761 self.buildOperandNameMap(user_dict, t.lexer.lineno) 1762 1763 # A bitfield definition looks like: 1764 # 'def [signed] bitfield <ID> [<first>:<last>]' 1765 # This generates a preprocessor macro in the output file. 1766 def p_def_bitfield_0(self, t): 1767 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' 1768 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) 1769 if (t[2] == 'signed'): 1770 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr) 1771 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 1772 GenCode(self, header_output=hash_define).emit() 1773 1774 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]' 1775 def p_def_bitfield_1(self, t): 1776 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI' 1777 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6]) 1778 if (t[2] == 'signed'): 1779 expr = 'sext<%d>(%s)' % (1, expr) 1780 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 1781 GenCode(self, header_output=hash_define).emit() 1782 1783 # alternate form for structure member: 'def bitfield <ID> <ID>' 1784 def p_def_bitfield_struct(self, t): 1785 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' 1786 if (t[2] != ''): 1787 error(t, 'error: structure bitfields are always unsigned.') 1788 expr = 'machInst.%s' % t[5] 1789 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 1790 GenCode(self, header_output=hash_define).emit() 1791 1792 def p_id_with_dot_0(self, t): 1793 'id_with_dot : ID' 1794 t[0] = t[1] 1795 1796 def p_id_with_dot_1(self, t): 1797 'id_with_dot : ID DOT id_with_dot' 1798 t[0] = t[1] + t[2] + t[3] 1799 1800 def p_opt_signed_0(self, t): 1801 'opt_signed : SIGNED' 1802 t[0] = t[1] 1803 1804 def p_opt_signed_1(self, t): 1805 'opt_signed : empty' 1806 t[0] = '' 1807 1808 def p_def_template(self, t): 1809 'def_template : DEF TEMPLATE ID CODELIT SEMI' 1810 if t[3] in self.templateMap: 1811 print "warning: template %s already defined" % t[3] 1812 self.templateMap[t[3]] = Template(self, t[4]) 1813 1814 # An instruction format definition looks like 1815 # "def format <fmt>(<params>) {{...}};" 1816 def p_def_format(self, t): 1817 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' 1818 (id, params, code) = (t[3], t[5], t[7]) 1819 self.defFormat(id, params, code, t.lexer.lineno) 1820 1821 # The formal parameter list for an instruction format is a 1822 # possibly empty list of comma-separated parameters. Positional 1823 # (standard, non-keyword) parameters must come first, followed by 1824 # keyword parameters, followed by a '*foo' parameter that gets 1825 # excess positional arguments (as in Python). Each of these three 1826 # parameter categories is optional. 1827 # 1828 # Note that we do not support the '**foo' parameter for collecting 1829 # otherwise undefined keyword args. Otherwise the parameter list 1830 # is (I believe) identical to what is supported in Python. 1831 # 1832 # The param list generates a tuple, where the first element is a 1833 # list of the positional params and the second element is a dict 1834 # containing the keyword params. 1835 def p_param_list_0(self, t): 1836 'param_list : positional_param_list COMMA nonpositional_param_list' 1837 t[0] = t[1] + t[3] 1838 1839 def p_param_list_1(self, t): 1840 '''param_list : positional_param_list 1841 | nonpositional_param_list''' 1842 t[0] = t[1] 1843 1844 def p_positional_param_list_0(self, t): 1845 'positional_param_list : empty' 1846 t[0] = [] 1847 1848 def p_positional_param_list_1(self, t): 1849 'positional_param_list : ID' 1850 t[0] = [t[1]] 1851 1852 def p_positional_param_list_2(self, t): 1853 'positional_param_list : positional_param_list COMMA ID' 1854 t[0] = t[1] + [t[3]] 1855 1856 def p_nonpositional_param_list_0(self, t): 1857 'nonpositional_param_list : keyword_param_list COMMA excess_args_param' 1858 t[0] = t[1] + t[3] 1859 1860 def p_nonpositional_param_list_1(self, t): 1861 '''nonpositional_param_list : keyword_param_list 1862 | excess_args_param''' 1863 t[0] = t[1] 1864 1865 def p_keyword_param_list_0(self, t): 1866 'keyword_param_list : keyword_param' 1867 t[0] = [t[1]] 1868 1869 def p_keyword_param_list_1(self, t): 1870 'keyword_param_list : keyword_param_list COMMA keyword_param' 1871 t[0] = t[1] + [t[3]] 1872 1873 def p_keyword_param(self, t): 1874 'keyword_param : ID EQUALS expr' 1875 t[0] = t[1] + ' = ' + t[3].__repr__() 1876 1877 def p_excess_args_param(self, t): 1878 'excess_args_param : ASTERISK ID' 1879 # Just concatenate them: '*ID'. Wrap in list to be consistent 1880 # with positional_param_list and keyword_param_list. 1881 t[0] = [t[1] + t[2]] 1882 1883 # End of format definition-related rules. 1884 ############## 1885 1886 # 1887 # A decode block looks like: 1888 # decode <field1> [, <field2>]* [default <inst>] { ... } 1889 # 1890 def p_top_level_decode_block(self, t): 1891 'top_level_decode_block : decode_block' 1892 codeObj = t[1] 1893 codeObj.wrap_decode_block(''' 1894StaticInstPtr 1895%(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst) 1896{ 1897 using namespace %(namespace)s; 1898''' % self, '}') 1899 1900 codeObj.emit() 1901 1902 def p_decode_block(self, t): 1903 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' 1904 default_defaults = self.defaultStack.pop() 1905 codeObj = t[5] 1906 # use the "default defaults" only if there was no explicit 1907 # default statement in decode_stmt_list 1908 if not codeObj.has_decode_default: 1909 codeObj += default_defaults 1910 codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n') 1911 t[0] = codeObj 1912 1913 # The opt_default statement serves only to push the "default 1914 # defaults" onto defaultStack. This value will be used by nested 1915 # decode blocks, and used and popped off when the current 1916 # decode_block is processed (in p_decode_block() above). 1917 def p_opt_default_0(self, t): 1918 'opt_default : empty' 1919 # no default specified: reuse the one currently at the top of 1920 # the stack 1921 self.defaultStack.push(self.defaultStack.top()) 1922 # no meaningful value returned 1923 t[0] = None 1924 1925 def p_opt_default_1(self, t): 1926 'opt_default : DEFAULT inst' 1927 # push the new default 1928 codeObj = t[2] 1929 codeObj.wrap_decode_block('\ndefault:\n', 'break;\n') 1930 self.defaultStack.push(codeObj) 1931 # no meaningful value returned 1932 t[0] = None 1933 1934 def p_decode_stmt_list_0(self, t): 1935 'decode_stmt_list : decode_stmt' 1936 t[0] = t[1] 1937 1938 def p_decode_stmt_list_1(self, t): 1939 'decode_stmt_list : decode_stmt decode_stmt_list' 1940 if (t[1].has_decode_default and t[2].has_decode_default): 1941 error(t, 'Two default cases in decode block') 1942 t[0] = t[1] + t[2] 1943 1944 # 1945 # Decode statement rules 1946 # 1947 # There are four types of statements allowed in a decode block: 1948 # 1. Format blocks 'format <foo> { ... }' 1949 # 2. Nested decode blocks 1950 # 3. Instruction definitions. 1951 # 4. C preprocessor directives. 1952 1953 1954 # Preprocessor directives found in a decode statement list are 1955 # passed through to the output, replicated to all of the output 1956 # code streams. This works well for ifdefs, so we can ifdef out 1957 # both the declarations and the decode cases generated by an 1958 # instruction definition. Handling them as part of the grammar 1959 # makes it easy to keep them in the right place with respect to 1960 # the code generated by the other statements. 1961 def p_decode_stmt_cpp(self, t): 1962 'decode_stmt : CPPDIRECTIVE' 1963 t[0] = GenCode(self, t[1], t[1], t[1], t[1]) 1964 1965 # A format block 'format <foo> { ... }' sets the default 1966 # instruction format used to handle instruction definitions inside 1967 # the block. This format can be overridden by using an explicit 1968 # format on the instruction definition or with a nested format 1969 # block. 1970 def p_decode_stmt_format(self, t): 1971 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE' 1972 # The format will be pushed on the stack when 'push_format_id' 1973 # is processed (see below). Once the parser has recognized 1974 # the full production (though the right brace), we're done 1975 # with the format, so now we can pop it. 1976 self.formatStack.pop() 1977 t[0] = t[4] 1978 1979 # This rule exists so we can set the current format (& push the 1980 # stack) when we recognize the format name part of the format 1981 # block. 1982 def p_push_format_id(self, t): 1983 'push_format_id : ID' 1984 try: 1985 self.formatStack.push(self.formatMap[t[1]]) 1986 t[0] = ('', '// format %s' % t[1]) 1987 except KeyError: 1988 error(t, 'instruction format "%s" not defined.' % t[1]) 1989 1990 # Nested decode block: if the value of the current field matches 1991 # the specified constant(s), do a nested decode on some other field. 1992 def p_decode_stmt_decode(self, t): 1993 'decode_stmt : case_list COLON decode_block' 1994 case_list = t[1] 1995 codeObj = t[3] 1996 # just wrap the decoding code from the block as a case in the 1997 # outer switch statement. 1998 codeObj.wrap_decode_block('\n%s\n' % ''.join(case_list)) 1999 codeObj.has_decode_default = (case_list == ['default:']) 2000 t[0] = codeObj 2001 2002 # Instruction definition (finally!). 2003 def p_decode_stmt_inst(self, t): 2004 'decode_stmt : case_list COLON inst SEMI' 2005 case_list = t[1] 2006 codeObj = t[3] 2007 codeObj.wrap_decode_block('\n%s' % ''.join(case_list), 'break;\n') 2008 codeObj.has_decode_default = (case_list == ['default:']) 2009 t[0] = codeObj 2010 2011 # The constant list for a decode case label must be non-empty, and must 2012 # either be the keyword 'default', or made up of one or more 2013 # comma-separated integer literals or strings which evaluate to 2014 # constants when compiled as C++. 2015 def p_case_list_0(self, t): 2016 'case_list : DEFAULT' 2017 t[0] = ['default:'] 2018 2019 def prep_int_lit_case_label(self, lit): 2020 if lit >= 2**32: 2021 return 'case ULL(%#x): ' % lit 2022 else: 2023 return 'case %#x: ' % lit 2024 2025 def prep_str_lit_case_label(self, lit): 2026 return 'case %s: ' % lit 2027 2028 def p_case_list_1(self, t): 2029 'case_list : INTLIT' 2030 t[0] = [self.prep_int_lit_case_label(t[1])] 2031 2032 def p_case_list_2(self, t): 2033 'case_list : STRLIT' 2034 t[0] = [self.prep_str_lit_case_label(t[1])] 2035 2036 def p_case_list_3(self, t): 2037 'case_list : case_list COMMA INTLIT' 2038 t[0] = t[1] 2039 t[0].append(self.prep_int_lit_case_label(t[3])) 2040 2041 def p_case_list_4(self, t): 2042 'case_list : case_list COMMA STRLIT' 2043 t[0] = t[1] 2044 t[0].append(self.prep_str_lit_case_label(t[3])) 2045 2046 # Define an instruction using the current instruction format 2047 # (specified by an enclosing format block). 2048 # "<mnemonic>(<args>)" 2049 def p_inst_0(self, t): 2050 'inst : ID LPAREN arg_list RPAREN' 2051 # Pass the ID and arg list to the current format class to deal with. 2052 currentFormat = self.formatStack.top() 2053 codeObj = currentFormat.defineInst(self, t[1], t[3], t.lexer.lineno) 2054 args = ','.join(map(str, t[3])) 2055 args = re.sub('(?m)^', '//', args) 2056 args = re.sub('^//', '', args) 2057 comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args) 2058 codeObj.prepend_all(comment) 2059 t[0] = codeObj 2060 2061 # Define an instruction using an explicitly specified format: 2062 # "<fmt>::<mnemonic>(<args>)" 2063 def p_inst_1(self, t): 2064 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN' 2065 try: 2066 format = self.formatMap[t[1]] 2067 except KeyError: 2068 error(t, 'instruction format "%s" not defined.' % t[1]) 2069 2070 codeObj = format.defineInst(self, t[3], t[5], t.lexer.lineno) 2071 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5]) 2072 codeObj.prepend_all(comment) 2073 t[0] = codeObj 2074 2075 # The arg list generates a tuple, where the first element is a 2076 # list of the positional args and the second element is a dict 2077 # containing the keyword args. 2078 def p_arg_list_0(self, t): 2079 'arg_list : positional_arg_list COMMA keyword_arg_list' 2080 t[0] = ( t[1], t[3] ) 2081 2082 def p_arg_list_1(self, t): 2083 'arg_list : positional_arg_list' 2084 t[0] = ( t[1], {} ) 2085 2086 def p_arg_list_2(self, t): 2087 'arg_list : keyword_arg_list' 2088 t[0] = ( [], t[1] ) 2089 2090 def p_positional_arg_list_0(self, t): 2091 'positional_arg_list : empty' 2092 t[0] = [] 2093 2094 def p_positional_arg_list_1(self, t): 2095 'positional_arg_list : expr' 2096 t[0] = [t[1]] 2097 2098 def p_positional_arg_list_2(self, t): 2099 'positional_arg_list : positional_arg_list COMMA expr' 2100 t[0] = t[1] + [t[3]] 2101 2102 def p_keyword_arg_list_0(self, t): 2103 'keyword_arg_list : keyword_arg' 2104 t[0] = t[1] 2105 2106 def p_keyword_arg_list_1(self, t): 2107 'keyword_arg_list : keyword_arg_list COMMA keyword_arg' 2108 t[0] = t[1] 2109 t[0].update(t[3]) 2110 2111 def p_keyword_arg(self, t): 2112 'keyword_arg : ID EQUALS expr' 2113 t[0] = { t[1] : t[3] } 2114 2115 # 2116 # Basic expressions. These constitute the argument values of 2117 # "function calls" (i.e. instruction definitions in the decode 2118 # block) and default values for formal parameters of format 2119 # functions. 2120 # 2121 # Right now, these are either strings, integers, or (recursively) 2122 # lists of exprs (using Python square-bracket list syntax). Note 2123 # that bare identifiers are trated as string constants here (since 2124 # there isn't really a variable namespace to refer to). 2125 # 2126 def p_expr_0(self, t): 2127 '''expr : ID 2128 | INTLIT 2129 | STRLIT 2130 | CODELIT''' 2131 t[0] = t[1] 2132 2133 def p_expr_1(self, t): 2134 '''expr : LBRACKET list_expr RBRACKET''' 2135 t[0] = t[2] 2136 2137 def p_list_expr_0(self, t): 2138 'list_expr : expr' 2139 t[0] = [t[1]] 2140 2141 def p_list_expr_1(self, t): 2142 'list_expr : list_expr COMMA expr' 2143 t[0] = t[1] + [t[3]] 2144 2145 def p_list_expr_2(self, t): 2146 'list_expr : empty' 2147 t[0] = [] 2148 2149 # 2150 # Empty production... use in other rules for readability. 2151 # 2152 def p_empty(self, t): 2153 'empty :' 2154 pass 2155 2156 # Parse error handler. Note that the argument here is the 2157 # offending *token*, not a grammar symbol (hence the need to use 2158 # t.value) 2159 def p_error(self, t): 2160 if t: 2161 error(t, "syntax error at '%s'" % t.value) 2162 else: 2163 error("unknown syntax error") 2164 2165 # END OF GRAMMAR RULES 2166 2167 def updateExportContext(self): 2168 2169 # create a continuation that allows us to grab the current parser 2170 def wrapInstObjParams(*args): 2171 return InstObjParams(self, *args) 2172 self.exportContext['InstObjParams'] = wrapInstObjParams 2173 self.exportContext.update(self.templateMap) 2174 2175 def defFormat(self, id, params, code, lineno): 2176 '''Define a new format''' 2177 2178 # make sure we haven't already defined this one 2179 if id in self.formatMap: 2180 error(lineno, 'format %s redefined.' % id) 2181 2182 # create new object and store in global map 2183 self.formatMap[id] = Format(id, params, code) 2184 2185 def expandCpuSymbolsToDict(self, template): 2186 '''Expand template with CPU-specific references into a 2187 dictionary with an entry for each CPU model name. The entry 2188 key is the model name and the corresponding value is the 2189 template with the CPU-specific refs substituted for that 2190 model.''' 2191 2192 # Protect '%'s that don't go with CPU-specific terms 2193 t = re.sub(r'%(?!\(CPU_)', '%%', template) 2194 result = {} 2195 for cpu in self.cpuModels: 2196 result[cpu.name] = t % cpu.strings 2197 return result 2198 2199 def expandCpuSymbolsToString(self, template): 2200 '''*If* the template has CPU-specific references, return a 2201 single string containing a copy of the template for each CPU 2202 model with the corresponding values substituted in. If the 2203 template has no CPU-specific references, it is returned 2204 unmodified.''' 2205 2206 if template.find('%(CPU_') != -1: 2207 return reduce(lambda x,y: x+y, 2208 self.expandCpuSymbolsToDict(template).values()) 2209 else: 2210 return template 2211 2212 def protectCpuSymbols(self, template): 2213 '''Protect CPU-specific references by doubling the 2214 corresponding '%'s (in preparation for substituting a different 2215 set of references into the template).''' 2216 2217 return re.sub(r'%(?=\(CPU_)', '%%', template) 2218 2219 def protectNonSubstPercents(self, s): 2220 '''Protect any non-dict-substitution '%'s in a format string 2221 (i.e. those not followed by '(')''' 2222 2223 return re.sub(r'%(?!\()', '%%', s) 2224 2225 def buildOperandNameMap(self, user_dict, lineno): 2226 operand_name = {} 2227 for op_name, val in user_dict.iteritems(): 2228 2229 # Check if extra attributes have been specified. 2230 if len(val) > 9: 2231 error(lineno, 'error: too many attributes for operand "%s"' % 2232 base_cls_name) 2233 2234 # Pad val with None in case optional args are missing 2235 val += (None, None, None, None) 2236 base_cls_name, dflt_ext, reg_spec, flags, sort_pri, \ 2237 read_code, write_code, read_predicate, write_predicate = val[:9] 2238 2239 # Canonical flag structure is a triple of lists, where each list 2240 # indicates the set of flags implied by this operand always, when 2241 # used as a source, and when used as a dest, respectively. 2242 # For simplicity this can be initialized using a variety of fairly 2243 # obvious shortcuts; we convert these to canonical form here. 2244 if not flags: 2245 # no flags specified (e.g., 'None') 2246 flags = ( [], [], [] ) 2247 elif isinstance(flags, str): 2248 # a single flag: assumed to be unconditional 2249 flags = ( [ flags ], [], [] ) 2250 elif isinstance(flags, list): 2251 # a list of flags: also assumed to be unconditional 2252 flags = ( flags, [], [] ) 2253 elif isinstance(flags, tuple): 2254 # it's a tuple: it should be a triple, 2255 # but each item could be a single string or a list 2256 (uncond_flags, src_flags, dest_flags) = flags 2257 flags = (makeList(uncond_flags), 2258 makeList(src_flags), makeList(dest_flags)) 2259 2260 # Accumulate attributes of new operand class in tmp_dict 2261 tmp_dict = {} 2262 attrList = ['reg_spec', 'flags', 'sort_pri', 2263 'read_code', 'write_code', 2264 'read_predicate', 'write_predicate'] 2265 if dflt_ext: 2266 dflt_ctype = self.operandTypeMap[dflt_ext] 2267 attrList.extend(['dflt_ctype', 'dflt_ext']) 2268 for attr in attrList: 2269 tmp_dict[attr] = eval(attr) 2270 tmp_dict['base_name'] = op_name 2271 2272 # New class name will be e.g. "IntReg_Ra" 2273 cls_name = base_cls_name + '_' + op_name 2274 # Evaluate string arg to get class object. Note that the 2275 # actual base class for "IntReg" is "IntRegOperand", i.e. we 2276 # have to append "Operand". 2277 try: 2278 base_cls = eval(base_cls_name + 'Operand') 2279 except NameError: 2280 error(lineno, 2281 'error: unknown operand base class "%s"' % base_cls_name) 2282 # The following statement creates a new class called 2283 # <cls_name> as a subclass of <base_cls> with the attributes 2284 # in tmp_dict, just as if we evaluated a class declaration. 2285 operand_name[op_name] = type(cls_name, (base_cls,), tmp_dict) 2286 2287 self.operandNameMap = operand_name 2288 2289 # Define operand variables. 2290 operands = user_dict.keys() 2291 extensions = self.operandTypeMap.keys() 2292 2293 operandsREString = r''' 2294 (?<!\w) # neg. lookbehind assertion: prevent partial matches
|
2405 ((%s)(?:_(%s))?(?:\[\w+\])?) # match: operand with optional '_' 2406 # then suffix, and then an optional array index.
| 2295 ((%s)(?:_(%s))?) # match: operand with optional '_' then suffix
|
2407 (?!\w) # neg. lookahead assertion: prevent partial matches 2408 ''' % (string.join(operands, '|'), string.join(extensions, '|')) 2409 2410 self.operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) 2411 2412 # Same as operandsREString, but extension is mandatory, and only two 2413 # groups are returned (base and ext, not full name as above). 2414 # Used for subtituting '_' for '.' to make C++ identifiers. 2415 operandsWithExtREString = r'(?<!\w)(%s)_(%s)(?!\w)' \ 2416 % (string.join(operands, '|'), string.join(extensions, '|')) 2417 2418 self.operandsWithExtRE = \ 2419 re.compile(operandsWithExtREString, re.MULTILINE) 2420 2421 def substMungedOpNames(self, code): 2422 '''Munge operand names in code string to make legal C++ 2423 variable names. This means getting rid of the type extension 2424 if any. Will match base_name attribute of Operand object.)''' 2425 return self.operandsWithExtRE.sub(r'\1', code) 2426 2427 def mungeSnippet(self, s): 2428 '''Fix up code snippets for final substitution in templates.''' 2429 if isinstance(s, str): 2430 return self.substMungedOpNames(substBitOps(s)) 2431 else: 2432 return s 2433 2434 def open(self, name, bare=False): 2435 '''Open the output file for writing and include scary warning.''' 2436 filename = os.path.join(self.output_dir, name) 2437 f = open(filename, 'w') 2438 if f: 2439 if not bare: 2440 f.write(ISAParser.scaremonger_template % self) 2441 return f 2442 2443 def update(self, file, contents): 2444 '''Update the output file only. Scons should handle the case when 2445 the new contents are unchanged using its built-in hash feature.''' 2446 f = self.open(file) 2447 f.write(contents) 2448 f.close() 2449 2450 # This regular expression matches '##include' directives 2451 includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[^"]*)".*$', 2452 re.MULTILINE) 2453 2454 def replace_include(self, matchobj, dirname): 2455 """Function to replace a matched '##include' directive with the 2456 contents of the specified file (with nested ##includes 2457 replaced recursively). 'matchobj' is an re match object 2458 (from a match of includeRE) and 'dirname' is the directory 2459 relative to which the file path should be resolved.""" 2460 2461 fname = matchobj.group('filename') 2462 full_fname = os.path.normpath(os.path.join(dirname, fname)) 2463 contents = '##newfile "%s"\n%s\n##endfile\n' % \ 2464 (full_fname, self.read_and_flatten(full_fname)) 2465 return contents 2466 2467 def read_and_flatten(self, filename): 2468 """Read a file and recursively flatten nested '##include' files.""" 2469 2470 current_dir = os.path.dirname(filename) 2471 try: 2472 contents = open(filename).read() 2473 except IOError: 2474 error('Error including file "%s"' % filename) 2475 2476 self.fileNameStack.push((filename, 0)) 2477 2478 # Find any includes and include them 2479 def replace(matchobj): 2480 return self.replace_include(matchobj, current_dir) 2481 contents = self.includeRE.sub(replace, contents) 2482 2483 self.fileNameStack.pop() 2484 return contents 2485 2486 AlreadyGenerated = {} 2487 2488 def _parse_isa_desc(self, isa_desc_file): 2489 '''Read in and parse the ISA description.''' 2490 2491 # The build system can end up running the ISA parser twice: once to 2492 # finalize the build dependencies, and then to actually generate 2493 # the files it expects (in src/arch/$ARCH/generated). This code 2494 # doesn't do anything different either time, however; the SCons 2495 # invocations just expect different things. Since this code runs 2496 # within SCons, we can just remember that we've already run and 2497 # not perform a completely unnecessary run, since the ISA parser's 2498 # effect is idempotent. 2499 if isa_desc_file in ISAParser.AlreadyGenerated: 2500 return 2501 2502 # grab the last three path components of isa_desc_file 2503 self.filename = '/'.join(isa_desc_file.split('/')[-3:]) 2504 2505 # Read file and (recursively) all included files into a string. 2506 # PLY requires that the input be in a single string so we have to 2507 # do this up front. 2508 isa_desc = self.read_and_flatten(isa_desc_file) 2509 2510 # Initialize filename stack with outer file. 2511 self.fileNameStack.push((isa_desc_file, 0)) 2512 2513 # Parse. 2514 self.parse_string(isa_desc) 2515 2516 ISAParser.AlreadyGenerated[isa_desc_file] = None 2517 2518 def parse_isa_desc(self, *args, **kwargs): 2519 try: 2520 self._parse_isa_desc(*args, **kwargs) 2521 except ISAParserError, e: 2522 e.exit(self.fileNameStack) 2523 2524# Called as script: get args from command line. 2525# Args are: <isa desc file> <output dir> 2526if __name__ == '__main__': 2527 ISAParser(sys.argv[2]).parse_isa_desc(sys.argv[1])
| 2296 (?!\w) # neg. lookahead assertion: prevent partial matches 2297 ''' % (string.join(operands, '|'), string.join(extensions, '|')) 2298 2299 self.operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) 2300 2301 # Same as operandsREString, but extension is mandatory, and only two 2302 # groups are returned (base and ext, not full name as above). 2303 # Used for subtituting '_' for '.' to make C++ identifiers. 2304 operandsWithExtREString = r'(?<!\w)(%s)_(%s)(?!\w)' \ 2305 % (string.join(operands, '|'), string.join(extensions, '|')) 2306 2307 self.operandsWithExtRE = \ 2308 re.compile(operandsWithExtREString, re.MULTILINE) 2309 2310 def substMungedOpNames(self, code): 2311 '''Munge operand names in code string to make legal C++ 2312 variable names. This means getting rid of the type extension 2313 if any. Will match base_name attribute of Operand object.)''' 2314 return self.operandsWithExtRE.sub(r'\1', code) 2315 2316 def mungeSnippet(self, s): 2317 '''Fix up code snippets for final substitution in templates.''' 2318 if isinstance(s, str): 2319 return self.substMungedOpNames(substBitOps(s)) 2320 else: 2321 return s 2322 2323 def open(self, name, bare=False): 2324 '''Open the output file for writing and include scary warning.''' 2325 filename = os.path.join(self.output_dir, name) 2326 f = open(filename, 'w') 2327 if f: 2328 if not bare: 2329 f.write(ISAParser.scaremonger_template % self) 2330 return f 2331 2332 def update(self, file, contents): 2333 '''Update the output file only. Scons should handle the case when 2334 the new contents are unchanged using its built-in hash feature.''' 2335 f = self.open(file) 2336 f.write(contents) 2337 f.close() 2338 2339 # This regular expression matches '##include' directives 2340 includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[^"]*)".*$', 2341 re.MULTILINE) 2342 2343 def replace_include(self, matchobj, dirname): 2344 """Function to replace a matched '##include' directive with the 2345 contents of the specified file (with nested ##includes 2346 replaced recursively). 'matchobj' is an re match object 2347 (from a match of includeRE) and 'dirname' is the directory 2348 relative to which the file path should be resolved.""" 2349 2350 fname = matchobj.group('filename') 2351 full_fname = os.path.normpath(os.path.join(dirname, fname)) 2352 contents = '##newfile "%s"\n%s\n##endfile\n' % \ 2353 (full_fname, self.read_and_flatten(full_fname)) 2354 return contents 2355 2356 def read_and_flatten(self, filename): 2357 """Read a file and recursively flatten nested '##include' files.""" 2358 2359 current_dir = os.path.dirname(filename) 2360 try: 2361 contents = open(filename).read() 2362 except IOError: 2363 error('Error including file "%s"' % filename) 2364 2365 self.fileNameStack.push((filename, 0)) 2366 2367 # Find any includes and include them 2368 def replace(matchobj): 2369 return self.replace_include(matchobj, current_dir) 2370 contents = self.includeRE.sub(replace, contents) 2371 2372 self.fileNameStack.pop() 2373 return contents 2374 2375 AlreadyGenerated = {} 2376 2377 def _parse_isa_desc(self, isa_desc_file): 2378 '''Read in and parse the ISA description.''' 2379 2380 # The build system can end up running the ISA parser twice: once to 2381 # finalize the build dependencies, and then to actually generate 2382 # the files it expects (in src/arch/$ARCH/generated). This code 2383 # doesn't do anything different either time, however; the SCons 2384 # invocations just expect different things. Since this code runs 2385 # within SCons, we can just remember that we've already run and 2386 # not perform a completely unnecessary run, since the ISA parser's 2387 # effect is idempotent. 2388 if isa_desc_file in ISAParser.AlreadyGenerated: 2389 return 2390 2391 # grab the last three path components of isa_desc_file 2392 self.filename = '/'.join(isa_desc_file.split('/')[-3:]) 2393 2394 # Read file and (recursively) all included files into a string. 2395 # PLY requires that the input be in a single string so we have to 2396 # do this up front. 2397 isa_desc = self.read_and_flatten(isa_desc_file) 2398 2399 # Initialize filename stack with outer file. 2400 self.fileNameStack.push((isa_desc_file, 0)) 2401 2402 # Parse. 2403 self.parse_string(isa_desc) 2404 2405 ISAParser.AlreadyGenerated[isa_desc_file] = None 2406 2407 def parse_isa_desc(self, *args, **kwargs): 2408 try: 2409 self._parse_isa_desc(*args, **kwargs) 2410 except ISAParserError, e: 2411 e.exit(self.fileNameStack) 2412 2413# Called as script: get args from command line. 2414# Args are: <isa desc file> <output dir> 2415if __name__ == '__main__': 2416 ISAParser(sys.argv[2]).parse_isa_desc(sys.argv[1])
|