isa_parser.py revision 6986:f4895857bb48
1# Copyright (c) 2003-2005 The Regents of The University of Michigan 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright 9# notice, this list of conditions and the following disclaimer in the 10# documentation and/or other materials provided with the distribution; 11# neither the name of the copyright holders nor the names of its 12# contributors may be used to endorse or promote products derived from 13# this software without specific prior written permission. 14# 15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# 27# Authors: Steve Reinhardt 28 29import os 30import sys 31import re 32import string 33import inspect, traceback 34# get type names 35from types import * 36 37from m5.util.grammar import Grammar 38 39################### 40# Utility functions 41 42# 43# Indent every line in string 's' by two spaces 44# (except preprocessor directives). 45# Used to make nested code blocks look pretty. 46# 47def indent(s): 48 return re.sub(r'(?m)^(?!#)', ' ', s) 49 50# 51# Munge a somewhat arbitrarily formatted piece of Python code 52# (e.g. from a format 'let' block) into something whose indentation 53# will get by the Python parser. 54# 55# The two keys here are that Python will give a syntax error if 56# there's any whitespace at the beginning of the first line, and that 57# all lines at the same lexical nesting level must have identical 58# indentation. Unfortunately the way code literals work, an entire 59# let block tends to have some initial indentation. Rather than 60# trying to figure out what that is and strip it off, we prepend 'if 61# 1:' to make the let code the nested block inside the if (and have 62# the parser automatically deal with the indentation for us). 63# 64# We don't want to do this if (1) the code block is empty or (2) the 65# first line of the block doesn't have any whitespace at the front. 66 67def fixPythonIndentation(s): 68 # get rid of blank lines first 69 s = re.sub(r'(?m)^\s*\n', '', s); 70 if (s != '' and re.match(r'[ \t]', s[0])): 71 s = 'if 1:\n' + s 72 return s 73 74class ISAParserError(Exception): 75 """Error handler for parser errors""" 76 def __init__(self, first, second=None): 77 if second is None: 78 self.lineno = 0 79 self.string = first 80 else: 81 if hasattr(first, 'lexer'): 82 first = first.lexer.lineno 83 self.lineno = first 84 self.string = second 85 86 def display(self, filename_stack, print_traceback=False): 87 # Output formatted to work under Emacs compile-mode. Optional 88 # 'print_traceback' arg, if set to True, prints a Python stack 89 # backtrace too (can be handy when trying to debug the parser 90 # itself). 91 92 spaces = "" 93 for (filename, line) in filename_stack[:-1]: 94 print "%sIn file included from %s:" % (spaces, filename) 95 spaces += " " 96 97 # Print a Python stack backtrace if requested. 98 if print_traceback or not self.lineno: 99 traceback.print_exc() 100 101 line_str = "%s:" % (filename_stack[-1][0], ) 102 if self.lineno: 103 line_str += "%d:" % (self.lineno, ) 104 105 return "%s%s %s" % (spaces, line_str, self.string) 106 107 def exit(self, filename_stack, print_traceback=False): 108 # Just call exit. 109 110 sys.exit(self.display(filename_stack, print_traceback)) 111 112def error(*args): 113 raise ISAParserError(*args) 114 115#################### 116# Template objects. 117# 118# Template objects are format strings that allow substitution from 119# the attribute spaces of other objects (e.g. InstObjParams instances). 120 121labelRE = re.compile(r'(?<!%)%\(([^\)]+)\)[sd]') 122 123class Template(object): 124 def __init__(self, t): 125 self.template = t 126 127 def subst(self, d): 128 myDict = None 129 130 # Protect non-Python-dict substitutions (e.g. if there's a printf 131 # in the templated C++ code) 132 template = protect_non_subst_percents(self.template) 133 # CPU-model-specific substitutions are handled later (in GenCode). 134 template = protect_cpu_symbols(template) 135 136 # Build a dict ('myDict') to use for the template substitution. 137 # Start with the template namespace. Make a copy since we're 138 # going to modify it. 139 myDict = parser.templateMap.copy() 140 141 if isinstance(d, InstObjParams): 142 # If we're dealing with an InstObjParams object, we need 143 # to be a little more sophisticated. The instruction-wide 144 # parameters are already formed, but the parameters which 145 # are only function wide still need to be generated. 146 compositeCode = '' 147 148 myDict.update(d.__dict__) 149 # The "operands" and "snippets" attributes of the InstObjParams 150 # objects are for internal use and not substitution. 151 del myDict['operands'] 152 del myDict['snippets'] 153 154 snippetLabels = [l for l in labelRE.findall(template) 155 if d.snippets.has_key(l)] 156 157 snippets = dict([(s, mungeSnippet(d.snippets[s])) 158 for s in snippetLabels]) 159 160 myDict.update(snippets) 161 162 compositeCode = ' '.join(map(str, snippets.values())) 163 164 # Add in template itself in case it references any 165 # operands explicitly (like Mem) 166 compositeCode += ' ' + template 167 168 operands = SubOperandList(compositeCode, d.operands) 169 170 myDict['op_decl'] = operands.concatAttrStrings('op_decl') 171 172 is_src = lambda op: op.is_src 173 is_dest = lambda op: op.is_dest 174 175 myDict['op_src_decl'] = \ 176 operands.concatSomeAttrStrings(is_src, 'op_src_decl') 177 myDict['op_dest_decl'] = \ 178 operands.concatSomeAttrStrings(is_dest, 'op_dest_decl') 179 180 myDict['op_rd'] = operands.concatAttrStrings('op_rd') 181 myDict['op_wb'] = operands.concatAttrStrings('op_wb') 182 183 if d.operands.memOperand: 184 myDict['mem_acc_size'] = d.operands.memOperand.mem_acc_size 185 myDict['mem_acc_type'] = d.operands.memOperand.mem_acc_type 186 187 elif isinstance(d, dict): 188 # if the argument is a dictionary, we just use it. 189 myDict.update(d) 190 elif hasattr(d, '__dict__'): 191 # if the argument is an object, we use its attribute map. 192 myDict.update(d.__dict__) 193 else: 194 raise TypeError, "Template.subst() arg must be or have dictionary" 195 return template % myDict 196 197 # Convert to string. This handles the case when a template with a 198 # CPU-specific term gets interpolated into another template or into 199 # an output block. 200 def __str__(self): 201 return expand_cpu_symbols_to_string(self.template) 202 203################ 204# Format object. 205# 206# A format object encapsulates an instruction format. It must provide 207# a defineInst() method that generates the code for an instruction 208# definition. 209 210exportContextSymbols = ('InstObjParams', 'makeList', 're', 'string') 211 212exportContext = {} 213 214def updateExportContext(): 215 exportContext.update(exportDict(*exportContextSymbols)) 216 exportContext.update(parser.templateMap) 217 218def exportDict(*symNames): 219 return dict([(s, eval(s)) for s in symNames]) 220 221 222class Format(object): 223 def __init__(self, id, params, code): 224 # constructor: just save away arguments 225 self.id = id 226 self.params = params 227 label = 'def format ' + id 228 self.user_code = compile(fixPythonIndentation(code), label, 'exec') 229 param_list = string.join(params, ", ") 230 f = '''def defInst(_code, _context, %s): 231 my_locals = vars().copy() 232 exec _code in _context, my_locals 233 return my_locals\n''' % param_list 234 c = compile(f, label + ' wrapper', 'exec') 235 exec c 236 self.func = defInst 237 238 def defineInst(self, name, args, lineno): 239 context = {} 240 updateExportContext() 241 context.update(exportContext) 242 if len(name): 243 Name = name[0].upper() 244 if len(name) > 1: 245 Name += name[1:] 246 context.update({ 'name': name, 'Name': Name }) 247 try: 248 vars = self.func(self.user_code, context, *args[0], **args[1]) 249 except Exception, exc: 250 error(lineno, 'error defining "%s": %s.' % (name, exc)) 251 for k in vars.keys(): 252 if k not in ('header_output', 'decoder_output', 253 'exec_output', 'decode_block'): 254 del vars[k] 255 return GenCode(**vars) 256 257# Special null format to catch an implicit-format instruction 258# definition outside of any format block. 259class NoFormat(object): 260 def __init__(self): 261 self.defaultInst = '' 262 263 def defineInst(self, name, args, lineno): 264 error(lineno, 265 'instruction definition "%s" with no active format!' % name) 266 267# This dictionary maps format name strings to Format objects. 268formatMap = {} 269 270# Define a new format 271def defFormat(id, params, code, lineno): 272 # make sure we haven't already defined this one 273 if formatMap.get(id, None) != None: 274 error(lineno, 'format %s redefined.' % id) 275 # create new object and store in global map 276 formatMap[id] = Format(id, params, code) 277 278##################################################################### 279# 280# Support Classes 281# 282##################################################################### 283 284# Expand template with CPU-specific references into a dictionary with 285# an entry for each CPU model name. The entry key is the model name 286# and the corresponding value is the template with the CPU-specific 287# refs substituted for that model. 288def expand_cpu_symbols_to_dict(template): 289 # Protect '%'s that don't go with CPU-specific terms 290 t = re.sub(r'%(?!\(CPU_)', '%%', template) 291 result = {} 292 for cpu in cpu_models: 293 result[cpu.name] = t % cpu.strings 294 return result 295 296# *If* the template has CPU-specific references, return a single 297# string containing a copy of the template for each CPU model with the 298# corresponding values substituted in. If the template has no 299# CPU-specific references, it is returned unmodified. 300def expand_cpu_symbols_to_string(template): 301 if template.find('%(CPU_') != -1: 302 return reduce(lambda x,y: x+y, 303 expand_cpu_symbols_to_dict(template).values()) 304 else: 305 return template 306 307# Protect CPU-specific references by doubling the corresponding '%'s 308# (in preparation for substituting a different set of references into 309# the template). 310def protect_cpu_symbols(template): 311 return re.sub(r'%(?=\(CPU_)', '%%', template) 312 313# Protect any non-dict-substitution '%'s in a format string 314# (i.e. those not followed by '(') 315def protect_non_subst_percents(s): 316 return re.sub(r'%(?!\()', '%%', s) 317 318############### 319# GenCode class 320# 321# The GenCode class encapsulates generated code destined for various 322# output files. The header_output and decoder_output attributes are 323# strings containing code destined for decoder.hh and decoder.cc 324# respectively. The decode_block attribute contains code to be 325# incorporated in the decode function itself (that will also end up in 326# decoder.cc). The exec_output attribute is a dictionary with a key 327# for each CPU model name; the value associated with a particular key 328# is the string of code for that CPU model's exec.cc file. The 329# has_decode_default attribute is used in the decode block to allow 330# explicit default clauses to override default default clauses. 331 332class GenCode(object): 333 # Constructor. At this point we substitute out all CPU-specific 334 # symbols. For the exec output, these go into the per-model 335 # dictionary. For all other output types they get collapsed into 336 # a single string. 337 def __init__(self, 338 header_output = '', decoder_output = '', exec_output = '', 339 decode_block = '', has_decode_default = False): 340 self.header_output = expand_cpu_symbols_to_string(header_output) 341 self.decoder_output = expand_cpu_symbols_to_string(decoder_output) 342 if isinstance(exec_output, dict): 343 self.exec_output = exec_output 344 elif isinstance(exec_output, str): 345 # If the exec_output arg is a single string, we replicate 346 # it for each of the CPU models, substituting and 347 # %(CPU_foo)s params appropriately. 348 self.exec_output = expand_cpu_symbols_to_dict(exec_output) 349 self.decode_block = expand_cpu_symbols_to_string(decode_block) 350 self.has_decode_default = has_decode_default 351 352 # Override '+' operator: generate a new GenCode object that 353 # concatenates all the individual strings in the operands. 354 def __add__(self, other): 355 exec_output = {} 356 for cpu in cpu_models: 357 n = cpu.name 358 exec_output[n] = self.exec_output[n] + other.exec_output[n] 359 return GenCode(self.header_output + other.header_output, 360 self.decoder_output + other.decoder_output, 361 exec_output, 362 self.decode_block + other.decode_block, 363 self.has_decode_default or other.has_decode_default) 364 365 # Prepend a string (typically a comment) to all the strings. 366 def prepend_all(self, pre): 367 self.header_output = pre + self.header_output 368 self.decoder_output = pre + self.decoder_output 369 self.decode_block = pre + self.decode_block 370 for cpu in cpu_models: 371 self.exec_output[cpu.name] = pre + self.exec_output[cpu.name] 372 373 # Wrap the decode block in a pair of strings (e.g., 'case foo:' 374 # and 'break;'). Used to build the big nested switch statement. 375 def wrap_decode_block(self, pre, post = ''): 376 self.decode_block = pre + indent(self.decode_block) + post 377 378##################################################################### 379# 380# Bitfield Operator Support 381# 382##################################################################### 383 384bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>') 385 386bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>') 387bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>') 388 389def substBitOps(code): 390 # first convert single-bit selectors to two-index form 391 # i.e., <n> --> <n:n> 392 code = bitOp1ArgRE.sub(r'<\1:\1>', code) 393 # simple case: selector applied to ID (name) 394 # i.e., foo<a:b> --> bits(foo, a, b) 395 code = bitOpWordRE.sub(r'bits(\1, \2, \3)', code) 396 # if selector is applied to expression (ending in ')'), 397 # we need to search backward for matching '(' 398 match = bitOpExprRE.search(code) 399 while match: 400 exprEnd = match.start() 401 here = exprEnd - 1 402 nestLevel = 1 403 while nestLevel > 0: 404 if code[here] == '(': 405 nestLevel -= 1 406 elif code[here] == ')': 407 nestLevel += 1 408 here -= 1 409 if here < 0: 410 sys.exit("Didn't find '('!") 411 exprStart = here+1 412 newExpr = r'bits(%s, %s, %s)' % (code[exprStart:exprEnd+1], 413 match.group(1), match.group(2)) 414 code = code[:exprStart] + newExpr + code[match.end():] 415 match = bitOpExprRE.search(code) 416 return code 417 418 419##################################################################### 420# 421# Code Parser 422# 423# The remaining code is the support for automatically extracting 424# instruction characteristics from pseudocode. 425# 426##################################################################### 427 428# Force the argument to be a list. Useful for flags, where a caller 429# can specify a singleton flag or a list of flags. Also usful for 430# converting tuples to lists so they can be modified. 431def makeList(arg): 432 if isinstance(arg, list): 433 return arg 434 elif isinstance(arg, tuple): 435 return list(arg) 436 elif not arg: 437 return [] 438 else: 439 return [ arg ] 440 441# Generate operandTypeMap from the user's 'def operand_types' 442# statement. 443def buildOperandTypeMap(user_dict, lineno): 444 global operandTypeMap 445 operandTypeMap = {} 446 for (ext, (desc, size)) in user_dict.iteritems(): 447 if desc == 'signed int': 448 ctype = 'int%d_t' % size 449 is_signed = 1 450 elif desc == 'unsigned int': 451 ctype = 'uint%d_t' % size 452 is_signed = 0 453 elif desc == 'float': 454 is_signed = 1 # shouldn't really matter 455 if size == 32: 456 ctype = 'float' 457 elif size == 64: 458 ctype = 'double' 459 elif desc == 'twin64 int': 460 is_signed = 0 461 ctype = 'Twin64_t' 462 elif desc == 'twin32 int': 463 is_signed = 0 464 ctype = 'Twin32_t' 465 if ctype == '': 466 error(lineno, 'Unrecognized type description "%s" in user_dict') 467 operandTypeMap[ext] = (size, ctype, is_signed) 468 469class Operand(object): 470 '''Base class for operand descriptors. An instance of this class 471 (or actually a class derived from this one) represents a specific 472 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate 473 derived classes encapsulates the traits of a particular operand 474 type (e.g., "32-bit integer register").''' 475 476 def buildReadCode(self, func = None): 477 code = self.read_code % {"name": self.base_name, 478 "func": func, 479 "op_idx": self.src_reg_idx, 480 "reg_idx": self.reg_spec, 481 "size": self.size, 482 "ctype": self.ctype} 483 if self.size != self.dflt_size: 484 return '%s = bits(%s, %d, 0);\n' % \ 485 (self.base_name, code, self.size-1) 486 else: 487 return '%s = %s;\n' % \ 488 (self.base_name, code) 489 490 def buildWriteCode(self, func = None): 491 if (self.size != self.dflt_size and self.is_signed): 492 final_val = 'sext<%d>(%s)' % (self.size, self.base_name) 493 else: 494 final_val = self.base_name 495 code = self.write_code % {"name": self.base_name, 496 "func": func, 497 "op_idx": self.dest_reg_idx, 498 "reg_idx": self.reg_spec, 499 "size": self.size, 500 "ctype": self.ctype, 501 "final_val": final_val} 502 return ''' 503 { 504 %s final_val = %s; 505 %s; 506 if (traceData) { traceData->setData(final_val); } 507 }''' % (self.dflt_ctype, final_val, code) 508 509 def __init__(self, full_name, ext, is_src, is_dest): 510 self.full_name = full_name 511 self.ext = ext 512 self.is_src = is_src 513 self.is_dest = is_dest 514 # The 'effective extension' (eff_ext) is either the actual 515 # extension, if one was explicitly provided, or the default. 516 if ext: 517 self.eff_ext = ext 518 else: 519 self.eff_ext = self.dflt_ext 520 521 (self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext] 522 523 # note that mem_acc_size is undefined for non-mem operands... 524 # template must be careful not to use it if it doesn't apply. 525 if self.isMem(): 526 self.mem_acc_size = self.makeAccSize() 527 if self.ctype in ['Twin32_t', 'Twin64_t']: 528 self.mem_acc_type = 'Twin' 529 else: 530 self.mem_acc_type = 'uint' 531 532 # Finalize additional fields (primarily code fields). This step 533 # is done separately since some of these fields may depend on the 534 # register index enumeration that hasn't been performed yet at the 535 # time of __init__(). 536 def finalize(self): 537 self.flags = self.getFlags() 538 self.constructor = self.makeConstructor() 539 self.op_decl = self.makeDecl() 540 541 if self.is_src: 542 self.op_rd = self.makeRead() 543 self.op_src_decl = self.makeDecl() 544 else: 545 self.op_rd = '' 546 self.op_src_decl = '' 547 548 if self.is_dest: 549 self.op_wb = self.makeWrite() 550 self.op_dest_decl = self.makeDecl() 551 else: 552 self.op_wb = '' 553 self.op_dest_decl = '' 554 555 def isMem(self): 556 return 0 557 558 def isReg(self): 559 return 0 560 561 def isFloatReg(self): 562 return 0 563 564 def isIntReg(self): 565 return 0 566 567 def isControlReg(self): 568 return 0 569 570 def getFlags(self): 571 # note the empty slice '[:]' gives us a copy of self.flags[0] 572 # instead of a reference to it 573 my_flags = self.flags[0][:] 574 if self.is_src: 575 my_flags += self.flags[1] 576 if self.is_dest: 577 my_flags += self.flags[2] 578 return my_flags 579 580 def makeDecl(self): 581 # Note that initializations in the declarations are solely 582 # to avoid 'uninitialized variable' errors from the compiler. 583 return self.ctype + ' ' + self.base_name + ' = 0;\n'; 584 585class IntRegOperand(Operand): 586 def isReg(self): 587 return 1 588 589 def isIntReg(self): 590 return 1 591 592 def makeConstructor(self): 593 c = '' 594 if self.is_src: 595 c += '\n\t_srcRegIdx[%d] = %s;' % \ 596 (self.src_reg_idx, self.reg_spec) 597 if self.is_dest: 598 c += '\n\t_destRegIdx[%d] = %s;' % \ 599 (self.dest_reg_idx, self.reg_spec) 600 return c 601 602 def makeRead(self): 603 if (self.ctype == 'float' or self.ctype == 'double'): 604 error('Attempt to read integer register as FP') 605 if self.read_code != None: 606 return self.buildReadCode('readIntRegOperand') 607 if (self.size == self.dflt_size): 608 return '%s = xc->readIntRegOperand(this, %d);\n' % \ 609 (self.base_name, self.src_reg_idx) 610 elif (self.size > self.dflt_size): 611 int_reg_val = 'xc->readIntRegOperand(this, %d)' % \ 612 (self.src_reg_idx) 613 if (self.is_signed): 614 int_reg_val = 'sext<%d>(%s)' % (self.dflt_size, int_reg_val) 615 return '%s = %s;\n' % (self.base_name, int_reg_val) 616 else: 617 return '%s = bits(xc->readIntRegOperand(this, %d), %d, 0);\n' % \ 618 (self.base_name, self.src_reg_idx, self.size-1) 619 620 def makeWrite(self): 621 if (self.ctype == 'float' or self.ctype == 'double'): 622 error('Attempt to write integer register as FP') 623 if self.write_code != None: 624 return self.buildWriteCode('setIntRegOperand') 625 if (self.size != self.dflt_size and self.is_signed): 626 final_val = 'sext<%d>(%s)' % (self.size, self.base_name) 627 else: 628 final_val = self.base_name 629 wb = ''' 630 { 631 %s final_val = %s; 632 xc->setIntRegOperand(this, %d, final_val);\n 633 if (traceData) { traceData->setData(final_val); } 634 }''' % (self.dflt_ctype, final_val, self.dest_reg_idx) 635 return wb 636 637class FloatRegOperand(Operand): 638 def isReg(self): 639 return 1 640 641 def isFloatReg(self): 642 return 1 643 644 def makeConstructor(self): 645 c = '' 646 if self.is_src: 647 c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \ 648 (self.src_reg_idx, self.reg_spec) 649 if self.is_dest: 650 c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \ 651 (self.dest_reg_idx, self.reg_spec) 652 return c 653 654 def makeRead(self): 655 bit_select = 0 656 if (self.ctype == 'float' or self.ctype == 'double'): 657 func = 'readFloatRegOperand' 658 else: 659 func = 'readFloatRegOperandBits' 660 if (self.size != self.dflt_size): 661 bit_select = 1 662 base = 'xc->%s(this, %d)' % (func, self.src_reg_idx) 663 if self.read_code != None: 664 return self.buildReadCode(func) 665 if bit_select: 666 return '%s = bits(%s, %d, 0);\n' % \ 667 (self.base_name, base, self.size-1) 668 else: 669 return '%s = %s;\n' % (self.base_name, base) 670 671 def makeWrite(self): 672 final_val = self.base_name 673 final_ctype = self.ctype 674 if (self.ctype == 'float' or self.ctype == 'double'): 675 func = 'setFloatRegOperand' 676 elif (self.ctype == 'uint32_t' or self.ctype == 'uint64_t'): 677 func = 'setFloatRegOperandBits' 678 else: 679 func = 'setFloatRegOperandBits' 680 final_ctype = 'uint%d_t' % self.dflt_size 681 if (self.size != self.dflt_size and self.is_signed): 682 final_val = 'sext<%d>(%s)' % (self.size, self.base_name) 683 if self.write_code != None: 684 return self.buildWriteCode(func) 685 wb = ''' 686 { 687 %s final_val = %s; 688 xc->%s(this, %d, final_val);\n 689 if (traceData) { traceData->setData(final_val); } 690 }''' % (final_ctype, final_val, func, self.dest_reg_idx) 691 return wb 692 693class ControlRegOperand(Operand): 694 def isReg(self): 695 return 1 696 697 def isControlReg(self): 698 return 1 699 700 def makeConstructor(self): 701 c = '' 702 if self.is_src: 703 c += '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \ 704 (self.src_reg_idx, self.reg_spec) 705 if self.is_dest: 706 c += '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \ 707 (self.dest_reg_idx, self.reg_spec) 708 return c 709 710 def makeRead(self): 711 bit_select = 0 712 if (self.ctype == 'float' or self.ctype == 'double'): 713 error('Attempt to read control register as FP') 714 if self.read_code != None: 715 return self.buildReadCode('readMiscRegOperand') 716 base = 'xc->readMiscRegOperand(this, %s)' % self.src_reg_idx 717 if self.size == self.dflt_size: 718 return '%s = %s;\n' % (self.base_name, base) 719 else: 720 return '%s = bits(%s, %d, 0);\n' % \ 721 (self.base_name, base, self.size-1) 722 723 def makeWrite(self): 724 if (self.ctype == 'float' or self.ctype == 'double'): 725 error('Attempt to write control register as FP') 726 if self.write_code != None: 727 return self.buildWriteCode('setMiscRegOperand') 728 wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \ 729 (self.dest_reg_idx, self.base_name) 730 wb += 'if (traceData) { traceData->setData(%s); }' % \ 731 self.base_name 732 return wb 733 734class MemOperand(Operand): 735 def isMem(self): 736 return 1 737 738 def makeConstructor(self): 739 return '' 740 741 def makeDecl(self): 742 # Note that initializations in the declarations are solely 743 # to avoid 'uninitialized variable' errors from the compiler. 744 # Declare memory data variable. 745 if self.ctype in ['Twin32_t','Twin64_t']: 746 return "%s %s; %s.a = 0; %s.b = 0;\n" % \ 747 (self.ctype, self.base_name, self.base_name, self.base_name) 748 return '%s %s = 0;\n' % (self.ctype, self.base_name) 749 750 def makeRead(self): 751 if self.read_code != None: 752 return self.buildReadCode() 753 return '' 754 755 def makeWrite(self): 756 if self.write_code != None: 757 return self.buildWriteCode() 758 return '' 759 760 # Return the memory access size *in bits*, suitable for 761 # forming a type via "uint%d_t". Divide by 8 if you want bytes. 762 def makeAccSize(self): 763 return self.size 764 765class PCOperand(Operand): 766 def makeConstructor(self): 767 return '' 768 769 def makeRead(self): 770 return '%s = xc->readPC();\n' % self.base_name 771 772 def makeWrite(self): 773 return 'xc->setPC(%s);\n' % self.base_name 774 775class UPCOperand(Operand): 776 def makeConstructor(self): 777 return '' 778 779 def makeRead(self): 780 if self.read_code != None: 781 return self.buildReadCode('readMicroPC') 782 return '%s = xc->readMicroPC();\n' % self.base_name 783 784 def makeWrite(self): 785 if self.write_code != None: 786 return self.buildWriteCode('setMicroPC') 787 return 'xc->setMicroPC(%s);\n' % self.base_name 788 789class NUPCOperand(Operand): 790 def makeConstructor(self): 791 return '' 792 793 def makeRead(self): 794 if self.read_code != None: 795 return self.buildReadCode('readNextMicroPC') 796 return '%s = xc->readNextMicroPC();\n' % self.base_name 797 798 def makeWrite(self): 799 if self.write_code != None: 800 return self.buildWriteCode('setNextMicroPC') 801 return 'xc->setNextMicroPC(%s);\n' % self.base_name 802 803class NPCOperand(Operand): 804 def makeConstructor(self): 805 return '' 806 807 def makeRead(self): 808 if self.read_code != None: 809 return self.buildReadCode('readNextPC') 810 return '%s = xc->readNextPC();\n' % self.base_name 811 812 def makeWrite(self): 813 if self.write_code != None: 814 return self.buildWriteCode('setNextPC') 815 return 'xc->setNextPC(%s);\n' % self.base_name 816 817class NNPCOperand(Operand): 818 def makeConstructor(self): 819 return '' 820 821 def makeRead(self): 822 if self.read_code != None: 823 return self.buildReadCode('readNextNPC') 824 return '%s = xc->readNextNPC();\n' % self.base_name 825 826 def makeWrite(self): 827 if self.write_code != None: 828 return self.buildWriteCode('setNextNPC') 829 return 'xc->setNextNPC(%s);\n' % self.base_name 830 831def buildOperandNameMap(user_dict, lineno): 832 global operandNameMap 833 operandNameMap = {} 834 for (op_name, val) in user_dict.iteritems(): 835 (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val[:5] 836 if len(val) > 5: 837 read_code = val[5] 838 else: 839 read_code = None 840 if len(val) > 6: 841 write_code = val[6] 842 else: 843 write_code = None 844 if len(val) > 7: 845 error(lineno, 846 'error: too many attributes for operand "%s"' % 847 base_cls_name) 848 849 (dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext] 850 # Canonical flag structure is a triple of lists, where each list 851 # indicates the set of flags implied by this operand always, when 852 # used as a source, and when used as a dest, respectively. 853 # For simplicity this can be initialized using a variety of fairly 854 # obvious shortcuts; we convert these to canonical form here. 855 if not flags: 856 # no flags specified (e.g., 'None') 857 flags = ( [], [], [] ) 858 elif isinstance(flags, str): 859 # a single flag: assumed to be unconditional 860 flags = ( [ flags ], [], [] ) 861 elif isinstance(flags, list): 862 # a list of flags: also assumed to be unconditional 863 flags = ( flags, [], [] ) 864 elif isinstance(flags, tuple): 865 # it's a tuple: it should be a triple, 866 # but each item could be a single string or a list 867 (uncond_flags, src_flags, dest_flags) = flags 868 flags = (makeList(uncond_flags), 869 makeList(src_flags), makeList(dest_flags)) 870 # Accumulate attributes of new operand class in tmp_dict 871 tmp_dict = {} 872 for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri', 873 'dflt_size', 'dflt_ctype', 'dflt_is_signed', 874 'read_code', 'write_code'): 875 tmp_dict[attr] = eval(attr) 876 tmp_dict['base_name'] = op_name 877 # New class name will be e.g. "IntReg_Ra" 878 cls_name = base_cls_name + '_' + op_name 879 # Evaluate string arg to get class object. Note that the 880 # actual base class for "IntReg" is "IntRegOperand", i.e. we 881 # have to append "Operand". 882 try: 883 base_cls = eval(base_cls_name + 'Operand') 884 except NameError: 885 error(lineno, 886 'error: unknown operand base class "%s"' % base_cls_name) 887 # The following statement creates a new class called 888 # <cls_name> as a subclass of <base_cls> with the attributes 889 # in tmp_dict, just as if we evaluated a class declaration. 890 operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict) 891 892 # Define operand variables. 893 operands = user_dict.keys() 894 895 operandsREString = (r''' 896 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches 897 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix 898 (?![\w\.]) # neg. lookahead assertion: prevent partial matches 899 ''' 900 % string.join(operands, '|')) 901 902 global operandsRE 903 operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) 904 905 # Same as operandsREString, but extension is mandatory, and only two 906 # groups are returned (base and ext, not full name as above). 907 # Used for subtituting '_' for '.' to make C++ identifiers. 908 operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])' 909 % string.join(operands, '|')) 910 911 global operandsWithExtRE 912 operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE) 913 914maxInstSrcRegs = 0 915maxInstDestRegs = 0 916 917class OperandList(object): 918 '''Find all the operands in the given code block. Returns an operand 919 descriptor list (instance of class OperandList).''' 920 def __init__(self, code): 921 self.items = [] 922 self.bases = {} 923 # delete comments so we don't match on reg specifiers inside 924 code = commentRE.sub('', code) 925 # search for operands 926 next_pos = 0 927 while 1: 928 match = operandsRE.search(code, next_pos) 929 if not match: 930 # no more matches: we're done 931 break 932 op = match.groups() 933 # regexp groups are operand full name, base, and extension 934 (op_full, op_base, op_ext) = op 935 # if the token following the operand is an assignment, this is 936 # a destination (LHS), else it's a source (RHS) 937 is_dest = (assignRE.match(code, match.end()) != None) 938 is_src = not is_dest 939 # see if we've already seen this one 940 op_desc = self.find_base(op_base) 941 if op_desc: 942 if op_desc.ext != op_ext: 943 error('Inconsistent extensions for operand %s' % \ 944 op_base) 945 op_desc.is_src = op_desc.is_src or is_src 946 op_desc.is_dest = op_desc.is_dest or is_dest 947 else: 948 # new operand: create new descriptor 949 op_desc = operandNameMap[op_base](op_full, op_ext, 950 is_src, is_dest) 951 self.append(op_desc) 952 # start next search after end of current match 953 next_pos = match.end() 954 self.sort() 955 # enumerate source & dest register operands... used in building 956 # constructor later 957 self.numSrcRegs = 0 958 self.numDestRegs = 0 959 self.numFPDestRegs = 0 960 self.numIntDestRegs = 0 961 self.memOperand = None 962 for op_desc in self.items: 963 if op_desc.isReg(): 964 if op_desc.is_src: 965 op_desc.src_reg_idx = self.numSrcRegs 966 self.numSrcRegs += 1 967 if op_desc.is_dest: 968 op_desc.dest_reg_idx = self.numDestRegs 969 self.numDestRegs += 1 970 if op_desc.isFloatReg(): 971 self.numFPDestRegs += 1 972 elif op_desc.isIntReg(): 973 self.numIntDestRegs += 1 974 elif op_desc.isMem(): 975 if self.memOperand: 976 error("Code block has more than one memory operand.") 977 self.memOperand = op_desc 978 global maxInstSrcRegs 979 global maxInstDestRegs 980 if maxInstSrcRegs < self.numSrcRegs: 981 maxInstSrcRegs = self.numSrcRegs 982 if maxInstDestRegs < self.numDestRegs: 983 maxInstDestRegs = self.numDestRegs 984 # now make a final pass to finalize op_desc fields that may depend 985 # on the register enumeration 986 for op_desc in self.items: 987 op_desc.finalize() 988 989 def __len__(self): 990 return len(self.items) 991 992 def __getitem__(self, index): 993 return self.items[index] 994 995 def append(self, op_desc): 996 self.items.append(op_desc) 997 self.bases[op_desc.base_name] = op_desc 998 999 def find_base(self, base_name): 1000 # like self.bases[base_name], but returns None if not found 1001 # (rather than raising exception) 1002 return self.bases.get(base_name) 1003 1004 # internal helper function for concat[Some]Attr{Strings|Lists} 1005 def __internalConcatAttrs(self, attr_name, filter, result): 1006 for op_desc in self.items: 1007 if filter(op_desc): 1008 result += getattr(op_desc, attr_name) 1009 return result 1010 1011 # return a single string that is the concatenation of the (string) 1012 # values of the specified attribute for all operands 1013 def concatAttrStrings(self, attr_name): 1014 return self.__internalConcatAttrs(attr_name, lambda x: 1, '') 1015 1016 # like concatAttrStrings, but only include the values for the operands 1017 # for which the provided filter function returns true 1018 def concatSomeAttrStrings(self, filter, attr_name): 1019 return self.__internalConcatAttrs(attr_name, filter, '') 1020 1021 # return a single list that is the concatenation of the (list) 1022 # values of the specified attribute for all operands 1023 def concatAttrLists(self, attr_name): 1024 return self.__internalConcatAttrs(attr_name, lambda x: 1, []) 1025 1026 # like concatAttrLists, but only include the values for the operands 1027 # for which the provided filter function returns true 1028 def concatSomeAttrLists(self, filter, attr_name): 1029 return self.__internalConcatAttrs(attr_name, filter, []) 1030 1031 def sort(self): 1032 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri) 1033 1034class SubOperandList(OperandList): 1035 '''Find all the operands in the given code block. Returns an operand 1036 descriptor list (instance of class OperandList).''' 1037 def __init__(self, code, master_list): 1038 self.items = [] 1039 self.bases = {} 1040 # delete comments so we don't match on reg specifiers inside 1041 code = commentRE.sub('', code) 1042 # search for operands 1043 next_pos = 0 1044 while 1: 1045 match = operandsRE.search(code, next_pos) 1046 if not match: 1047 # no more matches: we're done 1048 break 1049 op = match.groups() 1050 # regexp groups are operand full name, base, and extension 1051 (op_full, op_base, op_ext) = op 1052 # find this op in the master list 1053 op_desc = master_list.find_base(op_base) 1054 if not op_desc: 1055 error('Found operand %s which is not in the master list!' \ 1056 ' This is an internal error' % op_base) 1057 else: 1058 # See if we've already found this operand 1059 op_desc = self.find_base(op_base) 1060 if not op_desc: 1061 # if not, add a reference to it to this sub list 1062 self.append(master_list.bases[op_base]) 1063 1064 # start next search after end of current match 1065 next_pos = match.end() 1066 self.sort() 1067 self.memOperand = None 1068 for op_desc in self.items: 1069 if op_desc.isMem(): 1070 if self.memOperand: 1071 error("Code block has more than one memory operand.") 1072 self.memOperand = op_desc 1073 1074# Regular expression object to match C++ comments 1075# (used in findOperands()) 1076commentRE = re.compile(r'//.*\n') 1077 1078# Regular expression object to match assignment statements 1079# (used in findOperands()) 1080assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) 1081 1082# Munge operand names in code string to make legal C++ variable names. 1083# This means getting rid of the type extension if any. 1084# (Will match base_name attribute of Operand object.) 1085def substMungedOpNames(code): 1086 return operandsWithExtRE.sub(r'\1', code) 1087 1088# Fix up code snippets for final substitution in templates. 1089def mungeSnippet(s): 1090 if isinstance(s, str): 1091 return substMungedOpNames(substBitOps(s)) 1092 else: 1093 return s 1094 1095def makeFlagConstructor(flag_list): 1096 if len(flag_list) == 0: 1097 return '' 1098 # filter out repeated flags 1099 flag_list.sort() 1100 i = 1 1101 while i < len(flag_list): 1102 if flag_list[i] == flag_list[i-1]: 1103 del flag_list[i] 1104 else: 1105 i += 1 1106 pre = '\n\tflags[' 1107 post = '] = true;' 1108 code = pre + string.join(flag_list, post + pre) + post 1109 return code 1110 1111# Assume all instruction flags are of the form 'IsFoo' 1112instFlagRE = re.compile(r'Is.*') 1113 1114# OpClass constants end in 'Op' except No_OpClass 1115opClassRE = re.compile(r'.*Op|No_OpClass') 1116 1117class InstObjParams(object): 1118 def __init__(self, mnem, class_name, base_class = '', 1119 snippets = {}, opt_args = []): 1120 self.mnemonic = mnem 1121 self.class_name = class_name 1122 self.base_class = base_class 1123 if not isinstance(snippets, dict): 1124 snippets = {'code' : snippets} 1125 compositeCode = ' '.join(map(str, snippets.values())) 1126 self.snippets = snippets 1127 1128 self.operands = OperandList(compositeCode) 1129 self.constructor = self.operands.concatAttrStrings('constructor') 1130 self.constructor += \ 1131 '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs 1132 self.constructor += \ 1133 '\n\t_numDestRegs = %d;' % self.operands.numDestRegs 1134 self.constructor += \ 1135 '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs 1136 self.constructor += \ 1137 '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs 1138 self.flags = self.operands.concatAttrLists('flags') 1139 1140 # Make a basic guess on the operand class (function unit type). 1141 # These are good enough for most cases, and can be overridden 1142 # later otherwise. 1143 if 'IsStore' in self.flags: 1144 self.op_class = 'MemWriteOp' 1145 elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags: 1146 self.op_class = 'MemReadOp' 1147 elif 'IsFloating' in self.flags: 1148 self.op_class = 'FloatAddOp' 1149 else: 1150 self.op_class = 'IntAluOp' 1151 1152 # Optional arguments are assumed to be either StaticInst flags 1153 # or an OpClass value. To avoid having to import a complete 1154 # list of these values to match against, we do it ad-hoc 1155 # with regexps. 1156 for oa in opt_args: 1157 if instFlagRE.match(oa): 1158 self.flags.append(oa) 1159 elif opClassRE.match(oa): 1160 self.op_class = oa 1161 else: 1162 error('InstObjParams: optional arg "%s" not recognized ' 1163 'as StaticInst::Flag or OpClass.' % oa) 1164 1165 # add flag initialization to contructor here to include 1166 # any flags added via opt_args 1167 self.constructor += makeFlagConstructor(self.flags) 1168 1169 # if 'IsFloating' is set, add call to the FP enable check 1170 # function (which should be provided by isa_desc via a declare) 1171 if 'IsFloating' in self.flags: 1172 self.fp_enable_check = 'fault = checkFpEnableFault(xc);' 1173 else: 1174 self.fp_enable_check = '' 1175 1176############## 1177# Stack: a simple stack object. Used for both formats (formatStack) 1178# and default cases (defaultStack). Simply wraps a list to give more 1179# stack-like syntax and enable initialization with an argument list 1180# (as opposed to an argument that's a list). 1181 1182class Stack(list): 1183 def __init__(self, *items): 1184 list.__init__(self, items) 1185 1186 def push(self, item): 1187 self.append(item); 1188 1189 def top(self): 1190 return self[-1] 1191 1192# The global format stack. 1193formatStack = Stack(NoFormat()) 1194 1195# The global default case stack. 1196defaultStack = Stack(None) 1197 1198# Global stack that tracks current file and line number. 1199# Each element is a tuple (filename, lineno) that records the 1200# *current* filename and the line number in the *previous* file where 1201# it was included. 1202fileNameStack = Stack() 1203 1204 1205####################### 1206# 1207# Output file template 1208# 1209 1210file_template = ''' 1211/* 1212 * DO NOT EDIT THIS FILE!!! 1213 * 1214 * It was automatically generated from the ISA description in %(filename)s 1215 */ 1216 1217%(includes)s 1218 1219%(global_output)s 1220 1221namespace %(namespace)s { 1222 1223%(namespace_output)s 1224 1225} // namespace %(namespace)s 1226 1227%(decode_function)s 1228''' 1229 1230max_inst_regs_template = ''' 1231/* 1232 * DO NOT EDIT THIS FILE!!! 1233 * 1234 * It was automatically generated from the ISA description in %(filename)s 1235 */ 1236 1237namespace %(namespace)s { 1238 1239 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d; 1240 const int MaxInstDestRegs = %(MaxInstDestRegs)d; 1241 1242} // namespace %(namespace)s 1243 1244''' 1245 1246class ISAParser(Grammar): 1247 def __init__(self, output_dir): 1248 super(ISAParser, self).__init__() 1249 self.output_dir = output_dir 1250 1251 self.templateMap = {} 1252 1253 ##################################################################### 1254 # 1255 # Lexer 1256 # 1257 # The PLY lexer module takes two things as input: 1258 # - A list of token names (the string list 'tokens') 1259 # - A regular expression describing a match for each token. The 1260 # regexp for token FOO can be provided in two ways: 1261 # - as a string variable named t_FOO 1262 # - as the doc string for a function named t_FOO. In this case, 1263 # the function is also executed, allowing an action to be 1264 # associated with each token match. 1265 # 1266 ##################################################################### 1267 1268 # Reserved words. These are listed separately as they are matched 1269 # using the same regexp as generic IDs, but distinguished in the 1270 # t_ID() function. The PLY documentation suggests this approach. 1271 reserved = ( 1272 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT', 1273 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS', 1274 'OUTPUT', 'SIGNED', 'TEMPLATE' 1275 ) 1276 1277 # List of tokens. The lex module requires this. 1278 tokens = reserved + ( 1279 # identifier 1280 'ID', 1281 1282 # integer literal 1283 'INTLIT', 1284 1285 # string literal 1286 'STRLIT', 1287 1288 # code literal 1289 'CODELIT', 1290 1291 # ( ) [ ] { } < > , ; . : :: * 1292 'LPAREN', 'RPAREN', 1293 'LBRACKET', 'RBRACKET', 1294 'LBRACE', 'RBRACE', 1295 'LESS', 'GREATER', 'EQUALS', 1296 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON', 1297 'ASTERISK', 1298 1299 # C preprocessor directives 1300 'CPPDIRECTIVE' 1301 1302 # The following are matched but never returned. commented out to 1303 # suppress PLY warning 1304 # newfile directive 1305 # 'NEWFILE', 1306 1307 # endfile directive 1308 # 'ENDFILE' 1309 ) 1310 1311 # Regular expressions for token matching 1312 t_LPAREN = r'\(' 1313 t_RPAREN = r'\)' 1314 t_LBRACKET = r'\[' 1315 t_RBRACKET = r'\]' 1316 t_LBRACE = r'\{' 1317 t_RBRACE = r'\}' 1318 t_LESS = r'\<' 1319 t_GREATER = r'\>' 1320 t_EQUALS = r'=' 1321 t_COMMA = r',' 1322 t_SEMI = r';' 1323 t_DOT = r'\.' 1324 t_COLON = r':' 1325 t_DBLCOLON = r'::' 1326 t_ASTERISK = r'\*' 1327 1328 # Identifiers and reserved words 1329 reserved_map = { } 1330 for r in reserved: 1331 reserved_map[r.lower()] = r 1332 1333 def t_ID(self, t): 1334 r'[A-Za-z_]\w*' 1335 t.type = self.reserved_map.get(t.value, 'ID') 1336 return t 1337 1338 # Integer literal 1339 def t_INTLIT(self, t): 1340 r'-?(0x[\da-fA-F]+)|\d+' 1341 try: 1342 t.value = int(t.value,0) 1343 except ValueError: 1344 error(t, 'Integer value "%s" too large' % t.value) 1345 t.value = 0 1346 return t 1347 1348 # String literal. Note that these use only single quotes, and 1349 # can span multiple lines. 1350 def t_STRLIT(self, t): 1351 r"(?m)'([^'])+'" 1352 # strip off quotes 1353 t.value = t.value[1:-1] 1354 t.lexer.lineno += t.value.count('\n') 1355 return t 1356 1357 1358 # "Code literal"... like a string literal, but delimiters are 1359 # '{{' and '}}' so they get formatted nicely under emacs c-mode 1360 def t_CODELIT(self, t): 1361 r"(?m)\{\{([^\}]|}(?!\}))+\}\}" 1362 # strip off {{ & }} 1363 t.value = t.value[2:-2] 1364 t.lexer.lineno += t.value.count('\n') 1365 return t 1366 1367 def t_CPPDIRECTIVE(self, t): 1368 r'^\#[^\#].*\n' 1369 t.lexer.lineno += t.value.count('\n') 1370 return t 1371 1372 def t_NEWFILE(self, t): 1373 r'^\#\#newfile\s+"[\w/.-]*"' 1374 fileNameStack.push((t.value[11:-1], t.lexer.lineno)) 1375 t.lexer.lineno = 0 1376 1377 def t_ENDFILE(self, t): 1378 r'^\#\#endfile' 1379 (old_filename, t.lexer.lineno) = fileNameStack.pop() 1380 1381 # 1382 # The functions t_NEWLINE, t_ignore, and t_error are 1383 # special for the lex module. 1384 # 1385 1386 # Newlines 1387 def t_NEWLINE(self, t): 1388 r'\n+' 1389 t.lexer.lineno += t.value.count('\n') 1390 1391 # Comments 1392 def t_comment(self, t): 1393 r'//.*' 1394 1395 # Completely ignored characters 1396 t_ignore = ' \t\x0c' 1397 1398 # Error handler 1399 def t_error(self, t): 1400 error(t, "illegal character '%s'" % t.value[0]) 1401 t.skip(1) 1402 1403 ##################################################################### 1404 # 1405 # Parser 1406 # 1407 # Every function whose name starts with 'p_' defines a grammar 1408 # rule. The rule is encoded in the function's doc string, while 1409 # the function body provides the action taken when the rule is 1410 # matched. The argument to each function is a list of the values 1411 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the 1412 # symbols on the RHS. For tokens, the value is copied from the 1413 # t.value attribute provided by the lexer. For non-terminals, the 1414 # value is assigned by the producing rule; i.e., the job of the 1415 # grammar rule function is to set the value for the non-terminal 1416 # on the LHS (by assigning to t[0]). 1417 ##################################################################### 1418 1419 # The LHS of the first grammar rule is used as the start symbol 1420 # (in this case, 'specification'). Note that this rule enforces 1421 # that there will be exactly one namespace declaration, with 0 or 1422 # more global defs/decls before and after it. The defs & decls 1423 # before the namespace decl will be outside the namespace; those 1424 # after will be inside. The decoder function is always inside the 1425 # namespace. 1426 def p_specification(self, t): 1427 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block' 1428 global_code = t[1] 1429 isa_name = t[2] 1430 namespace = isa_name + "Inst" 1431 # wrap the decode block as a function definition 1432 t[4].wrap_decode_block(''' 1433StaticInstPtr 1434%(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst) 1435{ 1436 using namespace %(namespace)s; 1437''' % vars(), '}') 1438 # both the latter output blocks and the decode block are in 1439 # the namespace 1440 namespace_code = t[3] + t[4] 1441 # pass it all back to the caller of yacc.parse() 1442 t[0] = (isa_name, namespace, global_code, namespace_code) 1443 1444 # ISA name declaration looks like "namespace <foo>;" 1445 def p_name_decl(self, t): 1446 'name_decl : NAMESPACE ID SEMI' 1447 t[0] = t[2] 1448 1449 # 'opt_defs_and_outputs' is a possibly empty sequence of 1450 # def and/or output statements. 1451 def p_opt_defs_and_outputs_0(self, t): 1452 'opt_defs_and_outputs : empty' 1453 t[0] = GenCode() 1454 1455 def p_opt_defs_and_outputs_1(self, t): 1456 'opt_defs_and_outputs : defs_and_outputs' 1457 t[0] = t[1] 1458 1459 def p_defs_and_outputs_0(self, t): 1460 'defs_and_outputs : def_or_output' 1461 t[0] = t[1] 1462 1463 def p_defs_and_outputs_1(self, t): 1464 'defs_and_outputs : defs_and_outputs def_or_output' 1465 t[0] = t[1] + t[2] 1466 1467 # The list of possible definition/output statements. 1468 def p_def_or_output(self, t): 1469 '''def_or_output : def_format 1470 | def_bitfield 1471 | def_bitfield_struct 1472 | def_template 1473 | def_operand_types 1474 | def_operands 1475 | output_header 1476 | output_decoder 1477 | output_exec 1478 | global_let''' 1479 t[0] = t[1] 1480 1481 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied 1482 # directly to the appropriate output section. 1483 1484 # Massage output block by substituting in template definitions and 1485 # bit operators. We handle '%'s embedded in the string that don't 1486 # indicate template substitutions (or CPU-specific symbols, which 1487 # get handled in GenCode) by doubling them first so that the 1488 # format operation will reduce them back to single '%'s. 1489 def process_output(self, s): 1490 s = protect_non_subst_percents(s) 1491 # protects cpu-specific symbols too 1492 s = protect_cpu_symbols(s) 1493 return substBitOps(s % self.templateMap) 1494 1495 def p_output_header(self, t): 1496 'output_header : OUTPUT HEADER CODELIT SEMI' 1497 t[0] = GenCode(header_output = self.process_output(t[3])) 1498 1499 def p_output_decoder(self, t): 1500 'output_decoder : OUTPUT DECODER CODELIT SEMI' 1501 t[0] = GenCode(decoder_output = self.process_output(t[3])) 1502 1503 def p_output_exec(self, t): 1504 'output_exec : OUTPUT EXEC CODELIT SEMI' 1505 t[0] = GenCode(exec_output = self.process_output(t[3])) 1506 1507 # global let blocks 'let {{...}}' (Python code blocks) are 1508 # executed directly when seen. Note that these execute in a 1509 # special variable context 'exportContext' to prevent the code 1510 # from polluting this script's namespace. 1511 def p_global_let(self, t): 1512 'global_let : LET CODELIT SEMI' 1513 updateExportContext() 1514 exportContext["header_output"] = '' 1515 exportContext["decoder_output"] = '' 1516 exportContext["exec_output"] = '' 1517 exportContext["decode_block"] = '' 1518 try: 1519 exec fixPythonIndentation(t[2]) in exportContext 1520 except Exception, exc: 1521 error(t, 'error: %s in global let block "%s".' % (exc, t[2])) 1522 t[0] = GenCode(header_output = exportContext["header_output"], 1523 decoder_output = exportContext["decoder_output"], 1524 exec_output = exportContext["exec_output"], 1525 decode_block = exportContext["decode_block"]) 1526 1527 # Define the mapping from operand type extensions to C++ types and 1528 # bit widths (stored in operandTypeMap). 1529 def p_def_operand_types(self, t): 1530 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' 1531 try: 1532 user_dict = eval('{' + t[3] + '}') 1533 except Exception, exc: 1534 error(t, 1535 'error: %s in def operand_types block "%s".' % (exc, t[3])) 1536 buildOperandTypeMap(user_dict, t.lexer.lineno) 1537 t[0] = GenCode() # contributes nothing to the output C++ file 1538 1539 # Define the mapping from operand names to operand classes and 1540 # other traits. Stored in operandNameMap. 1541 def p_def_operands(self, t): 1542 'def_operands : DEF OPERANDS CODELIT SEMI' 1543 if not globals().has_key('operandTypeMap'): 1544 error(t, 'error: operand types must be defined before operands') 1545 try: 1546 user_dict = eval('{' + t[3] + '}', exportContext) 1547 except Exception, exc: 1548 error(t, 'error: %s in def operands block "%s".' % (exc, t[3])) 1549 buildOperandNameMap(user_dict, t.lexer.lineno) 1550 t[0] = GenCode() # contributes nothing to the output C++ file 1551 1552 # A bitfield definition looks like: 1553 # 'def [signed] bitfield <ID> [<first>:<last>]' 1554 # This generates a preprocessor macro in the output file. 1555 def p_def_bitfield_0(self, t): 1556 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' 1557 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) 1558 if (t[2] == 'signed'): 1559 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr) 1560 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 1561 t[0] = GenCode(header_output = hash_define) 1562 1563 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]' 1564 def p_def_bitfield_1(self, t): 1565 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI' 1566 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6]) 1567 if (t[2] == 'signed'): 1568 expr = 'sext<%d>(%s)' % (1, expr) 1569 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 1570 t[0] = GenCode(header_output = hash_define) 1571 1572 # alternate form for structure member: 'def bitfield <ID> <ID>' 1573 def p_def_bitfield_struct(self, t): 1574 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' 1575 if (t[2] != ''): 1576 error(t, 'error: structure bitfields are always unsigned.') 1577 expr = 'machInst.%s' % t[5] 1578 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 1579 t[0] = GenCode(header_output = hash_define) 1580 1581 def p_id_with_dot_0(self, t): 1582 'id_with_dot : ID' 1583 t[0] = t[1] 1584 1585 def p_id_with_dot_1(self, t): 1586 'id_with_dot : ID DOT id_with_dot' 1587 t[0] = t[1] + t[2] + t[3] 1588 1589 def p_opt_signed_0(self, t): 1590 'opt_signed : SIGNED' 1591 t[0] = t[1] 1592 1593 def p_opt_signed_1(self, t): 1594 'opt_signed : empty' 1595 t[0] = '' 1596 1597 def p_def_template(self, t): 1598 'def_template : DEF TEMPLATE ID CODELIT SEMI' 1599 self.templateMap[t[3]] = Template(t[4]) 1600 t[0] = GenCode() 1601 1602 # An instruction format definition looks like 1603 # "def format <fmt>(<params>) {{...}};" 1604 def p_def_format(self, t): 1605 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' 1606 (id, params, code) = (t[3], t[5], t[7]) 1607 defFormat(id, params, code, t.lexer.lineno) 1608 t[0] = GenCode() 1609 1610 # The formal parameter list for an instruction format is a 1611 # possibly empty list of comma-separated parameters. Positional 1612 # (standard, non-keyword) parameters must come first, followed by 1613 # keyword parameters, followed by a '*foo' parameter that gets 1614 # excess positional arguments (as in Python). Each of these three 1615 # parameter categories is optional. 1616 # 1617 # Note that we do not support the '**foo' parameter for collecting 1618 # otherwise undefined keyword args. Otherwise the parameter list 1619 # is (I believe) identical to what is supported in Python. 1620 # 1621 # The param list generates a tuple, where the first element is a 1622 # list of the positional params and the second element is a dict 1623 # containing the keyword params. 1624 def p_param_list_0(self, t): 1625 'param_list : positional_param_list COMMA nonpositional_param_list' 1626 t[0] = t[1] + t[3] 1627 1628 def p_param_list_1(self, t): 1629 '''param_list : positional_param_list 1630 | nonpositional_param_list''' 1631 t[0] = t[1] 1632 1633 def p_positional_param_list_0(self, t): 1634 'positional_param_list : empty' 1635 t[0] = [] 1636 1637 def p_positional_param_list_1(self, t): 1638 'positional_param_list : ID' 1639 t[0] = [t[1]] 1640 1641 def p_positional_param_list_2(self, t): 1642 'positional_param_list : positional_param_list COMMA ID' 1643 t[0] = t[1] + [t[3]] 1644 1645 def p_nonpositional_param_list_0(self, t): 1646 'nonpositional_param_list : keyword_param_list COMMA excess_args_param' 1647 t[0] = t[1] + t[3] 1648 1649 def p_nonpositional_param_list_1(self, t): 1650 '''nonpositional_param_list : keyword_param_list 1651 | excess_args_param''' 1652 t[0] = t[1] 1653 1654 def p_keyword_param_list_0(self, t): 1655 'keyword_param_list : keyword_param' 1656 t[0] = [t[1]] 1657 1658 def p_keyword_param_list_1(self, t): 1659 'keyword_param_list : keyword_param_list COMMA keyword_param' 1660 t[0] = t[1] + [t[3]] 1661 1662 def p_keyword_param(self, t): 1663 'keyword_param : ID EQUALS expr' 1664 t[0] = t[1] + ' = ' + t[3].__repr__() 1665 1666 def p_excess_args_param(self, t): 1667 'excess_args_param : ASTERISK ID' 1668 # Just concatenate them: '*ID'. Wrap in list to be consistent 1669 # with positional_param_list and keyword_param_list. 1670 t[0] = [t[1] + t[2]] 1671 1672 # End of format definition-related rules. 1673 ############## 1674 1675 # 1676 # A decode block looks like: 1677 # decode <field1> [, <field2>]* [default <inst>] { ... } 1678 # 1679 def p_decode_block(self, t): 1680 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' 1681 default_defaults = defaultStack.pop() 1682 codeObj = t[5] 1683 # use the "default defaults" only if there was no explicit 1684 # default statement in decode_stmt_list 1685 if not codeObj.has_decode_default: 1686 codeObj += default_defaults 1687 codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n') 1688 t[0] = codeObj 1689 1690 # The opt_default statement serves only to push the "default 1691 # defaults" onto defaultStack. This value will be used by nested 1692 # decode blocks, and used and popped off when the current 1693 # decode_block is processed (in p_decode_block() above). 1694 def p_opt_default_0(self, t): 1695 'opt_default : empty' 1696 # no default specified: reuse the one currently at the top of 1697 # the stack 1698 defaultStack.push(defaultStack.top()) 1699 # no meaningful value returned 1700 t[0] = None 1701 1702 def p_opt_default_1(self, t): 1703 'opt_default : DEFAULT inst' 1704 # push the new default 1705 codeObj = t[2] 1706 codeObj.wrap_decode_block('\ndefault:\n', 'break;\n') 1707 defaultStack.push(codeObj) 1708 # no meaningful value returned 1709 t[0] = None 1710 1711 def p_decode_stmt_list_0(self, t): 1712 'decode_stmt_list : decode_stmt' 1713 t[0] = t[1] 1714 1715 def p_decode_stmt_list_1(self, t): 1716 'decode_stmt_list : decode_stmt decode_stmt_list' 1717 if (t[1].has_decode_default and t[2].has_decode_default): 1718 error(t, 'Two default cases in decode block') 1719 t[0] = t[1] + t[2] 1720 1721 # 1722 # Decode statement rules 1723 # 1724 # There are four types of statements allowed in a decode block: 1725 # 1. Format blocks 'format <foo> { ... }' 1726 # 2. Nested decode blocks 1727 # 3. Instruction definitions. 1728 # 4. C preprocessor directives. 1729 1730 1731 # Preprocessor directives found in a decode statement list are 1732 # passed through to the output, replicated to all of the output 1733 # code streams. This works well for ifdefs, so we can ifdef out 1734 # both the declarations and the decode cases generated by an 1735 # instruction definition. Handling them as part of the grammar 1736 # makes it easy to keep them in the right place with respect to 1737 # the code generated by the other statements. 1738 def p_decode_stmt_cpp(self, t): 1739 'decode_stmt : CPPDIRECTIVE' 1740 t[0] = GenCode(t[1], t[1], t[1], t[1]) 1741 1742 # A format block 'format <foo> { ... }' sets the default 1743 # instruction format used to handle instruction definitions inside 1744 # the block. This format can be overridden by using an explicit 1745 # format on the instruction definition or with a nested format 1746 # block. 1747 def p_decode_stmt_format(self, t): 1748 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE' 1749 # The format will be pushed on the stack when 'push_format_id' 1750 # is processed (see below). Once the parser has recognized 1751 # the full production (though the right brace), we're done 1752 # with the format, so now we can pop it. 1753 formatStack.pop() 1754 t[0] = t[4] 1755 1756 # This rule exists so we can set the current format (& push the 1757 # stack) when we recognize the format name part of the format 1758 # block. 1759 def p_push_format_id(self, t): 1760 'push_format_id : ID' 1761 try: 1762 formatStack.push(formatMap[t[1]]) 1763 t[0] = ('', '// format %s' % t[1]) 1764 except KeyError: 1765 error(t, 'instruction format "%s" not defined.' % t[1]) 1766 1767 # Nested decode block: if the value of the current field matches 1768 # the specified constant, do a nested decode on some other field. 1769 def p_decode_stmt_decode(self, t): 1770 'decode_stmt : case_label COLON decode_block' 1771 label = t[1] 1772 codeObj = t[3] 1773 # just wrap the decoding code from the block as a case in the 1774 # outer switch statement. 1775 codeObj.wrap_decode_block('\n%s:\n' % label) 1776 codeObj.has_decode_default = (label == 'default') 1777 t[0] = codeObj 1778 1779 # Instruction definition (finally!). 1780 def p_decode_stmt_inst(self, t): 1781 'decode_stmt : case_label COLON inst SEMI' 1782 label = t[1] 1783 codeObj = t[3] 1784 codeObj.wrap_decode_block('\n%s:' % label, 'break;\n') 1785 codeObj.has_decode_default = (label == 'default') 1786 t[0] = codeObj 1787 1788 # The case label is either a list of one or more constants or 1789 # 'default' 1790 def p_case_label_0(self, t): 1791 'case_label : intlit_list' 1792 def make_case(intlit): 1793 if intlit >= 2**32: 1794 return 'case ULL(%#x)' % intlit 1795 else: 1796 return 'case %#x' % intlit 1797 t[0] = ': '.join(map(make_case, t[1])) 1798 1799 def p_case_label_1(self, t): 1800 'case_label : DEFAULT' 1801 t[0] = 'default' 1802 1803 # 1804 # The constant list for a decode case label must be non-empty, but 1805 # may have one or more comma-separated integer literals in it. 1806 # 1807 def p_intlit_list_0(self, t): 1808 'intlit_list : INTLIT' 1809 t[0] = [t[1]] 1810 1811 def p_intlit_list_1(self, t): 1812 'intlit_list : intlit_list COMMA INTLIT' 1813 t[0] = t[1] 1814 t[0].append(t[3]) 1815 1816 # Define an instruction using the current instruction format 1817 # (specified by an enclosing format block). 1818 # "<mnemonic>(<args>)" 1819 def p_inst_0(self, t): 1820 'inst : ID LPAREN arg_list RPAREN' 1821 # Pass the ID and arg list to the current format class to deal with. 1822 currentFormat = formatStack.top() 1823 codeObj = currentFormat.defineInst(t[1], t[3], t.lexer.lineno) 1824 args = ','.join(map(str, t[3])) 1825 args = re.sub('(?m)^', '//', args) 1826 args = re.sub('^//', '', args) 1827 comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args) 1828 codeObj.prepend_all(comment) 1829 t[0] = codeObj 1830 1831 # Define an instruction using an explicitly specified format: 1832 # "<fmt>::<mnemonic>(<args>)" 1833 def p_inst_1(self, t): 1834 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN' 1835 try: 1836 format = formatMap[t[1]] 1837 except KeyError: 1838 error(t, 'instruction format "%s" not defined.' % t[1]) 1839 codeObj = format.defineInst(t[3], t[5], t.lexer.lineno) 1840 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5]) 1841 codeObj.prepend_all(comment) 1842 t[0] = codeObj 1843 1844 # The arg list generates a tuple, where the first element is a 1845 # list of the positional args and the second element is a dict 1846 # containing the keyword args. 1847 def p_arg_list_0(self, t): 1848 'arg_list : positional_arg_list COMMA keyword_arg_list' 1849 t[0] = ( t[1], t[3] ) 1850 1851 def p_arg_list_1(self, t): 1852 'arg_list : positional_arg_list' 1853 t[0] = ( t[1], {} ) 1854 1855 def p_arg_list_2(self, t): 1856 'arg_list : keyword_arg_list' 1857 t[0] = ( [], t[1] ) 1858 1859 def p_positional_arg_list_0(self, t): 1860 'positional_arg_list : empty' 1861 t[0] = [] 1862 1863 def p_positional_arg_list_1(self, t): 1864 'positional_arg_list : expr' 1865 t[0] = [t[1]] 1866 1867 def p_positional_arg_list_2(self, t): 1868 'positional_arg_list : positional_arg_list COMMA expr' 1869 t[0] = t[1] + [t[3]] 1870 1871 def p_keyword_arg_list_0(self, t): 1872 'keyword_arg_list : keyword_arg' 1873 t[0] = t[1] 1874 1875 def p_keyword_arg_list_1(self, t): 1876 'keyword_arg_list : keyword_arg_list COMMA keyword_arg' 1877 t[0] = t[1] 1878 t[0].update(t[3]) 1879 1880 def p_keyword_arg(self, t): 1881 'keyword_arg : ID EQUALS expr' 1882 t[0] = { t[1] : t[3] } 1883 1884 # 1885 # Basic expressions. These constitute the argument values of 1886 # "function calls" (i.e. instruction definitions in the decode 1887 # block) and default values for formal parameters of format 1888 # functions. 1889 # 1890 # Right now, these are either strings, integers, or (recursively) 1891 # lists of exprs (using Python square-bracket list syntax). Note 1892 # that bare identifiers are trated as string constants here (since 1893 # there isn't really a variable namespace to refer to). 1894 # 1895 def p_expr_0(self, t): 1896 '''expr : ID 1897 | INTLIT 1898 | STRLIT 1899 | CODELIT''' 1900 t[0] = t[1] 1901 1902 def p_expr_1(self, t): 1903 '''expr : LBRACKET list_expr RBRACKET''' 1904 t[0] = t[2] 1905 1906 def p_list_expr_0(self, t): 1907 'list_expr : expr' 1908 t[0] = [t[1]] 1909 1910 def p_list_expr_1(self, t): 1911 'list_expr : list_expr COMMA expr' 1912 t[0] = t[1] + [t[3]] 1913 1914 def p_list_expr_2(self, t): 1915 'list_expr : empty' 1916 t[0] = [] 1917 1918 # 1919 # Empty production... use in other rules for readability. 1920 # 1921 def p_empty(self, t): 1922 'empty :' 1923 pass 1924 1925 # Parse error handler. Note that the argument here is the 1926 # offending *token*, not a grammar symbol (hence the need to use 1927 # t.value) 1928 def p_error(self, t): 1929 if t: 1930 error(t, "syntax error at '%s'" % t.value) 1931 else: 1932 error("unknown syntax error") 1933 1934 # END OF GRAMMAR RULES 1935 1936 def update_if_needed(self, file, contents): 1937 '''Update the output file only if the new contents are 1938 different from the current contents. Minimizes the files that 1939 need to be rebuilt after minor changes.''' 1940 1941 file = os.path.join(self.output_dir, file) 1942 update = False 1943 if os.access(file, os.R_OK): 1944 f = open(file, 'r') 1945 old_contents = f.read() 1946 f.close() 1947 if contents != old_contents: 1948 print 'Updating', file 1949 os.remove(file) # in case it's write-protected 1950 update = True 1951 else: 1952 print 'File', file, 'is unchanged' 1953 else: 1954 print 'Generating', file 1955 update = True 1956 if update: 1957 f = open(file, 'w') 1958 f.write(contents) 1959 f.close() 1960 1961 # This regular expression matches '##include' directives 1962 includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$', 1963 re.MULTILINE) 1964 1965 def replace_include(self, matchobj, dirname): 1966 """Function to replace a matched '##include' directive with the 1967 contents of the specified file (with nested ##includes 1968 replaced recursively). 'matchobj' is an re match object 1969 (from a match of includeRE) and 'dirname' is the directory 1970 relative to which the file path should be resolved.""" 1971 1972 fname = matchobj.group('filename') 1973 full_fname = os.path.normpath(os.path.join(dirname, fname)) 1974 contents = '##newfile "%s"\n%s\n##endfile\n' % \ 1975 (full_fname, self.read_and_flatten(full_fname)) 1976 return contents 1977 1978 def read_and_flatten(self, filename): 1979 """Read a file and recursively flatten nested '##include' files.""" 1980 1981 current_dir = os.path.dirname(filename) 1982 try: 1983 contents = open(filename).read() 1984 except IOError: 1985 error('Error including file "%s"' % filename) 1986 1987 fileNameStack.push((filename, 0)) 1988 1989 # Find any includes and include them 1990 def replace(matchobj): 1991 return self.replace_include(matchobj, current_dir) 1992 contents = self.includeRE.sub(replace, contents) 1993 1994 fileNameStack.pop() 1995 return contents 1996 1997 def _parse_isa_desc(self, isa_desc_file): 1998 '''Read in and parse the ISA description.''' 1999 2000 # Read file and (recursively) all included files into a string. 2001 # PLY requires that the input be in a single string so we have to 2002 # do this up front. 2003 isa_desc = self.read_and_flatten(isa_desc_file) 2004 2005 # Initialize filename stack with outer file. 2006 fileNameStack.push((isa_desc_file, 0)) 2007 2008 # Parse it. 2009 (isa_name, namespace, global_code, namespace_code) = \ 2010 self.parse(isa_desc) 2011 2012 # grab the last three path components of isa_desc_file to put in 2013 # the output 2014 filename = '/'.join(isa_desc_file.split('/')[-3:]) 2015 2016 # generate decoder.hh 2017 includes = '#include "base/bitfield.hh" // for bitfield support' 2018 global_output = global_code.header_output 2019 namespace_output = namespace_code.header_output 2020 decode_function = '' 2021 self.update_if_needed('decoder.hh', file_template % vars()) 2022 2023 # generate decoder.cc 2024 includes = '#include "decoder.hh"' 2025 global_output = global_code.decoder_output 2026 namespace_output = namespace_code.decoder_output 2027 # namespace_output += namespace_code.decode_block 2028 decode_function = namespace_code.decode_block 2029 self.update_if_needed('decoder.cc', file_template % vars()) 2030 2031 # generate per-cpu exec files 2032 for cpu in cpu_models: 2033 includes = '#include "decoder.hh"\n' 2034 includes += cpu.includes 2035 global_output = global_code.exec_output[cpu.name] 2036 namespace_output = namespace_code.exec_output[cpu.name] 2037 decode_function = '' 2038 self.update_if_needed(cpu.filename, file_template % vars()) 2039 2040 # The variable names here are hacky, but this will creat local 2041 # variables which will be referenced in vars() which have the 2042 # value of the globals. 2043 global maxInstSrcRegs 2044 MaxInstSrcRegs = maxInstSrcRegs 2045 global maxInstDestRegs 2046 MaxInstDestRegs = maxInstDestRegs 2047 # max_inst_regs.hh 2048 self.update_if_needed('max_inst_regs.hh', 2049 max_inst_regs_template % vars()) 2050 2051 def parse_isa_desc(self, *args, **kwargs): 2052 try: 2053 self._parse_isa_desc(*args, **kwargs) 2054 except ISAParserError, e: 2055 e.exit(fileNameStack) 2056 2057# global list of CpuModel objects (see cpu_models.py) 2058cpu_models = [] 2059 2060# Called as script: get args from command line. 2061# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models> 2062if __name__ == '__main__': 2063 execfile(sys.argv[1]) # read in CpuModel definitions 2064 cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]] 2065 parser = ISAParser(sys.argv[3]) 2066 parser.parse_isa_desc(sys.argv[2]) 2067