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