5 # Copyright (c) 2003 The Regents of The University of Michigan
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.
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.
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.
40 isa_desc_filename
= sys
.argv
[1]
41 decoder_filename
= sys
.argv
[2]
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 :-).
45 input = open(isa_desc_filename
)
46 isa_desc
= input.read()
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.
52 sys
.path
[0:0] = [os
.environ
['M5_EXT'] + '/ply']
57 #####################################################################
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.
70 #####################################################################
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.
76 'BITFIELD', 'DECLARE', 'DECODE', 'DEFAULT', 'DEF', 'FORMAT',
77 'LET', 'NAMESPACE', 'SIGNED', 'TEMPLATE'
80 # List of tokens. The lex module requires this.
94 # ( ) [ ] { } < > , ; : :: *
96 # not used any more... commented out to suppress PLY warning
97 # 'LBRACKET', 'RBRACKET',
100 'COMMA', 'SEMI', 'COLON', 'DBLCOLON',
103 # C preprocessor directives
107 # Regular expressions for token matching
110 # not used any more... commented out to suppress PLY warning
123 # Identifiers and reserved words
126 reserved_map
[r
.lower()] = r
130 t
.type = reserved_map
.get(t
.value
,'ID')
135 r
'(0x[\da-fA-F]+)|\d+'
137 t
.value
= int(t
.value
,0)
139 error(t
.lineno
, 'Integer value "%s" too large' % t
.value
)
143 # String literal. Note that these use only single quotes, and
144 # can span multiple lines.
148 t
.value
= t
.value
[1:-1]
149 t
.lineno
+= t
.value
.count('\n')
153 # "Code literal"... like a string literal, but delimiters are
154 # '{{' and '}}' so they get formatted nicely under emacs c-mode
156 r
"(?m)\{\{([^\}]|}(?!\}))+\}\}"
158 t
.value
= t
.value
[2:-2]
159 t
.lineno
+= t
.value
.count('\n')
162 def t_CPPDIRECTIVE(t
):
164 t
.lineno
+= t
.value
.count('\n')
168 # The functions t_NEWLINE, t_ignore, and t_error are
169 # special for the lex module.
175 t
.lineno
+= t
.value
.count('\n')
181 # Completely ignored characters
186 error(t
.lineno
, "illegal character '%s'" % t
.value
[0])
192 #####################################################################
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 #####################################################################
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.
213 ('right', 'DECLARE'),
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.
222 def p_specification(t
):
223 'specification : opt_defs_and_declares name_decl opt_defs_and_declares decode_block'
226 namespace
= isa_name
+ "Inst"
228 (inst_decls
, code
) = t
[4]
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
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
)
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' + '''$ */
246 * The Regents of The University of Michigan
247 * All Rights Reserved
249 * This code is part of the M5 simulator, developed by Nathan Binkert,
250 * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
251 * from Ron Dreslinski, Dave Greene, and Lisa Hsu.
253 * Permission is granted to use, copy, create derivative works and
254 * redistribute this software and such derivative works for any
255 * purpose, so long as the copyright notice above, this grant of
256 * permission, and the disclaimer below appear in all copies made; and
257 * so long as the name of The University of Michigan is not used in
258 * any advertising or publicity pertaining to the use or distribution
259 * of this software without specific, written prior authorization.
261 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
262 * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
263 * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
264 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
265 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
266 * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
267 * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
268 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
269 * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
270 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
275 * DO NOT EDIT THIS FILE!!!
277 * It was automatically generated from this ISA description:
278 * Filename: %(filename)s
279 * RCS %(local_rcs_id)s
282 #include "base/bitfield.hh" // required for bitfield support
285 /////////////////////////////////////
286 // Global defs (outside namespace) //
287 /////////////////////////////////////
292 * Namespace for %(isa_name)s static instruction objects.
294 namespace %(namespace)s
297 /////////////////////////////////////
298 // Global defs (within namespace) //
299 /////////////////////////////////////
303 ////////////////////////////////////
304 // Declares from inst definitions //
305 ////////////////////////////////////
309 } // namespace %(namespace)s
311 //////////////////////
312 // Decoder function //
313 //////////////////////
315 StaticInstPtr<%(isa_name)s>
316 %(isa_name)s::decodeInst(%(isa_name)s::MachInst machInst)
318 using namespace %(namespace)s;
324 # ISA name declaration looks like "namespace <foo>;"
326 'name_decl : NAMESPACE ID SEMI'
329 # 'opt_defs_and_declares' is a possibly empty sequence of
330 # defs and/or declares.
331 def p_opt_defs_and_declares_0(t
):
332 'opt_defs_and_declares : empty'
335 def p_opt_defs_and_declares_1(t
):
336 'opt_defs_and_declares : defs_and_declares'
339 def p_defs_and_declares_0(t
):
340 'defs_and_declares : def_or_declare'
343 def p_defs_and_declares_1(t
):
344 'defs_and_declares : defs_and_declares def_or_declare'
347 # The list of possible definition/declaration statements.
348 def p_def_or_declare(t
):
349 '''def_or_declare : def_format
357 # preprocessor directives are copied directly to the output.
358 def p_cpp_directive(t
):
359 '''cpp_directive : CPPDIRECTIVE'''
362 # Global declares 'declare {{...}}' (C++ code blocks) are copied
363 # directly to the output.
364 def p_global_declare(t
):
365 'global_declare : DECLARE CODELIT SEMI'
366 t
[0] = substBitOps(t
[2])
368 # global let blocks 'let {{...}}' (Python code blocks) are executed
369 # directly when seen. These are typically used to initialize global
370 # Python variables used in later format definitions.
372 'global_let : LET CODELIT SEMI'
374 exec(fixPythonIndentation(t
[2]))
376 error_bt(t
.lineno(1), 'error in global let block "%s".' % t
[2])
377 t
[0] = '' # contributes nothing to the output C++ file
379 # A bitfield definition looks like:
380 # 'def [signed] bitfield <ID> [<first>:<last>]'
381 # This generates a preprocessor macro in the output file.
382 def p_def_bitfield_0(t
):
383 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
384 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[8])
385 if (t
[2] == 'signed'):
386 expr
= 'sext<%d>(%s)' % (t
[6] - t
[8] + 1, expr
)
387 t
[0] = '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
389 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
390 def p_def_bitfield_1(t
):
391 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
392 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[6])
393 if (t
[2] == 'signed'):
394 expr
= 'sext<%d>(%s)' % (1, expr
)
395 t
[0] = '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
397 def p_opt_signed_0(t
):
398 'opt_signed : SIGNED'
401 def p_opt_signed_1(t
):
405 # Global map variable to hold templates
408 def p_def_template(t
):
409 'def_template : DEF TEMPLATE ID CODELIT SEMI'
410 templateMap
[t
[3]] = t
[4]
413 # An instruction format definition looks like
414 # "def format <fmt>(<params>) {{...}};"
416 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
417 (id, params
, code
) = (t
[3], t
[5], t
[7])
418 defFormat(id, params
, code
, t
.lineno(1))
419 # insert a comment into the output to note that the def was processed
422 // parser: format %s defined
426 # The formal parameter list for an instruction format is a possibly
427 # empty list of comma-separated parameters.
428 def p_param_list_0(t
):
432 def p_param_list_1(t
):
436 def p_param_list_2(t
):
437 'param_list : param_list COMMA param'
441 # Each formal parameter is either an identifier or an identifier
442 # preceded by an asterisk. As in Python, the latter (if present) gets
443 # a tuple containing all the excess positional arguments, allowing
450 'param : ASTERISK ID'
451 # just concatenate them: '*ID'
454 # End of format definition-related rules.
458 # A decode block looks like:
459 # decode <field1> [, <field2>]* [default <inst>] { ... }
461 def p_decode_block(t
):
462 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
463 default_defaults
= defaultStack
.pop()
464 (decls
, code
, has_default
) = t
[5]
465 # use the "default defaults" only if there was no explicit
466 # default statement in decode_stmt_list
468 (default_decls
, default_code
) = default_defaults
469 decls
+= default_decls
475 ''' % (t
[2], indent(code
)))
477 # The opt_default statement serves only to push the "default defaults"
478 # onto defaultStack. This value will be used by nested decode blocks,
479 # and used and popped off when the current decode_block is processed
480 # (in p_decode_block() above).
481 def p_opt_default_0(t
):
482 'opt_default : empty'
483 # no default specified: reuse the one currently at the top of the stack
484 defaultStack
.push(defaultStack
.top())
485 # no meaningful value returned
488 def p_opt_default_1(t
):
489 'opt_default : DEFAULT inst'
490 # push the new default
492 defaultStack
.push((decls
, '\ndefault:\n%sbreak;' % code
))
493 # no meaningful value returned
496 def p_decode_stmt_list_0(t
):
497 'decode_stmt_list : decode_stmt'
500 def p_decode_stmt_list_1(t
):
501 'decode_stmt_list : decode_stmt decode_stmt_list'
502 (decls1
, code1
, has_default1
) = t
[1]
503 (decls2
, code2
, has_default2
) = t
[2]
504 if (has_default1
and has_default2
):
505 error(t
.lineno(1), 'Two default cases in decode block')
506 t
[0] = (decls1
+ '\n' + decls2
, code1
+ '\n' + code2
,
507 has_default1
or has_default2
)
510 # Decode statement rules
512 # There are four types of statements allowed in a decode block:
513 # 1. Format blocks 'format <foo> { ... }'
514 # 2. Nested decode blocks
515 # 3. Instruction definitions.
516 # 4. C preprocessor directives.
519 # Preprocessor directives found in a decode statement list are passed
520 # through to the output, replicated to both the declaration and decode
521 # streams. This works well for ifdefs, so we can ifdef out both the
522 # declarations and the decode cases generated by an instruction
523 # definition. Handling them as part of the grammar makes it easy to
524 # keep them in the right place with respect to the code generated by
525 # the other statements.
526 def p_decode_stmt_cpp(t
):
527 'decode_stmt : CPPDIRECTIVE'
528 t
[0] = (t
[1], t
[1], 0)
530 # A format block 'format <foo> { ... }' sets the default instruction
531 # format used to handle instruction definitions inside the block.
532 # This format can be overridden by using an explicit format on the
533 # instruction definition or with a nested format block.
534 def p_decode_stmt_format(t
):
535 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
536 # The format will be pushed on the stack when 'push_format_id' is
537 # processed (see below). Once the parser has recognized the full
538 # production (though the right brace), we're done with the format,
539 # so now we can pop it.
543 # This rule exists so we can set the current format (& push the stack)
544 # when we recognize the format name part of the format block.
545 def p_push_format_id(t
):
546 'push_format_id : ID'
548 formatStack
.push(formatMap
[t
[1]])
549 t
[0] = ('', '// format %s' % t
[1])
551 error(t
.lineno(1), 'instruction format "%s" not defined.' % t
[1])
553 # Nested decode block: if the value of the current field matches the
554 # specified constant, do a nested decode on some other field.
555 def p_decode_stmt_decode(t
):
556 'decode_stmt : case_label COLON decode_block'
557 (label
, is_default
) = t
[1]
559 # just wrap the decoding code from the block as a case in the
560 # outer switch statement.
561 t
[0] = (decls
, '\n%s:\n%s' % (label
, indent(code
)), is_default
)
563 # Instruction definition (finally!).
564 def p_decode_stmt_inst(t
):
565 'decode_stmt : case_label COLON inst SEMI'
566 (label
, is_default
) = t
[1]
568 t
[0] = (decls
, '\n%s:%sbreak;' % (label
, indent(code
)), is_default
)
570 # The case label is either a list of one or more constants or 'default'
571 def p_case_label_0(t
):
572 'case_label : intlit_list'
573 t
[0] = (': '.join(map(lambda a
: 'case %#x' % a
, t
[1])), 0)
575 def p_case_label_1(t
):
576 'case_label : DEFAULT'
577 t
[0] = ('default', 1)
580 # The constant list for a decode case label must be non-empty, but may have
581 # one or more comma-separated integer literals in it.
583 def p_intlit_list_0(t
):
584 'intlit_list : INTLIT'
587 def p_intlit_list_1(t
):
588 'intlit_list : intlit_list COMMA INTLIT'
592 # Define an instruction using the current instruction format (specified
593 # by an enclosing format block).
594 # "<mnemonic>(<args>)"
596 'inst : ID LPAREN arg_list RPAREN'
597 # Pass the ID and arg list to the current format class to deal with.
598 currentFormat
= formatStack
.top()
599 (decls
, code
) = currentFormat
.defineInst(t
[1], t
[3], t
.lineno(1))
600 args
= ','.join(map(str, t
[3]))
601 args
= re
.sub('(?m)^', '//', args
)
602 args
= re
.sub('^//', '', args
)
603 comment
= '// %s::%s(%s)\n' % (currentFormat
.id, t
[1], args
)
604 t
[0] = (comment
+ decls
, comment
+ code
)
606 # Define an instruction using an explicitly specified format:
607 # "<fmt>::<mnemonic>(<args>)"
609 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
611 format
= formatMap
[t
[1]]
613 error(t
.lineno(1), 'instruction format "%s" not defined.' % t
[1])
614 (decls
, code
) = format
.defineInst(t
[3], t
[5], t
.lineno(1))
615 comment
= '// %s::%s(%s)\n' % (t
[1], t
[3], t
[5])
616 t
[0] = (comment
+ decls
, comment
+ code
)
627 'arg_list : arg_list COMMA arg'
639 # Empty production... use in other rules for readability.
645 # Parse error handler. Note that the argument here is the offending
646 # *token*, not a grammar symbol (hence the need to use t.value)
649 error(t
.lineno
, "syntax error at '%s'" % t
.value
)
651 error_bt(0, "unknown syntax error")
653 # END OF GRAMMAR RULES
655 # Now build the parser.
661 # A format object encapsulates an instruction format. It must provide
662 # a defineInst() method that generates the code for an instruction
666 def __init__(self
, id, params
, code
):
667 # constructor: just save away arguments
670 # strip blank lines from code (ones at the end are troublesome)
671 code
= re
.sub(r
'(?m)^\s*$', '', code
);
674 param_list
= string
.join(params
, ", ")
675 f
= 'def defInst(name, Name, ' + param_list
+ '):\n' + code
679 def defineInst(self
, name
, args
, lineno
):
680 # automatically provide a capitalized version of mnemonic
681 Name
= string
.capitalize(name
)
683 retval
= self
.func(name
, Name
, *args
)
685 error_bt(lineno
, 'error defining "%s".' % name
)
688 # Special null format to catch an implicit-format instruction
689 # definition outside of any format block.
692 self
.defaultInst
= ''
694 def defineInst(self
, name
, args
, lineno
):
696 'instruction definition "%s" with no active format!' % name
)
698 # This dictionary maps format name strings to Format objects.
701 # Define a new format
702 def defFormat(id, params
, code
, lineno
):
703 # make sure we haven't already defined this one
704 if formatMap
.get(id, None) != None:
705 error(lineno
, 'format %s redefined.' % id)
706 # create new object and store in global map
707 formatMap
[id] = Format(id, params
, code
)
711 # Stack: a simple stack object. Used for both formats (formatStack)
712 # and default cases (defaultStack).
715 def __init__(self
, initItem
):
716 self
.stack
= [ initItem
]
718 def push(self
, item
):
719 self
.stack
.append(item
);
722 return self
.stack
.pop()
725 return self
.stack
[-1]
727 # The global format stack.
728 formatStack
= Stack(NoFormat())
730 # The global default case stack.
731 defaultStack
= Stack( None )
737 # Indent every line in string 's' by two spaces
738 # (except preprocessor directives).
739 # Used to make nested code blocks look pretty.
742 return re
.sub(r
'(?m)^(?!\#)', ' ', s
)
745 # Munge a somewhat arbitrarily formatted piece of Python code
746 # (e.g. from a format 'let' block) into something whose indentation
747 # will get by the Python parser.
749 # The two keys here are that Python will give a syntax error if
750 # there's any whitespace at the beginning of the first line, and that
751 # all lines at the same lexical nesting level must have identical
752 # indentation. Unfortunately the way code literals work, an entire
753 # let block tends to have some initial indentation. Rather than
754 # trying to figure out what that is and strip it off, we prepend 'if
755 # 1:' to make the let code the nested block inside the if (and have
756 # the parser automatically deal with the indentation for us).
758 # We don't want to do this if (1) the code block is empty or (2) the
759 # first line of the block doesn't have any whitespace at the front.
761 def fixPythonIndentation(s
):
762 # get rid of blank lines first
763 s
= re
.sub(r
'(?m)^\s*\n', '', s
);
764 if (s
!= '' and re
.match(r
'[ \t]', s
[0])):
768 # Error handler. Just call exit. Output formatted to work under
769 # Emacs compile-mode.
770 def error(lineno
, string
):
771 sys
.exit("%s:%d: %s" % (isa_desc_filename
, lineno
, string
))
773 # Like error(), but include a Python stack backtrace (for processing
774 # Python exceptions).
775 def error_bt(lineno
, string
):
776 print >> sys
.stderr
, "%s:%d: %s" % (isa_desc_filename
, lineno
, string
)
780 #####################################################################
782 # Bitfield Operator Support
784 #####################################################################
786 bitOp1ArgRE
= re
.compile(r
'<\s*(\w+)\s*:\s*>')
788 bitOpWordRE
= re
.compile(r
'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
789 bitOpExprRE
= re
.compile(r
'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
791 def substBitOps(code
):
792 # first convert single-bit selectors to two-index form
793 # i.e., <n> --> <n:n>
794 code
= bitOp1ArgRE
.sub(r
'<\1:\1>', code
)
795 # simple case: selector applied to ID (name)
796 # i.e., foo<a:b> --> bits(foo, a, b)
797 code
= bitOpWordRE
.sub(r
'bits(\1, \2, \3)', code
)
798 # if selector is applied to expression (ending in ')'),
799 # we need to search backward for matching '('
800 match
= bitOpExprRE
.search(code
)
802 exprEnd
= match
.start()
806 if code
[here
] == '(':
808 elif code
[here
] == ')':
812 sys
.exit("Didn't find '('!")
814 newExpr
= r
'bits(%s, %s, %s)' % (code
[exprStart
:exprEnd
+1],
815 match
.group(1), match
.group(2))
816 code
= code
[:exprStart
] + newExpr
+ code
[match
.end():]
817 match
= bitOpExprRE
.search(code
)
821 #####################################################################
825 # The remaining code is the support for automatically extracting
826 # instruction characteristics from pseudocode.
828 #####################################################################
830 # Force the argument to be a list
831 def makeList(list_or_item
):
834 elif type(list_or_item
) == ListType
:
837 return [ list_or_item
]
839 # generate operandSizeMap based on provided operandTypeMap:
840 # basically generate equiv. C++ type and make is_signed flag
841 def buildOperandSizeMap():
842 global operandSizeMap
844 for ext
in operandTypeMap
.keys():
845 (desc
, size
) = operandTypeMap
[ext
]
846 if desc
== 'signed int':
847 type = 'int%d_t' % size
849 elif desc
== 'unsigned int':
850 type = 'uint%d_t' % size
852 elif desc
== 'float':
853 is_signed
= 1 # shouldn't really matter
859 error(0, 'Unrecognized type description "%s" in operandTypeMap')
860 operandSizeMap
[ext
] = (size
, type, is_signed
)
863 # Base class for operand traits. An instance of this class (or actually
864 # a class derived from this one) encapsulates the traits of a particular
865 # operand type (e.g., "32-bit integer register").
868 def __init__(self
, dflt_ext
, reg_spec
, flags
, sort_pri
):
869 # Force construction of operandSizeMap from operandTypeMap
870 # if it hasn't happened yet
871 if not globals().has_key('operandSizeMap'):
872 buildOperandSizeMap()
873 self
.dflt_ext
= dflt_ext
874 (self
.dflt_size
, self
.dflt_type
, self
.dflt_is_signed
) = \
875 operandSizeMap
[dflt_ext
]
876 self
.reg_spec
= reg_spec
877 # Canonical flag structure is a triple of lists, where each list
878 # indicates the set of flags implied by this operand always, when
879 # used as a source, and when used as a dest, respectively.
880 # For simplicity this can be initialized using a variety of fairly
881 # obvious shortcuts; we convert these to canonical form here.
883 # no flags specified (e.g., 'None')
884 self
.flags
= ( [], [], [] )
885 elif type(flags
) == StringType
:
886 # a single flag: assumed to be unconditional
887 self
.flags
= ( [ flags
], [], [] )
888 elif type(flags
) == ListType
:
889 # a list of flags: also assumed to be unconditional
890 self
.flags
= ( flags
, [], [] )
891 elif type(flags
) == TupleType
:
892 # it's a tuple: it should be a triple,
893 # but each item could be a single string or a list
894 (uncond_flags
, src_flags
, dest_flags
) = flags
895 self
.flags
= (makeList(uncond_flags
),
896 makeList(src_flags
), makeList(dest_flags
))
897 self
.sort_pri
= sort_pri
905 def isFloatReg(self
):
911 def isControlReg(self
):
914 def getFlags(self
, op_desc
):
915 # note the empty slice '[:]' gives us a copy of self.flags[0]
916 # instead of a reference to it
917 my_flags
= self
.flags
[0][:]
919 my_flags
+= self
.flags
[1]
921 my_flags
+= self
.flags
[2]
924 def makeDecl(self
, op_desc
):
925 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
926 # Note that initializations in the declarations are solely
927 # to avoid 'uninitialized variable' errors from the compiler.
928 return type + ' ' + op_desc
.munged_name
+ ' = 0;\n';
930 class IntRegOperandTraits(OperandTraits
):
937 def makeConstructor(self
, op_desc
):
940 c
+= '\n\t_srcRegIdx[%d] = %s;' % \
941 (op_desc
.src_reg_idx
, self
.reg_spec
)
943 c
+= '\n\t_destRegIdx[%d] = %s;' % \
944 (op_desc
.dest_reg_idx
, self
.reg_spec
)
947 def makeRead(self
, op_desc
, cpu_model
):
948 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
949 if (type == 'float' or type == 'double'):
950 error(0, 'Attempt to read integer register as FP')
951 if (size
== self
.dflt_size
):
952 return '%s = xc->readIntReg(_srcRegIdx[%d]);\n' % \
953 (op_desc
.munged_name
, op_desc
.src_reg_idx
)
955 return '%s = bits(xc->readIntReg(_srcRegIdx[%d]), %d, 0);\n' % \
956 (op_desc
.munged_name
, op_desc
.src_reg_idx
, size
-1)
958 def makeWrite(self
, op_desc
, cpu_model
):
959 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
960 if (type == 'float' or type == 'double'):
961 error(0, 'Attempt to write integer register as FP')
962 if (size
!= self
.dflt_size
and is_signed
):
963 final_val
= 'sext<%d>(%s)' % (size
, op_desc
.munged_name
)
965 final_val
= op_desc
.munged_name
969 xc->setIntReg(_destRegIdx[%d], final_val);\n
970 if (traceData) { traceData->setData(final_val); }
971 }''' % (self
.dflt_type
, final_val
, op_desc
.dest_reg_idx
)
974 class FloatRegOperandTraits(OperandTraits
):
978 def isFloatReg(self
):
981 def makeConstructor(self
, op_desc
):
984 c
+= '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
985 (op_desc
.src_reg_idx
, self
.reg_spec
)
987 c
+= '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
988 (op_desc
.dest_reg_idx
, self
.reg_spec
)
991 def makeRead(self
, op_desc
, cpu_model
):
992 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
994 if (type == 'float'):
995 func
= 'readFloatRegSingle'
996 elif (type == 'double'):
997 func
= 'readFloatRegDouble'
999 func
= 'readFloatRegInt'
1000 if (size
!= self
.dflt_size
):
1002 base
= 'xc->%s(_srcRegIdx[%d] - FP_Base_DepTag)' % \
1003 (func
, op_desc
.src_reg_idx
)
1005 return '%s = bits(%s, %d, 0);\n' % \
1006 (op_desc
.munged_name
, base
, size
-1)
1008 return '%s = %s;\n' % (op_desc
.munged_name
, base
)
1010 def makeWrite(self
, op_desc
, cpu_model
):
1011 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
1012 final_val
= op_desc
.munged_name
1013 if (type == 'float'):
1014 func
= 'setFloatRegSingle'
1015 elif (type == 'double'):
1016 func
= 'setFloatRegDouble'
1018 func
= 'setFloatRegInt'
1019 type = 'uint%d_t' % self
.dflt_size
1020 if (size
!= self
.dflt_size
and is_signed
):
1021 final_val
= 'sext<%d>(%s)' % (size
, op_desc
.munged_name
)
1025 xc->%s(_destRegIdx[%d] - FP_Base_DepTag, final_val);\n
1026 if (traceData) { traceData->setData(final_val); }
1027 }''' % (type, final_val
, func
, op_desc
.dest_reg_idx
)
1030 class ControlRegOperandTraits(OperandTraits
):
1034 def isControlReg(self
):
1037 def makeConstructor(self
, op_desc
):
1040 c
+= '\n\t_srcRegIdx[%d] = %s_DepTag;' % \
1041 (op_desc
.src_reg_idx
, self
.reg_spec
)
1043 c
+= '\n\t_destRegIdx[%d] = %s_DepTag;' % \
1044 (op_desc
.dest_reg_idx
, self
.reg_spec
)
1047 def makeRead(self
, op_desc
, cpu_model
):
1048 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
1050 if (type == 'float' or type == 'double'):
1051 error(0, 'Attempt to read control register as FP')
1052 base
= 'xc->read%s()' % self
.reg_spec
1053 if size
== self
.dflt_size
:
1054 return '%s = %s;\n' % (op_desc
.munged_name
, base
)
1056 return '%s = bits(%s, %d, 0);\n' % \
1057 (op_desc
.munged_name
, base
, size
-1)
1059 def makeWrite(self
, op_desc
, cpu_model
):
1060 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
1061 if (type == 'float' or type == 'double'):
1062 error(0, 'Attempt to write control register as FP')
1063 wb
= 'xc->set%s(%s);\n' % (self
.reg_spec
, op_desc
.munged_name
)
1064 wb
+= 'if (traceData) { traceData->setData(%s); }' % \
1068 class MemOperandTraits(OperandTraits
):
1072 def makeConstructor(self
, op_desc
):
1075 def makeDecl(self
, op_desc
):
1076 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
1077 # Note that initializations in the declarations are solely
1078 # to avoid 'uninitialized variable' errors from the compiler.
1079 # Declare memory data variable.
1080 c
= '%s %s = 0;\n' % (type, op_desc
.munged_name
)
1081 # Declare var to hold memory access flags.
1082 c
+= 'unsigned %s_flags = memAccessFlags;\n' % op_desc
.base_name
1083 # If this operand is a dest (i.e., it's a store operation),
1084 # then we need to declare a variable for the write result code
1087 c
+= 'uint64_t %s_write_result = 0;\n' % op_desc
.base_name
1090 def makeRead(self
, op_desc
, cpu_model
):
1091 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
1092 eff_type
= 'uint%d_t' % size
1093 return 'fault = memAccessObj->read(EA, (%s&)%s, %s_flags);\n' \
1094 % (eff_type
, op_desc
.munged_name
, op_desc
.base_name
)
1096 def makeWrite(self
, op_desc
, cpu_model
):
1097 (size
, type, is_signed
) = operandSizeMap
[op_desc
.eff_ext
]
1098 eff_type
= 'uint%d_t' % size
1099 return 'fault = memAccessObj->write((%s&)%s, EA, %s_flags,' \
1100 ' &%s_write_result);\n' \
1101 % (eff_type
, op_desc
.munged_name
, op_desc
.base_name
,
1104 class NPCOperandTraits(OperandTraits
):
1105 def makeConstructor(self
, op_desc
):
1108 def makeRead(self
, op_desc
, cpu_model
):
1109 return '%s = xc->readPC() + 4;\n' % op_desc
.munged_name
1111 def makeWrite(self
, op_desc
, cpu_model
):
1112 return 'xc->setNextPC(%s);\n' % op_desc
.munged_name
1116 # Define operand variables that get derived from the basic declaration
1117 # of ISA-specific operands in operandTraitsMap. This function must be
1118 # called by the ISA description file explicitly after defining
1119 # operandTraitsMap (in a 'let' block).
1121 def defineDerivedOperandVars():
1123 operands
= operandTraitsMap
.keys()
1125 operandsREString
= (r
'''
1126 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
1127 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
1128 (?![\w\.]) # neg. lookahead assertion: prevent partial matches
1130 % string
.join(operands
, '|'))
1133 operandsRE
= re
.compile(operandsREString
, re
.MULTILINE|re
.VERBOSE
)
1135 # Same as operandsREString, but extension is mandatory, and only two
1136 # groups are returned (base and ext, not full name as above).
1137 # Used for subtituting '_' for '.' to make C++ identifiers.
1138 operandsWithExtREString
= (r
'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
1139 % string
.join(operands
, '|'))
1141 global operandsWithExtRE
1142 operandsWithExtRE
= re
.compile(operandsWithExtREString
, re
.MULTILINE
)
1146 # Operand descriptor class. An instance of this class represents
1147 # a specific operand for a code block.
1149 class OperandDescriptor
:
1150 def __init__(self
, full_name
, base_name
, ext
, is_src
, is_dest
):
1151 self
.full_name
= full_name
1152 self
.base_name
= base_name
1154 self
.is_src
= is_src
1155 self
.is_dest
= is_dest
1156 self
.traits
= operandTraitsMap
[base_name
]
1157 # The 'effective extension' (eff_ext) is either the actual
1158 # extension, if one was explicitly provided, or the default.
1159 # The 'munged name' replaces the '.' between the base and
1160 # extension (if any) with a '_' to make a legal C++ variable name.
1163 self
.munged_name
= base_name
+ '_' + ext
1165 self
.eff_ext
= self
.traits
.dflt_ext
1166 self
.munged_name
= base_name
1168 # Finalize additional fields (primarily code fields). This step
1169 # is done separately since some of these fields may depend on the
1170 # register index enumeration that hasn't been performed yet at the
1171 # time of __init__().
1173 self
.flags
= self
.traits
.getFlags(self
)
1174 self
.constructor
= self
.traits
.makeConstructor(self
)
1175 self
.exec_decl
= self
.traits
.makeDecl(self
)
1178 self
.simple_rd
= self
.traits
.makeRead(self
, 'simple')
1179 self
.dtld_rd
= self
.traits
.makeRead(self
, 'dtld')
1185 self
.simple_wb
= self
.traits
.makeWrite(self
, 'simple')
1186 self
.dtld_wb
= self
.traits
.makeWrite(self
, 'dtld')
1191 class OperandDescriptorList
:
1197 return len(self
.items
)
1199 def __getitem__(self
, index
):
1200 return self
.items
[index
]
1202 def append(self
, op_desc
):
1203 self
.items
.append(op_desc
)
1204 self
.bases
[op_desc
.base_name
] = op_desc
1206 def find_base(self
, base_name
):
1207 # like self.bases[base_name], but returns None if not found
1208 # (rather than raising exception)
1209 return self
.bases
.get(base_name
)
1211 # internal helper function for concat[Some]Attr{Strings|Lists}
1212 def __internalConcatAttrs(self
, attr_name
, filter, result
):
1213 for op_desc
in self
.items
:
1215 result
+= getattr(op_desc
, attr_name
)
1218 # return a single string that is the concatenation of the (string)
1219 # values of the specified attribute for all operands
1220 def concatAttrStrings(self
, attr_name
):
1221 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, '')
1223 # like concatAttrStrings, but only include the values for the operands
1224 # for which the provided filter function returns true
1225 def concatSomeAttrStrings(self
, filter, attr_name
):
1226 return self
.__internalConcatAttrs
(attr_name
, filter, '')
1228 # return a single list that is the concatenation of the (list)
1229 # values of the specified attribute for all operands
1230 def concatAttrLists(self
, attr_name
):
1231 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, [])
1233 # like concatAttrLists, but only include the values for the operands
1234 # for which the provided filter function returns true
1235 def concatSomeAttrLists(self
, filter, attr_name
):
1236 return self
.__internalConcatAttrs
(attr_name
, filter, [])
1239 self
.items
.sort(lambda a
, b
: a
.traits
.sort_pri
- b
.traits
.sort_pri
)
1241 # Regular expression object to match C++ comments
1242 # (used in findOperands())
1243 commentRE
= re
.compile(r
'//.*\n')
1245 # Regular expression object to match assignment statements
1246 # (used in findOperands())
1247 assignRE
= re
.compile(r
'\s*=(?!=)', re
.MULTILINE
)
1250 # Find all the operands in the given code block. Returns an operand
1251 # descriptor list (instance of class OperandDescriptorList).
1253 def findOperands(code
):
1254 operands
= OperandDescriptorList()
1255 # delete comments so we don't accidentally match on reg specifiers inside
1256 code
= commentRE
.sub('', code
)
1257 # search for operands
1260 match
= operandsRE
.search(code
, next_pos
)
1262 # no more matches: we're done
1265 # regexp groups are operand full name, base, and extension
1266 (op_full
, op_base
, op_ext
) = op
1267 # if the token following the operand is an assignment, this is
1268 # a destination (LHS), else it's a source (RHS)
1269 is_dest
= (assignRE
.match(code
, match
.end()) != None)
1270 is_src
= not is_dest
1271 # see if we've already seen this one
1272 op_desc
= operands
.find_base(op_base
)
1274 if op_desc
.ext
!= op_ext
:
1275 error(0, 'Inconsistent extensions for operand %s' % op_base
)
1276 op_desc
.is_src
= op_desc
.is_src
or is_src
1277 op_desc
.is_dest
= op_desc
.is_dest
or is_dest
1279 # new operand: create new descriptor
1280 op_desc
= OperandDescriptor(op_full
, op_base
, op_ext
,
1282 operands
.append(op_desc
)
1283 # start next search after end of current match
1284 next_pos
= match
.end()
1286 # enumerate source & dest register operands... used in building
1290 operands
.numFPDestRegs
= 0
1291 operands
.numIntDestRegs
= 0
1292 for op_desc
in operands
:
1293 if op_desc
.traits
.isReg():
1295 op_desc
.src_reg_idx
= srcRegs
1298 op_desc
.dest_reg_idx
= destRegs
1300 if op_desc
.traits
.isFloatReg():
1301 operands
.numFPDestRegs
+= 1
1302 elif op_desc
.traits
.isIntReg():
1303 operands
.numIntDestRegs
+= 1
1304 operands
.numSrcRegs
= srcRegs
1305 operands
.numDestRegs
= destRegs
1306 # now make a final pass to finalize op_desc fields that may depend
1307 # on the register enumeration
1308 for op_desc
in operands
:
1312 # Munge operand names in code string to make legal C++ variable names.
1313 # (Will match munged_name attribute of OperandDescriptor object.)
1314 def substMungedOpNames(code
):
1315 return operandsWithExtRE
.sub(r
'\1_\2', code
)
1318 return map(string
.join
, t
)
1320 def makeFlagConstructor(flag_list
):
1321 if len(flag_list
) == 0:
1323 # filter out repeated flags
1326 while i
< len(flag_list
):
1327 if flag_list
[i
] == flag_list
[i
-1]:
1333 code
= pre
+ string
.join(flag_list
, post
+ pre
) + post
1337 def __init__(self
, code
):
1338 self
.orig_code
= code
1339 self
.operands
= findOperands(code
)
1340 self
.code
= substMungedOpNames(substBitOps(code
))
1341 self
.constructor
= self
.operands
.concatAttrStrings('constructor')
1342 self
.constructor
+= \
1343 '\n\t_numSrcRegs = %d;' % self
.operands
.numSrcRegs
1344 self
.constructor
+= \
1345 '\n\t_numDestRegs = %d;' % self
.operands
.numDestRegs
1346 self
.constructor
+= \
1347 '\n\t_numFPDestRegs = %d;' % self
.operands
.numFPDestRegs
1348 self
.constructor
+= \
1349 '\n\t_numIntDestRegs = %d;' % self
.operands
.numIntDestRegs
1351 self
.exec_decl
= self
.operands
.concatAttrStrings('exec_decl')
1353 is_mem
= lambda op
: op
.traits
.isMem()
1354 not_mem
= lambda op
: not op
.traits
.isMem()
1356 self
.simple_rd
= self
.operands
.concatAttrStrings('simple_rd')
1357 self
.simple_wb
= self
.operands
.concatAttrStrings('simple_wb')
1358 self
.simple_mem_rd
= \
1359 self
.operands
.concatSomeAttrStrings(is_mem
, 'simple_rd')
1360 self
.simple_mem_wb
= \
1361 self
.operands
.concatSomeAttrStrings(is_mem
, 'simple_wb')
1362 self
.simple_nonmem_rd
= \
1363 self
.operands
.concatSomeAttrStrings(not_mem
, 'simple_rd')
1364 self
.simple_nonmem_wb
= \
1365 self
.operands
.concatSomeAttrStrings(not_mem
, 'simple_wb')
1367 self
.dtld_rd
= self
.operands
.concatAttrStrings('dtld_rd')
1368 self
.dtld_wb
= self
.operands
.concatAttrStrings('dtld_wb')
1369 self
.dtld_mem_rd
= \
1370 self
.operands
.concatSomeAttrStrings(is_mem
, 'dtld_rd')
1371 self
.dtld_mem_wb
= \
1372 self
.operands
.concatSomeAttrStrings(is_mem
, 'dtld_wb')
1373 self
.dtld_nonmem_rd
= \
1374 self
.operands
.concatSomeAttrStrings(not_mem
, 'dtld_rd')
1375 self
.dtld_nonmem_wb
= \
1376 self
.operands
.concatSomeAttrStrings(not_mem
, 'dtld_wb')
1378 self
.flags
= self
.operands
.concatAttrLists('flags')
1380 # Make a basic guess on the operand class (function unit type).
1381 # These are good enough for most cases, and will be overridden
1383 if 'IsStore' in self
.flags
:
1384 self
.op_class
= 'WrPort'
1385 elif 'IsLoad' in self
.flags
or 'IsPrefetch' in self
.flags
:
1386 self
.op_class
= 'RdPort'
1387 elif 'IsFloating' in self
.flags
:
1388 self
.op_class
= 'FloatADD'
1390 self
.op_class
= 'IntALU'
1392 # Assume all instruction flags are of the form 'IsFoo'
1393 instFlagRE
= re
.compile(r
'Is.*')
1395 # OpClass constants are just a little more complicated
1396 opClassRE
= re
.compile(r
'Int.*|Float.*|.*Port|No_OpClass')
1398 class InstObjParams
:
1399 def __init__(self
, mnem
, class_name
, base_class
= '',
1400 code_block
= None, opt_args
= []):
1401 self
.mnemonic
= mnem
1402 self
.class_name
= class_name
1403 self
.base_class
= base_class
1405 for code_attr
in code_block
.__dict
__.keys():
1406 setattr(self
, code_attr
, getattr(code_block
, code_attr
))
1408 self
.constructor
= ''
1410 # Optional arguments are assumed to be either StaticInst flags
1411 # or an OpClass value. To avoid having to import a complete
1412 # list of these values to match against, we do it ad-hoc
1415 if instFlagRE
.match(oa
):
1416 self
.flags
.append(oa
)
1417 elif opClassRE
.match(oa
):
1420 error(0, 'InstObjParams: optional arg "%s" not recognized '
1421 'as StaticInst::Flag or OpClass.' % oa
)
1423 # add flag initialization to contructor here to include
1424 # any flags added via opt_args
1425 self
.constructor
+= makeFlagConstructor(self
.flags
)
1427 # if 'IsFloating' is set, add call to the FP enable check
1428 # function (which should be provided by isa_desc via a declare)
1429 if 'IsFloating' in self
.flags
:
1430 self
.fp_enable_check
= 'fault = checkFpEnableFault(xc);'
1432 self
.fp_enable_check
= ''
1434 def subst(self
, *args
):
1437 if not templateMap
.has_key(t
):
1438 error(0, 'InstObjParams::subst: undefined template "%s"' % t
)
1440 result
.append(templateMap
[t
] % self
.__dict
__)
1441 except KeyError, key
:
1442 error(0, 'InstObjParams::subst: no definition for "%s"' % key
)
1448 # All set... read in and parse the ISA description.
1450 yacc
.parse(isa_desc
)