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