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