isa_parser.py revision 2
1#! /usr/bin/env python 2 3# $Id$ 4 5# Copyright (c) 2003 The Regents of The University of Michigan 6# All rights reserved. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions are 10# met: redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer; 12# redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution; 15# neither the name of the copyright holders nor the names of its 16# contributors may be used to endorse or promote products derived from 17# this software without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31import os 32import sys 33import re 34import string 35# get type names 36from types import * 37 38# Check arguments. Right now there are only two: the name of the ISA 39# description (input) file and the name of the C++ decoder (output) file. 40isa_desc_filename = sys.argv[1] 41decoder_filename = sys.argv[2] 42 43# Might as well suck the file in while we're here. This way if it's a 44# bad filename we don't waste a lot of time building the parser :-). 45input = open(isa_desc_filename) 46isa_desc = input.read() 47input.close() 48 49# Prepend the directory where the PLY lex & yacc modules are found 50# to the search path. Assumes we're compiling in a subdirectory 51# of 'build' in the current tree. 52sys.path[0:0] = [os.environ['M5_EXT'] + '/ply'] 53 54import lex 55import yacc 56 57##################################################################### 58# 59# Lexer 60# 61# The PLY lexer module takes two things as input: 62# - A list of token names (the string list 'tokens') 63# - A regular expression describing a match for each token. The 64# regexp for token FOO can be provided in two ways: 65# - as a string variable named t_FOO 66# - as the doc string for a function named t_FOO. In this case, 67# the function is also executed, allowing an action to be 68# associated with each token match. 69# 70##################################################################### 71 72# Reserved words. These are listed separately as they are matched 73# using the same regexp as generic IDs, but distinguished in the 74# t_ID() function. The PLY documentation suggests this approach. 75reserved = ( 76 'BITFIELD', 'DECLARE', 'DECODE', 'DEFAULT', 'DEF', 'FORMAT', 77 'LET', 'NAMESPACE', 'SIGNED', 'TEMPLATE' 78 ) 79 80# List of tokens. The lex module requires this. 81tokens = reserved + ( 82 # identifier 83 'ID', 84 85 # integer literal 86 'INTLIT', 87 88 # string literal 89 'STRLIT', 90 91 # code literal 92 'CODELIT', 93 94 # ( ) [ ] { } < > , ; : :: * 95 'LPAREN', 'RPAREN', 96# not used any more... commented out to suppress PLY warning 97# 'LBRACKET', 'RBRACKET', 98 'LBRACE', 'RBRACE', 99 'LESS', 'GREATER', 100 'COMMA', 'SEMI', 'COLON', 'DBLCOLON', 101 'ASTERISK', 102 103 # C preprocessor directives 104 'CPPDIRECTIVE' 105) 106 107# Regular expressions for token matching 108t_LPAREN = r'\(' 109t_RPAREN = r'\)' 110# not used any more... commented out to suppress PLY warning 111# t_LBRACKET = r'\[' 112# t_RBRACKET = r'\]' 113t_LBRACE = r'\{' 114t_RBRACE = r'\}' 115t_LESS = r'\<' 116t_GREATER = r'\>' 117t_COMMA = r',' 118t_SEMI = r';' 119t_COLON = r':' 120t_DBLCOLON = r'::' 121t_ASTERISK = r'\*' 122 123# Identifiers and reserved words 124reserved_map = { } 125for r in reserved: 126 reserved_map[r.lower()] = r 127 128def t_ID(t): 129 r'[A-Za-z_]\w*' 130 t.type = reserved_map.get(t.value,'ID') 131 return t 132 133# Integer literal 134def t_INTLIT(t): 135 r'(0x[\da-fA-F]+)|\d+' 136 try: 137 t.value = int(t.value,0) 138 except ValueError: 139 error(t.lineno, 'Integer value "%s" too large' % t.value) 140 t.value = 0 141 return t 142 143# String literal. Note that these use only single quotes, and 144# can span multiple lines. 145def t_STRLIT(t): 146 r"(?m)'([^'])+'" 147 # strip off quotes 148 t.value = t.value[1:-1] 149 t.lineno += t.value.count('\n') 150 return t 151 152 153# "Code literal"... like a string literal, but delimiters are 154# '{{' and '}}' so they get formatted nicely under emacs c-mode 155def t_CODELIT(t): 156 r"(?m)\{\{([^\}]|}(?!\}))+\}\}" 157 # strip off {{ & }} 158 t.value = t.value[2:-2] 159 t.lineno += t.value.count('\n') 160 return t 161 162def t_CPPDIRECTIVE(t): 163 r'^\#.*\n' 164 t.lineno += t.value.count('\n') 165 return t 166 167# 168# The functions t_NEWLINE, t_ignore, and t_error are 169# special for the lex module. 170# 171 172# Newlines 173def t_NEWLINE(t): 174 r'\n+' 175 t.lineno += t.value.count('\n') 176 177# Comments 178def t_comment(t): 179 r'//.*' 180 181# Completely ignored characters 182t_ignore = ' \t\x0c' 183 184# Error handler 185def t_error(t): 186 error(t.lineno, "illegal character '%s'" % t.value[0]) 187 t.skip(1) 188 189# Build the lexer 190lex.lex() 191 192##################################################################### 193# 194# Parser 195# 196# Every function whose name starts with 'p_' defines a grammar rule. 197# The rule is encoded in the function's doc string, while the 198# function body provides the action taken when the rule is matched. 199# The argument to each function is a list of the values of the 200# rule's symbols: t[0] for the LHS, and t[1..n] for the symbols 201# on the RHS. For tokens, the value is copied from the t.value 202# attribute provided by the lexer. For non-terminals, the value 203# is assigned by the producing rule; i.e., the job of the grammar 204# rule function is to set the value for the non-terminal on the LHS 205# (by assigning to t[0]). 206##################################################################### 207 208# Not sure why, but we get a handful of shift/reduce conflicts on DECLARE. 209# By default these get resolved as shifts, which is correct, but 210# warnings are printed. Explicitly marking DECLARE as right-associative 211# suppresses the warnings. 212precedence = ( 213 ('right', 'DECLARE'), 214 ) 215 216# The LHS of the first grammar rule is used as the start symbol 217# (in this case, 'specification'). Note that this rule enforces 218# that there will be exactly one namespace declaration, with 0 or more 219# global defs/decls before and after it. The defs & decls before 220# the namespace decl will be outside the namespace; those after 221# will be inside. The decoder function is always inside the namespace. 222def p_specification(t): 223 'specification : opt_defs_and_declares name_decl opt_defs_and_declares decode_block' 224 global_decls1 = t[1] 225 isa_name = t[2] 226 namespace = isa_name + "Inst" 227 global_decls2 = t[3] 228 (inst_decls, code) = t[4] 229 code = indent(code) 230 # grab the last three path components of isa_desc_filename 231 filename = '/'.join(isa_desc_filename.split('/')[-3:]) 232 # if the isa_desc file defines a 'rcs_id' string, 233 # echo that into the output too 234 try: 235 local_rcs_id = rcs_id 236 # strip $s out of ID so it doesn't get re-substituted 237 local_rcs_id = re.sub(r'\$', '', local_rcs_id) 238 except NameError: 239 local_rcs_id = 'Id: no RCS id found' 240 output = open(decoder_filename, 'w') 241 # split string to keep rcs from substituting this file's RCS id in 242 print >> output, '/* $Id' + '''$ */ 243 244/* 245 * Copyright (c) 2003 246 * The Regents of The University of Michigan 247 * All Rights Reserved 248 * 249 * Permission is granted to use, copy, create derivative works and 250 * redistribute this software and such derivative works for any 251 * purpose, so long as the copyright notice above, this grant of 252 * permission, and the disclaimer below appear in all copies made; and 253 * so long as the name of The University of Michigan is not used in 254 * any advertising or publicity pertaining to the use or distribution 255 * of this software without specific, written prior authorization. 256 * 257 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE 258 * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND 259 * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER 260 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 261 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 262 * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE 263 * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, 264 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM 265 * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN 266 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH 267 * DAMAGES. 268 */ 269 270/* 271 * DO NOT EDIT THIS FILE!!! 272 * 273 * It was automatically generated from this ISA description: 274 * Filename: %(filename)s 275 * RCS %(local_rcs_id)s 276 */ 277 278#include "bitfield.hh" // required for bitfield support 279 280 281///////////////////////////////////// 282// Global defs (outside namespace) // 283///////////////////////////////////// 284 285%(global_decls1)s 286 287/** 288 * Namespace for %(isa_name)s static instruction objects. 289 */ 290namespace %(namespace)s 291{ 292 293///////////////////////////////////// 294// Global defs (within namespace) // 295///////////////////////////////////// 296 297%(global_decls2)s 298 299//////////////////////////////////// 300// Declares from inst definitions // 301//////////////////////////////////// 302 303%(inst_decls)s 304 305} // namespace %(namespace)s 306 307////////////////////// 308// Decoder function // 309////////////////////// 310 311StaticInstPtr<%(isa_name)s> 312%(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst) 313{ 314 using namespace %(namespace)s; 315%(code)s 316} // decodeInst 317''' % vars() 318 output.close() 319 320# ISA name declaration looks like "namespace <foo>;" 321def p_name_decl(t): 322 'name_decl : NAMESPACE ID SEMI' 323 t[0] = t[2] 324 325# 'opt_defs_and_declares' is a possibly empty sequence of 326# defs and/or declares. 327def p_opt_defs_and_declares_0(t): 328 'opt_defs_and_declares : empty' 329 t[0] = '' 330 331def p_opt_defs_and_declares_1(t): 332 'opt_defs_and_declares : defs_and_declares' 333 t[0] = t[1] 334 335def p_defs_and_declares_0(t): 336 'defs_and_declares : def_or_declare' 337 t[0] = t[1] 338 339def p_defs_and_declares_1(t): 340 'defs_and_declares : defs_and_declares def_or_declare' 341 t[0] = t[1] + t[2] 342 343# The list of possible definition/declaration statements. 344def p_def_or_declare(t): 345 '''def_or_declare : def_format 346 | def_bitfield 347 | def_template 348 | global_declare 349 | global_let 350 | cpp_directive''' 351 t[0] = t[1] 352 353# preprocessor directives are copied directly to the output. 354def p_cpp_directive(t): 355 '''cpp_directive : CPPDIRECTIVE''' 356 t[0] = t[1] 357 358# Global declares 'declare {{...}}' (C++ code blocks) are copied 359# directly to the output. 360def p_global_declare(t): 361 'global_declare : DECLARE CODELIT SEMI' 362 t[0] = substBitOps(t[2]) 363 364# global let blocks 'let {{...}}' (Python code blocks) are executed 365# directly when seen. These are typically used to initialize global 366# Python variables used in later format definitions. 367def p_global_let(t): 368 'global_let : LET CODELIT SEMI' 369 try: 370 exec(fixPythonIndentation(t[2])) 371 except: 372 error_bt(t.lineno(1), 'error in global let block "%s".' % t[2]) 373 t[0] = '' # contributes nothing to the output C++ file 374 375# A bitfield definition looks like: 376# 'def [signed] bitfield <ID> [<first>:<last>]' 377# This generates a preprocessor macro in the output file. 378def p_def_bitfield_0(t): 379 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' 380 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) 381 if (t[2] == 'signed'): 382 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr) 383 t[0] = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 384 385# alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]' 386def p_def_bitfield_1(t): 387 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI' 388 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6]) 389 if (t[2] == 'signed'): 390 expr = 'sext<%d>(%s)' % (1, expr) 391 t[0] = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 392 393def p_opt_signed_0(t): 394 'opt_signed : SIGNED' 395 t[0] = t[1] 396 397def p_opt_signed_1(t): 398 'opt_signed : empty' 399 t[0] = '' 400 401# Global map variable to hold templates 402templateMap = {} 403 404def p_def_template(t): 405 'def_template : DEF TEMPLATE ID CODELIT SEMI' 406 templateMap[t[3]] = t[4] 407 t[0] = '' 408 409# An instruction format definition looks like 410# "def format <fmt>(<params>) {{...}};" 411def p_def_format(t): 412 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' 413 (id, params, code) = (t[3], t[5], t[7]) 414 defFormat(id, params, code, t.lineno(1)) 415 # insert a comment into the output to note that the def was processed 416 t[0] = ''' 417// 418// parser: format %s defined 419// 420''' % id 421 422# The formal parameter list for an instruction format is a possibly 423# empty list of comma-separated parameters. 424def p_param_list_0(t): 425 'param_list : empty' 426 t[0] = [ ] 427 428def p_param_list_1(t): 429 'param_list : param' 430 t[0] = [t[1]] 431 432def p_param_list_2(t): 433 'param_list : param_list COMMA param' 434 t[0] = t[1] 435 t[0].append(t[3]) 436 437# Each formal parameter is either an identifier or an identifier 438# preceded by an asterisk. As in Python, the latter (if present) gets 439# a tuple containing all the excess positional arguments, allowing 440# varargs functions. 441def p_param_0(t): 442 'param : ID' 443 t[0] = t[1] 444 445def p_param_1(t): 446 'param : ASTERISK ID' 447 # just concatenate them: '*ID' 448 t[0] = t[1] + t[2] 449 450# End of format definition-related rules. 451############## 452 453# 454# A decode block looks like: 455# decode <field1> [, <field2>]* [default <inst>] { ... } 456# 457def p_decode_block(t): 458 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' 459 default_defaults = defaultStack.pop() 460 (decls, code, has_default) = t[5] 461 # use the "default defaults" only if there was no explicit 462 # default statement in decode_stmt_list 463 if not has_default: 464 (default_decls, default_code) = default_defaults 465 decls += default_decls 466 code += default_code 467 t[0] = (decls, ''' 468switch (%s) { 469%s 470} 471''' % (t[2], indent(code))) 472 473# The opt_default statement serves only to push the "default defaults" 474# onto defaultStack. This value will be used by nested decode blocks, 475# and used and popped off when the current decode_block is processed 476# (in p_decode_block() above). 477def p_opt_default_0(t): 478 'opt_default : empty' 479 # no default specified: reuse the one currently at the top of the stack 480 defaultStack.push(defaultStack.top()) 481 # no meaningful value returned 482 t[0] = None 483 484def p_opt_default_1(t): 485 'opt_default : DEFAULT inst' 486 # push the new default 487 (decls, code) = t[2] 488 defaultStack.push((decls, '\ndefault:\n%sbreak;' % code)) 489 # no meaningful value returned 490 t[0] = None 491 492def p_decode_stmt_list_0(t): 493 'decode_stmt_list : decode_stmt' 494 t[0] = t[1] 495 496def p_decode_stmt_list_1(t): 497 'decode_stmt_list : decode_stmt decode_stmt_list' 498 (decls1, code1, has_default1) = t[1] 499 (decls2, code2, has_default2) = t[2] 500 if (has_default1 and has_default2): 501 error(t.lineno(1), 'Two default cases in decode block') 502 t[0] = (decls1 + '\n' + decls2, code1 + '\n' + code2, 503 has_default1 or has_default2) 504 505# 506# Decode statement rules 507# 508# There are four types of statements allowed in a decode block: 509# 1. Format blocks 'format <foo> { ... }' 510# 2. Nested decode blocks 511# 3. Instruction definitions. 512# 4. C preprocessor directives. 513 514 515# Preprocessor directives found in a decode statement list are passed 516# through to the output, replicated to both the declaration and decode 517# streams. This works well for ifdefs, so we can ifdef out both the 518# declarations and the decode cases generated by an instruction 519# definition. Handling them as part of the grammar makes it easy to 520# keep them in the right place with respect to the code generated by 521# the other statements. 522def p_decode_stmt_cpp(t): 523 'decode_stmt : CPPDIRECTIVE' 524 t[0] = (t[1], t[1], 0) 525 526# A format block 'format <foo> { ... }' sets the default instruction 527# format used to handle instruction definitions inside the block. 528# This format can be overridden by using an explicit format on the 529# instruction definition or with a nested format block. 530def p_decode_stmt_format(t): 531 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE' 532 # The format will be pushed on the stack when 'push_format_id' is 533 # processed (see below). Once the parser has recognized the full 534 # production (though the right brace), we're done with the format, 535 # so now we can pop it. 536 formatStack.pop() 537 t[0] = t[4] 538 539# This rule exists so we can set the current format (& push the stack) 540# when we recognize the format name part of the format block. 541def p_push_format_id(t): 542 'push_format_id : ID' 543 try: 544 formatStack.push(formatMap[t[1]]) 545 t[0] = ('', '// format %s' % t[1]) 546 except KeyError: 547 error(t.lineno(1), 'instruction format "%s" not defined.' % t[1]) 548 549# Nested decode block: if the value of the current field matches the 550# specified constant, do a nested decode on some other field. 551def p_decode_stmt_decode(t): 552 'decode_stmt : case_label COLON decode_block' 553 (label, is_default) = t[1] 554 (decls, code) = t[3] 555 # just wrap the decoding code from the block as a case in the 556 # outer switch statement. 557 t[0] = (decls, '\n%s:\n%s' % (label, indent(code)), is_default) 558 559# Instruction definition (finally!). 560def p_decode_stmt_inst(t): 561 'decode_stmt : case_label COLON inst SEMI' 562 (label, is_default) = t[1] 563 (decls, code) = t[3] 564 t[0] = (decls, '\n%s:%sbreak;' % (label, indent(code)), is_default) 565 566# The case label is either a list of one or more constants or 'default' 567def p_case_label_0(t): 568 'case_label : intlit_list' 569 t[0] = (': '.join(map(lambda a: 'case %#x' % a, t[1])), 0) 570 571def p_case_label_1(t): 572 'case_label : DEFAULT' 573 t[0] = ('default', 1) 574 575# 576# The constant list for a decode case label must be non-empty, but may have 577# one or more comma-separated integer literals in it. 578# 579def p_intlit_list_0(t): 580 'intlit_list : INTLIT' 581 t[0] = [t[1]] 582 583def p_intlit_list_1(t): 584 'intlit_list : intlit_list COMMA INTLIT' 585 t[0] = t[1] 586 t[0].append(t[3]) 587 588# Define an instruction using the current instruction format (specified 589# by an enclosing format block). 590# "<mnemonic>(<args>)" 591def p_inst_0(t): 592 'inst : ID LPAREN arg_list RPAREN' 593 # Pass the ID and arg list to the current format class to deal with. 594 currentFormat = formatStack.top() 595 (decls, code) = currentFormat.defineInst(t[1], t[3], t.lineno(1)) 596 args = ','.join(map(str, t[3])) 597 args = re.sub('(?m)^', '//', args) 598 args = re.sub('^//', '', args) 599 comment = '// %s::%s(%s)\n' % (currentFormat.id, t[1], args) 600 t[0] = (comment + decls, comment + code) 601 602# Define an instruction using an explicitly specified format: 603# "<fmt>::<mnemonic>(<args>)" 604def p_inst_1(t): 605 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN' 606 try: 607 format = formatMap[t[1]] 608 except KeyError: 609 error(t.lineno(1), 'instruction format "%s" not defined.' % t[1]) 610 (decls, code) = format.defineInst(t[3], t[5], t.lineno(1)) 611 comment = '// %s::%s(%s)\n' % (t[1], t[3], t[5]) 612 t[0] = (comment + decls, comment + code) 613 614def p_arg_list_0(t): 615 'arg_list : empty' 616 t[0] = [ ] 617 618def p_arg_list_1(t): 619 'arg_list : arg' 620 t[0] = [t[1]] 621 622def p_arg_list_2(t): 623 'arg_list : arg_list COMMA arg' 624 t[0] = t[1] 625 t[0].append(t[3]) 626 627def p_arg(t): 628 '''arg : ID 629 | INTLIT 630 | STRLIT 631 | CODELIT''' 632 t[0] = t[1] 633 634# 635# Empty production... use in other rules for readability. 636# 637def p_empty(t): 638 'empty :' 639 pass 640 641# Parse error handler. Note that the argument here is the offending 642# *token*, not a grammar symbol (hence the need to use t.value) 643def p_error(t): 644 if t: 645 error(t.lineno, "syntax error at '%s'" % t.value) 646 else: 647 error_bt(0, "unknown syntax error") 648 649# END OF GRAMMAR RULES 650# 651# Now build the parser. 652yacc.yacc() 653 654################ 655# Format object. 656# 657# A format object encapsulates an instruction format. It must provide 658# a defineInst() method that generates the code for an instruction 659# definition. 660 661class Format: 662 def __init__(self, id, params, code): 663 # constructor: just save away arguments 664 self.id = id 665 self.params = params 666 # strip blank lines from code (ones at the end are troublesome) 667 code = re.sub(r'(?m)^\s*$', '', code); 668 if code == '': 669 code = ' pass\n' 670 param_list = string.join(params, ", ") 671 f = 'def defInst(name, Name, ' + param_list + '):\n' + code 672 exec(f) 673 self.func = defInst 674 675 def defineInst(self, name, args, lineno): 676 # automatically provide a capitalized version of mnemonic 677 Name = string.capitalize(name) 678 try: 679 retval = self.func(name, Name, *args) 680 except: 681 error_bt(lineno, 'error defining "%s".' % name) 682 return retval 683 684# Special null format to catch an implicit-format instruction 685# definition outside of any format block. 686class NoFormat: 687 def __init__(self): 688 self.defaultInst = '' 689 690 def defineInst(self, name, args, lineno): 691 error(lineno, 692 'instruction definition "%s" with no active format!' % name) 693 694# This dictionary maps format name strings to Format objects. 695formatMap = {} 696 697# Define a new format 698def defFormat(id, params, code, lineno): 699 # make sure we haven't already defined this one 700 if formatMap.get(id, None) != None: 701 error(lineno, 'format %s redefined.' % id) 702 # create new object and store in global map 703 formatMap[id] = Format(id, params, code) 704 705 706############## 707# Stack: a simple stack object. Used for both formats (formatStack) 708# and default cases (defaultStack). 709 710class Stack: 711 def __init__(self, initItem): 712 self.stack = [ initItem ] 713 714 def push(self, item): 715 self.stack.append(item); 716 717 def pop(self): 718 return self.stack.pop() 719 720 def top(self): 721 return self.stack[-1] 722 723# The global format stack. 724formatStack = Stack(NoFormat()) 725 726# The global default case stack. 727defaultStack = Stack( None ) 728 729################### 730# Utility functions 731 732# 733# Indent every line in string 's' by two spaces 734# (except preprocessor directives). 735# Used to make nested code blocks look pretty. 736# 737def indent(s): 738 return re.sub(r'(?m)^(?!\#)', ' ', s) 739 740# 741# Munge a somewhat arbitrarily formatted piece of Python code 742# (e.g. from a format 'let' block) into something whose indentation 743# will get by the Python parser. 744# 745# The two keys here are that Python will give a syntax error if 746# there's any whitespace at the beginning of the first line, and that 747# all lines at the same lexical nesting level must have identical 748# indentation. Unfortunately the way code literals work, an entire 749# let block tends to have some initial indentation. Rather than 750# trying to figure out what that is and strip it off, we prepend 'if 751# 1:' to make the let code the nested block inside the if (and have 752# the parser automatically deal with the indentation for us). 753# 754# We don't want to do this if (1) the code block is empty or (2) the 755# first line of the block doesn't have any whitespace at the front. 756 757def fixPythonIndentation(s): 758 # get rid of blank lines first 759 s = re.sub(r'(?m)^\s*\n', '', s); 760 if (s != '' and re.match(r'[ \t]', s[0])): 761 s = 'if 1:\n' + s 762 return s 763 764# Error handler. Just call exit. Output formatted to work under 765# Emacs compile-mode. 766def error(lineno, string): 767 sys.exit("%s:%d: %s" % (isa_desc_filename, lineno, string)) 768 769# Like error(), but include a Python stack backtrace (for processing 770# Python exceptions). 771def error_bt(lineno, string): 772 print >> sys.stderr, "%s:%d: %s" % (isa_desc_filename, lineno, string) 773 raise 774 775 776##################################################################### 777# 778# Bitfield Operator Support 779# 780##################################################################### 781 782bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>') 783 784bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>') 785bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>') 786 787def substBitOps(code): 788 # first convert single-bit selectors to two-index form 789 # i.e., <n> --> <n:n> 790 code = bitOp1ArgRE.sub(r'<\1:\1>', code) 791 # simple case: selector applied to ID (name) 792 # i.e., foo<a:b> --> bits(foo, a, b) 793 code = bitOpWordRE.sub(r'bits(\1, \2, \3)', code) 794 # if selector is applied to expression (ending in ')'), 795 # we need to search backward for matching '(' 796 match = bitOpExprRE.search(code) 797 while match: 798 exprEnd = match.start() 799 here = exprEnd - 1 800 nestLevel = 1 801 while nestLevel > 0: 802 if code[here] == '(': 803 nestLevel -= 1 804 elif code[here] == ')': 805 nestLevel += 1 806 here -= 1 807 if here < 0: 808 sys.exit("Didn't find '('!") 809 exprStart = here+1 810 newExpr = r'bits(%s, %s, %s)' % (code[exprStart:exprEnd+1], 811 match.group(1), match.group(2)) 812 code = code[:exprStart] + newExpr + code[match.end():] 813 match = bitOpExprRE.search(code) 814 return code 815 816 817##################################################################### 818# 819# Code Parser 820# 821# The remaining code is the support for automatically extracting 822# instruction characteristics from pseudocode. 823# 824##################################################################### 825 826# Force the argument to be a list 827def makeList(list_or_item): 828 if not list_or_item: 829 return [] 830 elif type(list_or_item) == ListType: 831 return list_or_item 832 else: 833 return [ list_or_item ] 834 835# generate operandSizeMap based on provided operandTypeMap: 836# basically generate equiv. C++ type and make is_signed flag 837def buildOperandSizeMap(): 838 global operandSizeMap 839 operandSizeMap = {} 840 for ext in operandTypeMap.keys(): 841 (desc, size) = operandTypeMap[ext] 842 if desc == 'signed int': 843 type = 'int%d_t' % size 844 is_signed = 1 845 elif desc == 'unsigned int': 846 type = 'uint%d_t' % size 847 is_signed = 0 848 elif desc == 'float': 849 is_signed = 1 # shouldn't really matter 850 if size == 32: 851 type = 'float' 852 elif size == 64: 853 type = 'double' 854 if type == '': 855 error(0, 'Unrecognized type description "%s" in operandTypeMap') 856 operandSizeMap[ext] = (size, type, is_signed) 857 858# 859# Base class for operand traits. An instance of this class (or actually 860# a class derived from this one) encapsulates the traits of a particular 861# operand type (e.g., "32-bit integer register"). 862# 863class OperandTraits: 864 def __init__(self, dflt_ext, reg_spec, flags, sort_pri): 865 # Force construction of operandSizeMap from operandTypeMap 866 # if it hasn't happened yet 867 if not globals().has_key('operandSizeMap'): 868 buildOperandSizeMap() 869 self.dflt_ext = dflt_ext 870 (self.dflt_size, self.dflt_type, self.dflt_is_signed) = \ 871 operandSizeMap[dflt_ext] 872 self.reg_spec = reg_spec 873 # Canonical flag structure is a triple of lists, where each list 874 # indicates the set of flags implied by this operand always, when 875 # used as a source, and when used as a dest, respectively. 876 # For simplicity this can be initialized using a variety of fairly 877 # obvious shortcuts; we convert these to canonical form here. 878 if not flags: 879 # no flags specified (e.g., 'None') 880 self.flags = ( [], [], [] ) 881 elif type(flags) == StringType: 882 # a single flag: assumed to be unconditional 883 self.flags = ( [ flags ], [], [] ) 884 elif type(flags) == ListType: 885 # a list of flags: also assumed to be unconditional 886 self.flags = ( flags, [], [] ) 887 elif type(flags) == TupleType: 888 # it's a tuple: it should be a triple, 889 # but each item could be a single string or a list 890 (uncond_flags, src_flags, dest_flags) = flags 891 self.flags = (makeList(uncond_flags), 892 makeList(src_flags), makeList(dest_flags)) 893 self.sort_pri = sort_pri 894 895 def isMem(self): 896 return 0 897 898 def isReg(self): 899 return 0 900 901 def isFloatReg(self): 902 return 0 903 904 def isIntReg(self): 905 return 0 906 907 def isControlReg(self): 908 return 0 909 910 def getFlags(self, op_desc): 911 # note the empty slice '[:]' gives us a copy of self.flags[0] 912 # instead of a reference to it 913 my_flags = self.flags[0][:] 914 if op_desc.is_src: 915 my_flags += self.flags[1] 916 if op_desc.is_dest: 917 my_flags += self.flags[2] 918 return my_flags 919 920 def makeDecl(self, op_desc): 921 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 922 # Note that initializations in the declarations are solely 923 # to avoid 'uninitialized variable' errors from the compiler. 924 return type + ' ' + op_desc.munged_name + ' = 0;\n'; 925 926class IntRegOperandTraits(OperandTraits): 927 def isReg(self): 928 return 1 929 930 def isIntReg(self): 931 return 1 932 933 def makeConstructor(self, op_desc): 934 c = '' 935 if op_desc.is_src: 936 c += '\n\t_srcRegIdx[%d] = %s;' % \ 937 (op_desc.src_reg_idx, self.reg_spec) 938 if op_desc.is_dest: 939 c += '\n\t_destRegIdx[%d] = %s;' % \ 940 (op_desc.dest_reg_idx, self.reg_spec) 941 return c 942 943 def makeRead(self, op_desc, cpu_model): 944 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 945 if (type == 'float' or type == 'double'): 946 error(0, 'Attempt to read integer register as FP') 947 if (size == self.dflt_size): 948 return '%s = xc->readIntReg(_srcRegIdx[%d]);\n' % \ 949 (op_desc.munged_name, op_desc.src_reg_idx) 950 else: 951 return '%s = bits(xc->readIntReg(_srcRegIdx[%d]), %d, 0);\n' % \ 952 (op_desc.munged_name, op_desc.src_reg_idx, size-1) 953 954 def makeWrite(self, op_desc, cpu_model): 955 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 956 if (type == 'float' or type == 'double'): 957 error(0, 'Attempt to write integer register as FP') 958 if (size != self.dflt_size and is_signed): 959 final_val = 'sext<%d>(%s)' % (size, op_desc.munged_name) 960 else: 961 final_val = op_desc.munged_name 962 wb = ''' 963 { 964 %s final_val = %s; 965 xc->setIntReg(_destRegIdx[%d], final_val);\n 966 if (traceData) { traceData->setData(final_val); } 967 }''' % (self.dflt_type, final_val, op_desc.dest_reg_idx) 968 return wb 969 970class FloatRegOperandTraits(OperandTraits): 971 def isReg(self): 972 return 1 973 974 def isFloatReg(self): 975 return 1 976 977 def makeConstructor(self, op_desc): 978 c = '' 979 if op_desc.is_src: 980 c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \ 981 (op_desc.src_reg_idx, self.reg_spec) 982 if op_desc.is_dest: 983 c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \ 984 (op_desc.dest_reg_idx, self.reg_spec) 985 return c 986 987 def makeRead(self, op_desc, cpu_model): 988 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 989 bit_select = 0 990 if (type == 'float'): 991 func = 'readFloatRegSingle' 992 elif (type == 'double'): 993 func = 'readFloatRegDouble' 994 else: 995 func = 'readFloatRegInt' 996 if (size != self.dflt_size): 997 bit_select = 1 998 base = 'xc->%s(_srcRegIdx[%d] - FP_Base_DepTag)' % \ 999 (func, op_desc.src_reg_idx) 1000 if bit_select: 1001 return '%s = bits(%s, %d, 0);\n' % \ 1002 (op_desc.munged_name, base, size-1) 1003 else: 1004 return '%s = %s;\n' % (op_desc.munged_name, base) 1005 1006 def makeWrite(self, op_desc, cpu_model): 1007 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 1008 final_val = op_desc.munged_name 1009 if (type == 'float'): 1010 func = 'setFloatRegSingle' 1011 elif (type == 'double'): 1012 func = 'setFloatRegDouble' 1013 else: 1014 func = 'setFloatRegInt' 1015 type = 'uint%d_t' % self.dflt_size 1016 if (size != self.dflt_size and is_signed): 1017 final_val = 'sext<%d>(%s)' % (size, op_desc.munged_name) 1018 wb = ''' 1019 { 1020 %s final_val = %s; 1021 xc->%s(_destRegIdx[%d] - FP_Base_DepTag, final_val);\n 1022 if (traceData) { traceData->setData(final_val); } 1023 }''' % (type, final_val, func, op_desc.dest_reg_idx) 1024 return wb 1025 1026class ControlRegOperandTraits(OperandTraits): 1027 def isReg(self): 1028 return 1 1029 1030 def isControlReg(self): 1031 return 1 1032 1033 def makeConstructor(self, op_desc): 1034 c = '' 1035 if op_desc.is_src: 1036 c += '\n\t_srcRegIdx[%d] = %s_DepTag;' % \ 1037 (op_desc.src_reg_idx, self.reg_spec) 1038 if op_desc.is_dest: 1039 c += '\n\t_destRegIdx[%d] = %s_DepTag;' % \ 1040 (op_desc.dest_reg_idx, self.reg_spec) 1041 return c 1042 1043 def makeRead(self, op_desc, cpu_model): 1044 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 1045 bit_select = 0 1046 if (type == 'float' or type == 'double'): 1047 error(0, 'Attempt to read control register as FP') 1048 base = 'xc->read%s()' % self.reg_spec 1049 if size == self.dflt_size: 1050 return '%s = %s;\n' % (op_desc.munged_name, base) 1051 else: 1052 return '%s = bits(%s, %d, 0);\n' % \ 1053 (op_desc.munged_name, base, size-1) 1054 1055 def makeWrite(self, op_desc, cpu_model): 1056 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 1057 if (type == 'float' or type == 'double'): 1058 error(0, 'Attempt to write control register as FP') 1059 wb = 'xc->set%s(%s);\n' % (self.reg_spec, op_desc.munged_name) 1060 wb += 'if (traceData) { traceData->setData(%s); }' % \ 1061 op_desc.munged_name 1062 return wb 1063 1064class MemOperandTraits(OperandTraits): 1065 def isMem(self): 1066 return 1 1067 1068 def makeConstructor(self, op_desc): 1069 return '' 1070 1071 def makeDecl(self, op_desc): 1072 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 1073 # Note that initializations in the declarations are solely 1074 # to avoid 'uninitialized variable' errors from the compiler. 1075 # Declare memory data variable. 1076 c = '%s %s = 0;\n' % (type, op_desc.munged_name) 1077 # Declare var to hold memory access flags. 1078 c += 'unsigned %s_flags = memAccessFlags;\n' % op_desc.base_name 1079 # If this operand is a dest (i.e., it's a store operation), 1080 # then we need to declare a variable for the write result code 1081 # as well. 1082 if op_desc.is_dest: 1083 c += 'uint64_t %s_write_result = 0;\n' % op_desc.base_name 1084 return c 1085 1086 def makeRead(self, op_desc, cpu_model): 1087 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 1088 eff_type = 'uint%d_t' % size 1089 return 'fault = memAccessObj->read(EA, (%s&)%s, %s_flags);\n' \ 1090 % (eff_type, op_desc.munged_name, op_desc.base_name) 1091 1092 def makeWrite(self, op_desc, cpu_model): 1093 (size, type, is_signed) = operandSizeMap[op_desc.eff_ext] 1094 eff_type = 'uint%d_t' % size 1095 return 'fault = memAccessObj->write((%s&)%s, EA, %s_flags,' \ 1096 ' &%s_write_result);\n' \ 1097 % (eff_type, op_desc.munged_name, op_desc.base_name, 1098 op_desc.base_name) 1099 1100class NPCOperandTraits(OperandTraits): 1101 def makeConstructor(self, op_desc): 1102 return '' 1103 1104 def makeRead(self, op_desc, cpu_model): 1105 return '%s = xc->readPC() + 4;\n' % op_desc.munged_name 1106 1107 def makeWrite(self, op_desc, cpu_model): 1108 return 'xc->setNextPC(%s);\n' % op_desc.munged_name 1109 1110 1111# 1112# Define operand variables that get derived from the basic declaration 1113# of ISA-specific operands in operandTraitsMap. This function must be 1114# called by the ISA description file explicitly after defining 1115# operandTraitsMap (in a 'let' block). 1116# 1117def defineDerivedOperandVars(): 1118 global operands 1119 operands = operandTraitsMap.keys() 1120 1121 operandsREString = (r''' 1122 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches 1123 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix 1124 (?![\w\.]) # neg. lookahead assertion: prevent partial matches 1125 ''' 1126 % string.join(operands, '|')) 1127 1128 global operandsRE 1129 operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) 1130 1131 # Same as operandsREString, but extension is mandatory, and only two 1132 # groups are returned (base and ext, not full name as above). 1133 # Used for subtituting '_' for '.' to make C++ identifiers. 1134 operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])' 1135 % string.join(operands, '|')) 1136 1137 global operandsWithExtRE 1138 operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE) 1139 1140 1141# 1142# Operand descriptor class. An instance of this class represents 1143# a specific operand for a code block. 1144# 1145class OperandDescriptor: 1146 def __init__(self, full_name, base_name, ext, is_src, is_dest): 1147 self.full_name = full_name 1148 self.base_name = base_name 1149 self.ext = ext 1150 self.is_src = is_src 1151 self.is_dest = is_dest 1152 self.traits = operandTraitsMap[base_name] 1153 # The 'effective extension' (eff_ext) is either the actual 1154 # extension, if one was explicitly provided, or the default. 1155 # The 'munged name' replaces the '.' between the base and 1156 # extension (if any) with a '_' to make a legal C++ variable name. 1157 if ext: 1158 self.eff_ext = ext 1159 self.munged_name = base_name + '_' + ext 1160 else: 1161 self.eff_ext = self.traits.dflt_ext 1162 self.munged_name = base_name 1163 1164 # Finalize additional fields (primarily code fields). This step 1165 # is done separately since some of these fields may depend on the 1166 # register index enumeration that hasn't been performed yet at the 1167 # time of __init__(). 1168 def finalize(self): 1169 self.flags = self.traits.getFlags(self) 1170 self.constructor = self.traits.makeConstructor(self) 1171 self.exec_decl = self.traits.makeDecl(self) 1172 1173 if self.is_src: 1174 self.simple_rd = self.traits.makeRead(self, 'simple') 1175 self.dtld_rd = self.traits.makeRead(self, 'dtld') 1176 else: 1177 self.simple_rd = '' 1178 self.dtld_rd = '' 1179 1180 if self.is_dest: 1181 self.simple_wb = self.traits.makeWrite(self, 'simple') 1182 self.dtld_wb = self.traits.makeWrite(self, 'dtld') 1183 else: 1184 self.simple_wb = '' 1185 self.dtld_wb = '' 1186 1187class OperandDescriptorList: 1188 def __init__(self): 1189 self.items = [] 1190 self.bases = {} 1191 1192 def __len__(self): 1193 return len(self.items) 1194 1195 def __getitem__(self, index): 1196 return self.items[index] 1197 1198 def append(self, op_desc): 1199 self.items.append(op_desc) 1200 self.bases[op_desc.base_name] = op_desc 1201 1202 def find_base(self, base_name): 1203 # like self.bases[base_name], but returns None if not found 1204 # (rather than raising exception) 1205 return self.bases.get(base_name) 1206 1207 # internal helper function for concat[Some]Attr{Strings|Lists} 1208 def __internalConcatAttrs(self, attr_name, filter, result): 1209 for op_desc in self.items: 1210 if filter(op_desc): 1211 result += getattr(op_desc, attr_name) 1212 return result 1213 1214 # return a single string that is the concatenation of the (string) 1215 # values of the specified attribute for all operands 1216 def concatAttrStrings(self, attr_name): 1217 return self.__internalConcatAttrs(attr_name, lambda x: 1, '') 1218 1219 # like concatAttrStrings, but only include the values for the operands 1220 # for which the provided filter function returns true 1221 def concatSomeAttrStrings(self, filter, attr_name): 1222 return self.__internalConcatAttrs(attr_name, filter, '') 1223 1224 # return a single list that is the concatenation of the (list) 1225 # values of the specified attribute for all operands 1226 def concatAttrLists(self, attr_name): 1227 return self.__internalConcatAttrs(attr_name, lambda x: 1, []) 1228 1229 # like concatAttrLists, but only include the values for the operands 1230 # for which the provided filter function returns true 1231 def concatSomeAttrLists(self, filter, attr_name): 1232 return self.__internalConcatAttrs(attr_name, filter, []) 1233 1234 def sort(self): 1235 self.items.sort(lambda a, b: a.traits.sort_pri - b.traits.sort_pri) 1236 1237# Regular expression object to match C++ comments 1238# (used in findOperands()) 1239commentRE = re.compile(r'//.*\n') 1240 1241# Regular expression object to match assignment statements 1242# (used in findOperands()) 1243assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) 1244 1245# 1246# Find all the operands in the given code block. Returns an operand 1247# descriptor list (instance of class OperandDescriptorList). 1248# 1249def findOperands(code): 1250 operands = OperandDescriptorList() 1251 # delete comments so we don't accidentally match on reg specifiers inside 1252 code = commentRE.sub('', code) 1253 # search for operands 1254 next_pos = 0 1255 while 1: 1256 match = operandsRE.search(code, next_pos) 1257 if not match: 1258 # no more matches: we're done 1259 break 1260 op = match.groups() 1261 # regexp groups are operand full name, base, and extension 1262 (op_full, op_base, op_ext) = op 1263 # if the token following the operand is an assignment, this is 1264 # a destination (LHS), else it's a source (RHS) 1265 is_dest = (assignRE.match(code, match.end()) != None) 1266 is_src = not is_dest 1267 # see if we've already seen this one 1268 op_desc = operands.find_base(op_base) 1269 if op_desc: 1270 if op_desc.ext != op_ext: 1271 error(0, 'Inconsistent extensions for operand %s' % op_base) 1272 op_desc.is_src = op_desc.is_src or is_src 1273 op_desc.is_dest = op_desc.is_dest or is_dest 1274 else: 1275 # new operand: create new descriptor 1276 op_desc = OperandDescriptor(op_full, op_base, op_ext, 1277 is_src, is_dest) 1278 operands.append(op_desc) 1279 # start next search after end of current match 1280 next_pos = match.end() 1281 operands.sort() 1282 # enumerate source & dest register operands... used in building 1283 # constructor later 1284 srcRegs = 0 1285 destRegs = 0 1286 operands.numFPDestRegs = 0 1287 operands.numIntDestRegs = 0 1288 for op_desc in operands: 1289 if op_desc.traits.isReg(): 1290 if op_desc.is_src: 1291 op_desc.src_reg_idx = srcRegs 1292 srcRegs += 1 1293 if op_desc.is_dest: 1294 op_desc.dest_reg_idx = destRegs 1295 destRegs += 1 1296 if op_desc.traits.isFloatReg(): 1297 operands.numFPDestRegs += 1 1298 elif op_desc.traits.isIntReg(): 1299 operands.numIntDestRegs += 1 1300 operands.numSrcRegs = srcRegs 1301 operands.numDestRegs = destRegs 1302 # now make a final pass to finalize op_desc fields that may depend 1303 # on the register enumeration 1304 for op_desc in operands: 1305 op_desc.finalize() 1306 return operands 1307 1308# Munge operand names in code string to make legal C++ variable names. 1309# (Will match munged_name attribute of OperandDescriptor object.) 1310def substMungedOpNames(code): 1311 return operandsWithExtRE.sub(r'\1_\2', code) 1312 1313def joinLists(t): 1314 return map(string.join, t) 1315 1316def makeFlagConstructor(flag_list): 1317 if len(flag_list) == 0: 1318 return '' 1319 # filter out repeated flags 1320 flag_list.sort() 1321 i = 1 1322 while i < len(flag_list): 1323 if flag_list[i] == flag_list[i-1]: 1324 del flag_list[i] 1325 else: 1326 i += 1 1327 pre = '\n\tflags[' 1328 post = '] = true;' 1329 code = pre + string.join(flag_list, post + pre) + post 1330 return code 1331 1332class CodeBlock: 1333 def __init__(self, code): 1334 self.orig_code = code 1335 self.operands = findOperands(code) 1336 self.code = substMungedOpNames(substBitOps(code)) 1337 self.constructor = self.operands.concatAttrStrings('constructor') 1338 self.constructor += \ 1339 '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs 1340 self.constructor += \ 1341 '\n\t_numDestRegs = %d;' % self.operands.numDestRegs 1342 self.constructor += \ 1343 '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs 1344 self.constructor += \ 1345 '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs 1346 1347 self.exec_decl = self.operands.concatAttrStrings('exec_decl') 1348 1349 is_mem = lambda op: op.traits.isMem() 1350 not_mem = lambda op: not op.traits.isMem() 1351 1352 self.simple_rd = self.operands.concatAttrStrings('simple_rd') 1353 self.simple_wb = self.operands.concatAttrStrings('simple_wb') 1354 self.simple_mem_rd = \ 1355 self.operands.concatSomeAttrStrings(is_mem, 'simple_rd') 1356 self.simple_mem_wb = \ 1357 self.operands.concatSomeAttrStrings(is_mem, 'simple_wb') 1358 self.simple_nonmem_rd = \ 1359 self.operands.concatSomeAttrStrings(not_mem, 'simple_rd') 1360 self.simple_nonmem_wb = \ 1361 self.operands.concatSomeAttrStrings(not_mem, 'simple_wb') 1362 1363 self.dtld_rd = self.operands.concatAttrStrings('dtld_rd') 1364 self.dtld_wb = self.operands.concatAttrStrings('dtld_wb') 1365 self.dtld_mem_rd = \ 1366 self.operands.concatSomeAttrStrings(is_mem, 'dtld_rd') 1367 self.dtld_mem_wb = \ 1368 self.operands.concatSomeAttrStrings(is_mem, 'dtld_wb') 1369 self.dtld_nonmem_rd = \ 1370 self.operands.concatSomeAttrStrings(not_mem, 'dtld_rd') 1371 self.dtld_nonmem_wb = \ 1372 self.operands.concatSomeAttrStrings(not_mem, 'dtld_wb') 1373 1374 self.flags = self.operands.concatAttrLists('flags') 1375 1376 # Make a basic guess on the operand class (function unit type). 1377 # These are good enough for most cases, and will be overridden 1378 # later otherwise. 1379 if 'IsStore' in self.flags: 1380 self.op_class = 'WrPort' 1381 elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags: 1382 self.op_class = 'RdPort' 1383 elif 'IsFloating' in self.flags: 1384 self.op_class = 'FloatADD' 1385 else: 1386 self.op_class = 'IntALU' 1387 1388# Assume all instruction flags are of the form 'IsFoo' 1389instFlagRE = re.compile(r'Is.*') 1390 1391# OpClass constants are just a little more complicated 1392opClassRE = re.compile(r'Int.*|Float.*|.*Port|No_OpClass') 1393 1394class InstObjParams: 1395 def __init__(self, mnem, class_name, base_class = '', 1396 code_block = None, opt_args = []): 1397 self.mnemonic = mnem 1398 self.class_name = class_name 1399 self.base_class = base_class 1400 if code_block: 1401 for code_attr in code_block.__dict__.keys(): 1402 setattr(self, code_attr, getattr(code_block, code_attr)) 1403 else: 1404 self.constructor = '' 1405 self.flags = [] 1406 # Optional arguments are assumed to be either StaticInst flags 1407 # or an OpClass value. To avoid having to import a complete 1408 # list of these values to match against, we do it ad-hoc 1409 # with regexps. 1410 for oa in opt_args: 1411 if instFlagRE.match(oa): 1412 self.flags.append(oa) 1413 elif opClassRE.match(oa): 1414 self.op_class = oa 1415 else: 1416 error(0, 'InstObjParams: optional arg "%s" not recognized ' 1417 'as StaticInst::Flag or OpClass.' % oa) 1418 1419 # add flag initialization to contructor here to include 1420 # any flags added via opt_args 1421 self.constructor += makeFlagConstructor(self.flags) 1422 1423 # if 'IsFloating' is set, add call to the FP enable check 1424 # function (which should be provided by isa_desc via a declare) 1425 if 'IsFloating' in self.flags: 1426 self.fp_enable_check = 'fault = checkFpEnableFault(xc);' 1427 else: 1428 self.fp_enable_check = '' 1429 1430 def subst(self, *args): 1431 result = [] 1432 for t in args: 1433 if not templateMap.has_key(t): 1434 error(0, 'InstObjParams::subst: undefined template "%s"' % t) 1435 try: 1436 result.append(templateMap[t] % self.__dict__) 1437 except KeyError, key: 1438 error(0, 'InstObjParams::subst: no definition for "%s"' % key) 1439 if len(args) == 1: 1440 result = result[0] 1441 return result 1442 1443# 1444# All set... read in and parse the ISA description. 1445# 1446yacc.parse(isa_desc) 1447