isa_parser.py (6314:781969fbeca9) isa_parser.py (6338:14572c7334b5)
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):
1177 code = self.read_code % {"name": self.base_name,
1178 "func": func,
1179 "op_idx": self.src_reg_idx,
1180 "reg_idx": self.reg_spec,
1181 "size": self.size,
1182 "ctype": self.ctype}
1183 if self.size != self.dflt_size:
1184 return '%s = bits(%s, %d, 0);\n' % \
1185 (self.base_name, code, self.size-1)
1186 else:
1187 return '%s = %s;\n' % \
1188 (self.base_name, code)
1189
1190 def buildWriteCode(self, func = None):
1191 if (self.size != self.dflt_size and self.is_signed):
1192 final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
1193 else:
1194 final_val = self.base_name
1195 code = self.write_code % {"name": self.base_name,
1196 "func": func,
1197 "op_idx": self.dest_reg_idx,
1198 "reg_idx": self.reg_spec,
1199 "size": self.size,
1200 "ctype": self.ctype,
1201 "final_val": final_val}
1202 return '''
1203 {
1204 %s final_val = %s;
1205 %s;
1206 if (traceData) { traceData->setData(final_val); }
1207 }''' % (self.dflt_ctype, final_val, code)
1208
1209 def __init__(self, full_name, ext, is_src, is_dest):
1210 self.full_name = full_name
1211 self.ext = ext
1212 self.is_src = is_src
1213 self.is_dest = is_dest
1214 # The 'effective extension' (eff_ext) is either the actual
1215 # extension, if one was explicitly provided, or the default.
1216 if ext:
1217 self.eff_ext = ext
1218 else:
1219 self.eff_ext = self.dflt_ext
1220
1221 (self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext]
1222
1223 # note that mem_acc_size is undefined for non-mem operands...
1224 # template must be careful not to use it if it doesn't apply.
1225 if self.isMem():
1226 self.mem_acc_size = self.makeAccSize()
1227 if self.ctype in ['Twin32_t', 'Twin64_t']:
1228 self.mem_acc_type = 'Twin'
1229 else:
1230 self.mem_acc_type = 'uint'
1231
1232 # Finalize additional fields (primarily code fields). This step
1233 # is done separately since some of these fields may depend on the
1234 # register index enumeration that hasn't been performed yet at the
1235 # time of __init__().
1236 def finalize(self):
1237 self.flags = self.getFlags()
1238 self.constructor = self.makeConstructor()
1239 self.op_decl = self.makeDecl()
1240
1241 if self.is_src:
1242 self.op_rd = self.makeRead()
1243 self.op_src_decl = self.makeDecl()
1244 else:
1245 self.op_rd = ''
1246 self.op_src_decl = ''
1247
1248 if self.is_dest:
1249 self.op_wb = self.makeWrite()
1250 self.op_dest_decl = self.makeDecl()
1251 else:
1252 self.op_wb = ''
1253 self.op_dest_decl = ''
1254
1255 def isMem(self):
1256 return 0
1257
1258 def isReg(self):
1259 return 0
1260
1261 def isFloatReg(self):
1262 return 0
1263
1264 def isIntReg(self):
1265 return 0
1266
1267 def isControlReg(self):
1268 return 0
1269
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):
1177 code = self.read_code % {"name": self.base_name,
1178 "func": func,
1179 "op_idx": self.src_reg_idx,
1180 "reg_idx": self.reg_spec,
1181 "size": self.size,
1182 "ctype": self.ctype}
1183 if self.size != self.dflt_size:
1184 return '%s = bits(%s, %d, 0);\n' % \
1185 (self.base_name, code, self.size-1)
1186 else:
1187 return '%s = %s;\n' % \
1188 (self.base_name, code)
1189
1190 def buildWriteCode(self, func = None):
1191 if (self.size != self.dflt_size and self.is_signed):
1192 final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
1193 else:
1194 final_val = self.base_name
1195 code = self.write_code % {"name": self.base_name,
1196 "func": func,
1197 "op_idx": self.dest_reg_idx,
1198 "reg_idx": self.reg_spec,
1199 "size": self.size,
1200 "ctype": self.ctype,
1201 "final_val": final_val}
1202 return '''
1203 {
1204 %s final_val = %s;
1205 %s;
1206 if (traceData) { traceData->setData(final_val); }
1207 }''' % (self.dflt_ctype, final_val, code)
1208
1209 def __init__(self, full_name, ext, is_src, is_dest):
1210 self.full_name = full_name
1211 self.ext = ext
1212 self.is_src = is_src
1213 self.is_dest = is_dest
1214 # The 'effective extension' (eff_ext) is either the actual
1215 # extension, if one was explicitly provided, or the default.
1216 if ext:
1217 self.eff_ext = ext
1218 else:
1219 self.eff_ext = self.dflt_ext
1220
1221 (self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext]
1222
1223 # note that mem_acc_size is undefined for non-mem operands...
1224 # template must be careful not to use it if it doesn't apply.
1225 if self.isMem():
1226 self.mem_acc_size = self.makeAccSize()
1227 if self.ctype in ['Twin32_t', 'Twin64_t']:
1228 self.mem_acc_type = 'Twin'
1229 else:
1230 self.mem_acc_type = 'uint'
1231
1232 # Finalize additional fields (primarily code fields). This step
1233 # is done separately since some of these fields may depend on the
1234 # register index enumeration that hasn't been performed yet at the
1235 # time of __init__().
1236 def finalize(self):
1237 self.flags = self.getFlags()
1238 self.constructor = self.makeConstructor()
1239 self.op_decl = self.makeDecl()
1240
1241 if self.is_src:
1242 self.op_rd = self.makeRead()
1243 self.op_src_decl = self.makeDecl()
1244 else:
1245 self.op_rd = ''
1246 self.op_src_decl = ''
1247
1248 if self.is_dest:
1249 self.op_wb = self.makeWrite()
1250 self.op_dest_decl = self.makeDecl()
1251 else:
1252 self.op_wb = ''
1253 self.op_dest_decl = ''
1254
1255 def isMem(self):
1256 return 0
1257
1258 def isReg(self):
1259 return 0
1260
1261 def isFloatReg(self):
1262 return 0
1263
1264 def isIntReg(self):
1265 return 0
1266
1267 def isControlReg(self):
1268 return 0
1269
1270 def isIControlReg(self):
1271 return 0
1272
1273 def getFlags(self):
1274 # note the empty slice '[:]' gives us a copy of self.flags[0]
1275 # instead of a reference to it
1276 my_flags = self.flags[0][:]
1277 if self.is_src:
1278 my_flags += self.flags[1]
1279 if self.is_dest:
1280 my_flags += self.flags[2]
1281 return my_flags
1282
1283 def makeDecl(self):
1284 # Note that initializations in the declarations are solely
1285 # to avoid 'uninitialized variable' errors from the compiler.
1286 return self.ctype + ' ' + self.base_name + ' = 0;\n';
1287
1288class IntRegOperand(Operand):
1289 def isReg(self):
1290 return 1
1291
1292 def isIntReg(self):
1293 return 1
1294
1295 def makeConstructor(self):
1296 c = ''
1297 if self.is_src:
1298 c += '\n\t_srcRegIdx[%d] = %s;' % \
1299 (self.src_reg_idx, self.reg_spec)
1300 if self.is_dest:
1301 c += '\n\t_destRegIdx[%d] = %s;' % \
1302 (self.dest_reg_idx, self.reg_spec)
1303 return c
1304
1305 def makeRead(self):
1306 if (self.ctype == 'float' or self.ctype == 'double'):
1307 error(0, 'Attempt to read integer register as FP')
1308 if self.read_code != None:
1309 return self.buildReadCode('readIntRegOperand')
1310 if (self.size == self.dflt_size):
1311 return '%s = xc->readIntRegOperand(this, %d);\n' % \
1312 (self.base_name, self.src_reg_idx)
1313 elif (self.size > self.dflt_size):
1314 int_reg_val = 'xc->readIntRegOperand(this, %d)' % \
1315 (self.src_reg_idx)
1316 if (self.is_signed):
1317 int_reg_val = 'sext<%d>(%s)' % (self.dflt_size, int_reg_val)
1318 return '%s = %s;\n' % (self.base_name, int_reg_val)
1319 else:
1320 return '%s = bits(xc->readIntRegOperand(this, %d), %d, 0);\n' % \
1321 (self.base_name, self.src_reg_idx, self.size-1)
1322
1323 def makeWrite(self):
1324 if (self.ctype == 'float' or self.ctype == 'double'):
1325 error(0, 'Attempt to write integer register as FP')
1326 if self.write_code != None:
1327 return self.buildWriteCode('setIntRegOperand')
1328 if (self.size != self.dflt_size and self.is_signed):
1329 final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
1330 else:
1331 final_val = self.base_name
1332 wb = '''
1333 {
1334 %s final_val = %s;
1335 xc->setIntRegOperand(this, %d, final_val);\n
1336 if (traceData) { traceData->setData(final_val); }
1337 }''' % (self.dflt_ctype, final_val, self.dest_reg_idx)
1338 return wb
1339
1340class FloatRegOperand(Operand):
1341 def isReg(self):
1342 return 1
1343
1344 def isFloatReg(self):
1345 return 1
1346
1347 def makeConstructor(self):
1348 c = ''
1349 if self.is_src:
1350 c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
1351 (self.src_reg_idx, self.reg_spec)
1352 if self.is_dest:
1353 c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
1354 (self.dest_reg_idx, self.reg_spec)
1355 return c
1356
1357 def makeRead(self):
1358 bit_select = 0
1359 if (self.ctype == 'float' or self.ctype == 'double'):
1360 func = 'readFloatRegOperand'
1361 else:
1362 func = 'readFloatRegOperandBits'
1363 if (self.size != self.dflt_size):
1364 bit_select = 1
1365 base = 'xc->%s(this, %d)' % (func, self.src_reg_idx)
1366 if self.read_code != None:
1367 return self.buildReadCode(func)
1368 if bit_select:
1369 return '%s = bits(%s, %d, 0);\n' % \
1370 (self.base_name, base, self.size-1)
1371 else:
1372 return '%s = %s;\n' % (self.base_name, base)
1373
1374 def makeWrite(self):
1375 final_val = self.base_name
1376 final_ctype = self.ctype
1377 if (self.ctype == 'float' or self.ctype == 'double'):
1378 func = 'setFloatRegOperand'
1379 elif (self.ctype == 'uint32_t' or self.ctype == 'uint64_t'):
1380 func = 'setFloatRegOperandBits'
1381 else:
1382 func = 'setFloatRegOperandBits'
1383 final_ctype = 'uint%d_t' % self.dflt_size
1384 if (self.size != self.dflt_size and self.is_signed):
1385 final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
1386 if self.write_code != None:
1387 return self.buildWriteCode(func)
1388 wb = '''
1389 {
1390 %s final_val = %s;
1391 xc->%s(this, %d, final_val);\n
1392 if (traceData) { traceData->setData(final_val); }
1393 }''' % (final_ctype, final_val, func, self.dest_reg_idx)
1394 return wb
1395
1396class ControlRegOperand(Operand):
1397 def isReg(self):
1398 return 1
1399
1400 def isControlReg(self):
1401 return 1
1402
1403 def makeConstructor(self):
1404 c = ''
1405 if self.is_src:
1406 c += '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
1407 (self.src_reg_idx, self.reg_spec)
1408 if self.is_dest:
1409 c += '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
1410 (self.dest_reg_idx, self.reg_spec)
1411 return c
1412
1413 def makeRead(self):
1414 bit_select = 0
1415 if (self.ctype == 'float' or self.ctype == 'double'):
1416 error(0, 'Attempt to read control register as FP')
1417 if self.read_code != None:
1418 return self.buildReadCode('readMiscRegOperand')
1419 base = 'xc->readMiscRegOperand(this, %s)' % self.src_reg_idx
1420 if self.size == self.dflt_size:
1421 return '%s = %s;\n' % (self.base_name, base)
1422 else:
1423 return '%s = bits(%s, %d, 0);\n' % \
1424 (self.base_name, base, self.size-1)
1425
1426 def makeWrite(self):
1427 if (self.ctype == 'float' or self.ctype == 'double'):
1428 error(0, 'Attempt to write control register as FP')
1429 if self.write_code != None:
1430 return self.buildWriteCode('setMiscRegOperand')
1431 wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \
1432 (self.dest_reg_idx, self.base_name)
1433 wb += 'if (traceData) { traceData->setData(%s); }' % \
1434 self.base_name
1435 return wb
1436
1270 def getFlags(self):
1271 # note the empty slice '[:]' gives us a copy of self.flags[0]
1272 # instead of a reference to it
1273 my_flags = self.flags[0][:]
1274 if self.is_src:
1275 my_flags += self.flags[1]
1276 if self.is_dest:
1277 my_flags += self.flags[2]
1278 return my_flags
1279
1280 def makeDecl(self):
1281 # Note that initializations in the declarations are solely
1282 # to avoid 'uninitialized variable' errors from the compiler.
1283 return self.ctype + ' ' + self.base_name + ' = 0;\n';
1284
1285class IntRegOperand(Operand):
1286 def isReg(self):
1287 return 1
1288
1289 def isIntReg(self):
1290 return 1
1291
1292 def makeConstructor(self):
1293 c = ''
1294 if self.is_src:
1295 c += '\n\t_srcRegIdx[%d] = %s;' % \
1296 (self.src_reg_idx, self.reg_spec)
1297 if self.is_dest:
1298 c += '\n\t_destRegIdx[%d] = %s;' % \
1299 (self.dest_reg_idx, self.reg_spec)
1300 return c
1301
1302 def makeRead(self):
1303 if (self.ctype == 'float' or self.ctype == 'double'):
1304 error(0, 'Attempt to read integer register as FP')
1305 if self.read_code != None:
1306 return self.buildReadCode('readIntRegOperand')
1307 if (self.size == self.dflt_size):
1308 return '%s = xc->readIntRegOperand(this, %d);\n' % \
1309 (self.base_name, self.src_reg_idx)
1310 elif (self.size > self.dflt_size):
1311 int_reg_val = 'xc->readIntRegOperand(this, %d)' % \
1312 (self.src_reg_idx)
1313 if (self.is_signed):
1314 int_reg_val = 'sext<%d>(%s)' % (self.dflt_size, int_reg_val)
1315 return '%s = %s;\n' % (self.base_name, int_reg_val)
1316 else:
1317 return '%s = bits(xc->readIntRegOperand(this, %d), %d, 0);\n' % \
1318 (self.base_name, self.src_reg_idx, self.size-1)
1319
1320 def makeWrite(self):
1321 if (self.ctype == 'float' or self.ctype == 'double'):
1322 error(0, 'Attempt to write integer register as FP')
1323 if self.write_code != None:
1324 return self.buildWriteCode('setIntRegOperand')
1325 if (self.size != self.dflt_size and self.is_signed):
1326 final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
1327 else:
1328 final_val = self.base_name
1329 wb = '''
1330 {
1331 %s final_val = %s;
1332 xc->setIntRegOperand(this, %d, final_val);\n
1333 if (traceData) { traceData->setData(final_val); }
1334 }''' % (self.dflt_ctype, final_val, self.dest_reg_idx)
1335 return wb
1336
1337class FloatRegOperand(Operand):
1338 def isReg(self):
1339 return 1
1340
1341 def isFloatReg(self):
1342 return 1
1343
1344 def makeConstructor(self):
1345 c = ''
1346 if self.is_src:
1347 c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
1348 (self.src_reg_idx, self.reg_spec)
1349 if self.is_dest:
1350 c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
1351 (self.dest_reg_idx, self.reg_spec)
1352 return c
1353
1354 def makeRead(self):
1355 bit_select = 0
1356 if (self.ctype == 'float' or self.ctype == 'double'):
1357 func = 'readFloatRegOperand'
1358 else:
1359 func = 'readFloatRegOperandBits'
1360 if (self.size != self.dflt_size):
1361 bit_select = 1
1362 base = 'xc->%s(this, %d)' % (func, self.src_reg_idx)
1363 if self.read_code != None:
1364 return self.buildReadCode(func)
1365 if bit_select:
1366 return '%s = bits(%s, %d, 0);\n' % \
1367 (self.base_name, base, self.size-1)
1368 else:
1369 return '%s = %s;\n' % (self.base_name, base)
1370
1371 def makeWrite(self):
1372 final_val = self.base_name
1373 final_ctype = self.ctype
1374 if (self.ctype == 'float' or self.ctype == 'double'):
1375 func = 'setFloatRegOperand'
1376 elif (self.ctype == 'uint32_t' or self.ctype == 'uint64_t'):
1377 func = 'setFloatRegOperandBits'
1378 else:
1379 func = 'setFloatRegOperandBits'
1380 final_ctype = 'uint%d_t' % self.dflt_size
1381 if (self.size != self.dflt_size and self.is_signed):
1382 final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
1383 if self.write_code != None:
1384 return self.buildWriteCode(func)
1385 wb = '''
1386 {
1387 %s final_val = %s;
1388 xc->%s(this, %d, final_val);\n
1389 if (traceData) { traceData->setData(final_val); }
1390 }''' % (final_ctype, final_val, func, self.dest_reg_idx)
1391 return wb
1392
1393class ControlRegOperand(Operand):
1394 def isReg(self):
1395 return 1
1396
1397 def isControlReg(self):
1398 return 1
1399
1400 def makeConstructor(self):
1401 c = ''
1402 if self.is_src:
1403 c += '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
1404 (self.src_reg_idx, self.reg_spec)
1405 if self.is_dest:
1406 c += '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
1407 (self.dest_reg_idx, self.reg_spec)
1408 return c
1409
1410 def makeRead(self):
1411 bit_select = 0
1412 if (self.ctype == 'float' or self.ctype == 'double'):
1413 error(0, 'Attempt to read control register as FP')
1414 if self.read_code != None:
1415 return self.buildReadCode('readMiscRegOperand')
1416 base = 'xc->readMiscRegOperand(this, %s)' % self.src_reg_idx
1417 if self.size == self.dflt_size:
1418 return '%s = %s;\n' % (self.base_name, base)
1419 else:
1420 return '%s = bits(%s, %d, 0);\n' % \
1421 (self.base_name, base, self.size-1)
1422
1423 def makeWrite(self):
1424 if (self.ctype == 'float' or self.ctype == 'double'):
1425 error(0, 'Attempt to write control register as FP')
1426 if self.write_code != None:
1427 return self.buildWriteCode('setMiscRegOperand')
1428 wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \
1429 (self.dest_reg_idx, self.base_name)
1430 wb += 'if (traceData) { traceData->setData(%s); }' % \
1431 self.base_name
1432 return wb
1433
1437class IControlRegOperand(Operand):
1438 def isReg(self):
1439 return 1
1440
1441 def isIControlReg(self):
1442 return 1
1443
1444 def makeConstructor(self):
1445 c = ''
1446 if self.is_src:
1447 c += '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
1448 (self.src_reg_idx, self.reg_spec)
1449 if self.is_dest:
1450 c += '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
1451 (self.dest_reg_idx, self.reg_spec)
1452 return c
1453
1454 def makeRead(self):
1455 bit_select = 0
1456 if (self.ctype == 'float' or self.ctype == 'double'):
1457 error(0, 'Attempt to read control register as FP')
1458 if self.read_code != None:
1459 return self.buildReadCode('readMiscReg')
1460 base = 'xc->readMiscReg(%s)' % self.reg_spec
1461 if self.size == self.dflt_size:
1462 return '%s = %s;\n' % (self.base_name, base)
1463 else:
1464 return '%s = bits(%s, %d, 0);\n' % \
1465 (self.base_name, base, self.size-1)
1466
1467 def makeWrite(self):
1468 if (self.ctype == 'float' or self.ctype == 'double'):
1469 error(0, 'Attempt to write control register as FP')
1470 if self.write_code != None:
1471 return self.buildWriteCode('setMiscReg')
1472 wb = 'xc->setMiscReg(%s, %s);\n' % \
1473 (self.reg_spec, self.base_name)
1474 wb += 'if (traceData) { traceData->setData(%s); }' % \
1475 self.base_name
1476 return wb
1477
1478class ControlBitfieldOperand(ControlRegOperand):
1479 def makeRead(self):
1480 bit_select = 0
1481 if (self.ctype == 'float' or self.ctype == 'double'):
1482 error(0, 'Attempt to read control register as FP')
1483 if self.read_code != None:
1484 return self.buildReadCode('readMiscReg')
1485 base = 'xc->readMiscReg(%s)' % self.reg_spec
1486 name = self.base_name
1487 return '%s = bits(%s, %s_HI, %s_LO);' % \
1488 (name, base, name, name)
1489
1490 def makeWrite(self):
1491 if (self.ctype == 'float' or self.ctype == 'double'):
1492 error(0, 'Attempt to write control register as FP')
1493 if self.write_code != None:
1494 return self.buildWriteCode('setMiscReg')
1495 base = 'xc->readMiscReg(%s)' % self.reg_spec
1496 name = self.base_name
1497 wb_val = 'insertBits(%s, %s_HI, %s_LO, %s)' % \
1498 (base, name, name, self.base_name)
1499 wb = 'xc->setMiscRegOperand(this, %s, %s );\n' % (self.dest_reg_idx, wb_val)
1500 wb += 'if (traceData) { traceData->setData(%s); }' % \
1501 self.base_name
1502 return wb
1503
1504class MemOperand(Operand):
1505 def isMem(self):
1506 return 1
1507
1508 def makeConstructor(self):
1509 return ''
1510
1511 def makeDecl(self):
1512 # Note that initializations in the declarations are solely
1513 # to avoid 'uninitialized variable' errors from the compiler.
1514 # Declare memory data variable.
1515 if self.ctype in ['Twin32_t','Twin64_t']:
1516 return "%s %s; %s.a = 0; %s.b = 0;\n" % (self.ctype, self.base_name,
1517 self.base_name, self.base_name)
1518 c = '%s %s = 0;\n' % (self.ctype, self.base_name)
1519 return c
1520
1521 def makeRead(self):
1522 if self.read_code != None:
1523 return self.buildReadCode()
1524 return ''
1525
1526 def makeWrite(self):
1527 if self.write_code != None:
1528 return self.buildWriteCode()
1529 return ''
1530
1531 # Return the memory access size *in bits*, suitable for
1532 # forming a type via "uint%d_t". Divide by 8 if you want bytes.
1533 def makeAccSize(self):
1534 return self.size
1535
1536class UPCOperand(Operand):
1537 def makeConstructor(self):
1538 return ''
1539
1540 def makeRead(self):
1541 if self.read_code != None:
1542 return self.buildReadCode('readMicroPC')
1543 return '%s = xc->readMicroPC();\n' % self.base_name
1544
1545 def makeWrite(self):
1546 if self.write_code != None:
1547 return self.buildWriteCode('setMicroPC')
1548 return 'xc->setMicroPC(%s);\n' % self.base_name
1549
1550class NUPCOperand(Operand):
1551 def makeConstructor(self):
1552 return ''
1553
1554 def makeRead(self):
1555 if self.read_code != None:
1556 return self.buildReadCode('readNextMicroPC')
1557 return '%s = xc->readNextMicroPC();\n' % self.base_name
1558
1559 def makeWrite(self):
1560 if self.write_code != None:
1561 return self.buildWriteCode('setNextMicroPC')
1562 return 'xc->setNextMicroPC(%s);\n' % self.base_name
1563
1564class NPCOperand(Operand):
1565 def makeConstructor(self):
1566 return ''
1567
1568 def makeRead(self):
1569 if self.read_code != None:
1570 return self.buildReadCode('readNextPC')
1571 return '%s = xc->readNextPC();\n' % self.base_name
1572
1573 def makeWrite(self):
1574 if self.write_code != None:
1575 return self.buildWriteCode('setNextPC')
1576 return 'xc->setNextPC(%s);\n' % self.base_name
1577
1578class NNPCOperand(Operand):
1579 def makeConstructor(self):
1580 return ''
1581
1582 def makeRead(self):
1583 if self.read_code != None:
1584 return self.buildReadCode('readNextNPC')
1585 return '%s = xc->readNextNPC();\n' % self.base_name
1586
1587 def makeWrite(self):
1588 if self.write_code != None:
1589 return self.buildWriteCode('setNextNPC')
1590 return 'xc->setNextNPC(%s);\n' % self.base_name
1591
1592def buildOperandNameMap(userDict, lineno):
1593 global operandNameMap
1594 operandNameMap = {}
1595 for (op_name, val) in userDict.iteritems():
1596 (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val[:5]
1597 if len(val) > 5:
1598 read_code = val[5]
1599 else:
1600 read_code = None
1601 if len(val) > 6:
1602 write_code = val[6]
1603 else:
1604 write_code = None
1605 if len(val) > 7:
1606 error(lineno,
1607 'error: too many attributes for operand "%s"' %
1608 base_cls_name)
1609
1610 (dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext]
1611 # Canonical flag structure is a triple of lists, where each list
1612 # indicates the set of flags implied by this operand always, when
1613 # used as a source, and when used as a dest, respectively.
1614 # For simplicity this can be initialized using a variety of fairly
1615 # obvious shortcuts; we convert these to canonical form here.
1616 if not flags:
1617 # no flags specified (e.g., 'None')
1618 flags = ( [], [], [] )
1619 elif isinstance(flags, str):
1620 # a single flag: assumed to be unconditional
1621 flags = ( [ flags ], [], [] )
1622 elif isinstance(flags, list):
1623 # a list of flags: also assumed to be unconditional
1624 flags = ( flags, [], [] )
1625 elif isinstance(flags, tuple):
1626 # it's a tuple: it should be a triple,
1627 # but each item could be a single string or a list
1628 (uncond_flags, src_flags, dest_flags) = flags
1629 flags = (makeList(uncond_flags),
1630 makeList(src_flags), makeList(dest_flags))
1631 # Accumulate attributes of new operand class in tmp_dict
1632 tmp_dict = {}
1633 for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
1634 'dflt_size', 'dflt_ctype', 'dflt_is_signed',
1635 'read_code', 'write_code'):
1636 tmp_dict[attr] = eval(attr)
1637 tmp_dict['base_name'] = op_name
1638 # New class name will be e.g. "IntReg_Ra"
1639 cls_name = base_cls_name + '_' + op_name
1640 # Evaluate string arg to get class object. Note that the
1641 # actual base class for "IntReg" is "IntRegOperand", i.e. we
1642 # have to append "Operand".
1643 try:
1644 base_cls = eval(base_cls_name + 'Operand')
1645 except NameError:
1646 error(lineno,
1647 'error: unknown operand base class "%s"' % base_cls_name)
1648 # The following statement creates a new class called
1649 # <cls_name> as a subclass of <base_cls> with the attributes
1650 # in tmp_dict, just as if we evaluated a class declaration.
1651 operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict)
1652
1653 # Define operand variables.
1654 operands = userDict.keys()
1655
1656 operandsREString = (r'''
1657 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
1658 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
1659 (?![\w\.]) # neg. lookahead assertion: prevent partial matches
1660 '''
1661 % string.join(operands, '|'))
1662
1663 global operandsRE
1664 operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
1665
1666 # Same as operandsREString, but extension is mandatory, and only two
1667 # groups are returned (base and ext, not full name as above).
1668 # Used for subtituting '_' for '.' to make C++ identifiers.
1669 operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
1670 % string.join(operands, '|'))
1671
1672 global operandsWithExtRE
1673 operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)
1674
1675maxInstSrcRegs = 0
1676maxInstDestRegs = 0
1677
1678class OperandList:
1679
1680 # Find all the operands in the given code block. Returns an operand
1681 # descriptor list (instance of class OperandList).
1682 def __init__(self, code):
1683 self.items = []
1684 self.bases = {}
1685 # delete comments so we don't match on reg specifiers inside
1686 code = commentRE.sub('', code)
1687 # search for operands
1688 next_pos = 0
1689 while 1:
1690 match = operandsRE.search(code, next_pos)
1691 if not match:
1692 # no more matches: we're done
1693 break
1694 op = match.groups()
1695 # regexp groups are operand full name, base, and extension
1696 (op_full, op_base, op_ext) = op
1697 # if the token following the operand is an assignment, this is
1698 # a destination (LHS), else it's a source (RHS)
1699 is_dest = (assignRE.match(code, match.end()) != None)
1700 is_src = not is_dest
1701 # see if we've already seen this one
1702 op_desc = self.find_base(op_base)
1703 if op_desc:
1704 if op_desc.ext != op_ext:
1705 error(0, 'Inconsistent extensions for operand %s' % \
1706 op_base)
1707 op_desc.is_src = op_desc.is_src or is_src
1708 op_desc.is_dest = op_desc.is_dest or is_dest
1709 else:
1710 # new operand: create new descriptor
1711 op_desc = operandNameMap[op_base](op_full, op_ext,
1712 is_src, is_dest)
1713 self.append(op_desc)
1714 # start next search after end of current match
1715 next_pos = match.end()
1716 self.sort()
1717 # enumerate source & dest register operands... used in building
1718 # constructor later
1719 self.numSrcRegs = 0
1720 self.numDestRegs = 0
1721 self.numFPDestRegs = 0
1722 self.numIntDestRegs = 0
1723 self.memOperand = None
1724 for op_desc in self.items:
1725 if op_desc.isReg():
1726 if op_desc.is_src:
1727 op_desc.src_reg_idx = self.numSrcRegs
1728 self.numSrcRegs += 1
1729 if op_desc.is_dest:
1730 op_desc.dest_reg_idx = self.numDestRegs
1731 self.numDestRegs += 1
1732 if op_desc.isFloatReg():
1733 self.numFPDestRegs += 1
1734 elif op_desc.isIntReg():
1735 self.numIntDestRegs += 1
1736 elif op_desc.isMem():
1737 if self.memOperand:
1738 error(0, "Code block has more than one memory operand.")
1739 self.memOperand = op_desc
1740 global maxInstSrcRegs
1741 global maxInstDestRegs
1742 if maxInstSrcRegs < self.numSrcRegs:
1743 maxInstSrcRegs = self.numSrcRegs
1744 if maxInstDestRegs < self.numDestRegs:
1745 maxInstDestRegs = self.numDestRegs
1746 # now make a final pass to finalize op_desc fields that may depend
1747 # on the register enumeration
1748 for op_desc in self.items:
1749 op_desc.finalize()
1750
1751 def __len__(self):
1752 return len(self.items)
1753
1754 def __getitem__(self, index):
1755 return self.items[index]
1756
1757 def append(self, op_desc):
1758 self.items.append(op_desc)
1759 self.bases[op_desc.base_name] = op_desc
1760
1761 def find_base(self, base_name):
1762 # like self.bases[base_name], but returns None if not found
1763 # (rather than raising exception)
1764 return self.bases.get(base_name)
1765
1766 # internal helper function for concat[Some]Attr{Strings|Lists}
1767 def __internalConcatAttrs(self, attr_name, filter, result):
1768 for op_desc in self.items:
1769 if filter(op_desc):
1770 result += getattr(op_desc, attr_name)
1771 return result
1772
1773 # return a single string that is the concatenation of the (string)
1774 # values of the specified attribute for all operands
1775 def concatAttrStrings(self, attr_name):
1776 return self.__internalConcatAttrs(attr_name, lambda x: 1, '')
1777
1778 # like concatAttrStrings, but only include the values for the operands
1779 # for which the provided filter function returns true
1780 def concatSomeAttrStrings(self, filter, attr_name):
1781 return self.__internalConcatAttrs(attr_name, filter, '')
1782
1783 # return a single list that is the concatenation of the (list)
1784 # values of the specified attribute for all operands
1785 def concatAttrLists(self, attr_name):
1786 return self.__internalConcatAttrs(attr_name, lambda x: 1, [])
1787
1788 # like concatAttrLists, but only include the values for the operands
1789 # for which the provided filter function returns true
1790 def concatSomeAttrLists(self, filter, attr_name):
1791 return self.__internalConcatAttrs(attr_name, filter, [])
1792
1793 def sort(self):
1794 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
1795
1796class SubOperandList(OperandList):
1797
1798 # Find all the operands in the given code block. Returns an operand
1799 # descriptor list (instance of class OperandList).
1800 def __init__(self, code, master_list):
1801 self.items = []
1802 self.bases = {}
1803 # delete comments so we don't match on reg specifiers inside
1804 code = commentRE.sub('', code)
1805 # search for operands
1806 next_pos = 0
1807 while 1:
1808 match = operandsRE.search(code, next_pos)
1809 if not match:
1810 # no more matches: we're done
1811 break
1812 op = match.groups()
1813 # regexp groups are operand full name, base, and extension
1814 (op_full, op_base, op_ext) = op
1815 # find this op in the master list
1816 op_desc = master_list.find_base(op_base)
1817 if not op_desc:
1818 error(0, 'Found operand %s which is not in the master list!' \
1819 ' This is an internal error' % \
1820 op_base)
1821 else:
1822 # See if we've already found this operand
1823 op_desc = self.find_base(op_base)
1824 if not op_desc:
1825 # if not, add a reference to it to this sub list
1826 self.append(master_list.bases[op_base])
1827
1828 # start next search after end of current match
1829 next_pos = match.end()
1830 self.sort()
1831 self.memOperand = None
1832 for op_desc in self.items:
1833 if op_desc.isMem():
1834 if self.memOperand:
1835 error(0, "Code block has more than one memory operand.")
1836 self.memOperand = op_desc
1837
1838# Regular expression object to match C++ comments
1839# (used in findOperands())
1840commentRE = re.compile(r'//.*\n')
1841
1842# Regular expression object to match assignment statements
1843# (used in findOperands())
1844assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
1845
1846# Munge operand names in code string to make legal C++ variable names.
1847# This means getting rid of the type extension if any.
1848# (Will match base_name attribute of Operand object.)
1849def substMungedOpNames(code):
1850 return operandsWithExtRE.sub(r'\1', code)
1851
1852# Fix up code snippets for final substitution in templates.
1853def mungeSnippet(s):
1854 if isinstance(s, str):
1855 return substMungedOpNames(substBitOps(s))
1856 else:
1857 return s
1858
1859def makeFlagConstructor(flag_list):
1860 if len(flag_list) == 0:
1861 return ''
1862 # filter out repeated flags
1863 flag_list.sort()
1864 i = 1
1865 while i < len(flag_list):
1866 if flag_list[i] == flag_list[i-1]:
1867 del flag_list[i]
1868 else:
1869 i += 1
1870 pre = '\n\tflags['
1871 post = '] = true;'
1872 code = pre + string.join(flag_list, post + pre) + post
1873 return code
1874
1875# Assume all instruction flags are of the form 'IsFoo'
1876instFlagRE = re.compile(r'Is.*')
1877
1878# OpClass constants end in 'Op' except No_OpClass
1879opClassRE = re.compile(r'.*Op|No_OpClass')
1880
1881class InstObjParams:
1882 def __init__(self, mnem, class_name, base_class = '',
1883 snippets = {}, opt_args = []):
1884 self.mnemonic = mnem
1885 self.class_name = class_name
1886 self.base_class = base_class
1887 if not isinstance(snippets, dict):
1888 snippets = {'code' : snippets}
1889 compositeCode = ' '.join(map(str, snippets.values()))
1890 self.snippets = snippets
1891
1892 self.operands = OperandList(compositeCode)
1893 self.constructor = self.operands.concatAttrStrings('constructor')
1894 self.constructor += \
1895 '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
1896 self.constructor += \
1897 '\n\t_numDestRegs = %d;' % self.operands.numDestRegs
1898 self.constructor += \
1899 '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs
1900 self.constructor += \
1901 '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
1902 self.flags = self.operands.concatAttrLists('flags')
1903
1904 # Make a basic guess on the operand class (function unit type).
1905 # These are good enough for most cases, and can be overridden
1906 # later otherwise.
1907 if 'IsStore' in self.flags:
1908 self.op_class = 'MemWriteOp'
1909 elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags:
1910 self.op_class = 'MemReadOp'
1911 elif 'IsFloating' in self.flags:
1912 self.op_class = 'FloatAddOp'
1913 else:
1914 self.op_class = 'IntAluOp'
1915
1916 # Optional arguments are assumed to be either StaticInst flags
1917 # or an OpClass value. To avoid having to import a complete
1918 # list of these values to match against, we do it ad-hoc
1919 # with regexps.
1920 for oa in opt_args:
1921 if instFlagRE.match(oa):
1922 self.flags.append(oa)
1923 elif opClassRE.match(oa):
1924 self.op_class = oa
1925 else:
1926 error(0, 'InstObjParams: optional arg "%s" not recognized '
1927 'as StaticInst::Flag or OpClass.' % oa)
1928
1929 # add flag initialization to contructor here to include
1930 # any flags added via opt_args
1931 self.constructor += makeFlagConstructor(self.flags)
1932
1933 # if 'IsFloating' is set, add call to the FP enable check
1934 # function (which should be provided by isa_desc via a declare)
1935 if 'IsFloating' in self.flags:
1936 self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
1937 else:
1938 self.fp_enable_check = ''
1939
1940#######################
1941#
1942# Output file template
1943#
1944
1945file_template = '''
1946/*
1947 * DO NOT EDIT THIS FILE!!!
1948 *
1949 * It was automatically generated from the ISA description in %(filename)s
1950 */
1951
1952%(includes)s
1953
1954%(global_output)s
1955
1956namespace %(namespace)s {
1957
1958%(namespace_output)s
1959
1960} // namespace %(namespace)s
1961
1962%(decode_function)s
1963'''
1964
1965max_inst_regs_template = '''
1966/*
1967 * DO NOT EDIT THIS FILE!!!
1968 *
1969 * It was automatically generated from the ISA description in %(filename)s
1970 */
1971
1972namespace %(namespace)s {
1973
1974 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
1975 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
1976
1977} // namespace %(namespace)s
1978
1979'''
1980
1981
1982# Update the output file only if the new contents are different from
1983# the current contents. Minimizes the files that need to be rebuilt
1984# after minor changes.
1985def update_if_needed(file, contents):
1986 update = False
1987 if os.access(file, os.R_OK):
1988 f = open(file, 'r')
1989 old_contents = f.read()
1990 f.close()
1991 if contents != old_contents:
1992 print 'Updating', file
1993 os.remove(file) # in case it's write-protected
1994 update = True
1995 else:
1996 print 'File', file, 'is unchanged'
1997 else:
1998 print 'Generating', file
1999 update = True
2000 if update:
2001 f = open(file, 'w')
2002 f.write(contents)
2003 f.close()
2004
2005# This regular expression matches '##include' directives
2006includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
2007 re.MULTILINE)
2008
2009# Function to replace a matched '##include' directive with the
2010# contents of the specified file (with nested ##includes replaced
2011# recursively). 'matchobj' is an re match object (from a match of
2012# includeRE) and 'dirname' is the directory relative to which the file
2013# path should be resolved.
2014def replace_include(matchobj, dirname):
2015 fname = matchobj.group('filename')
2016 full_fname = os.path.normpath(os.path.join(dirname, fname))
2017 contents = '##newfile "%s"\n%s\n##endfile\n' % \
2018 (full_fname, read_and_flatten(full_fname))
2019 return contents
2020
2021# Read a file and recursively flatten nested '##include' files.
2022def read_and_flatten(filename):
2023 current_dir = os.path.dirname(filename)
2024 try:
2025 contents = open(filename).read()
2026 except IOError:
2027 error(0, 'Error including file "%s"' % filename)
2028 fileNameStack.push((filename, 0))
2029 # Find any includes and include them
2030 contents = includeRE.sub(lambda m: replace_include(m, current_dir),
2031 contents)
2032 fileNameStack.pop()
2033 return contents
2034
2035#
2036# Read in and parse the ISA description.
2037#
2038def parse_isa_desc(isa_desc_file, output_dir):
2039 # Read file and (recursively) all included files into a string.
2040 # PLY requires that the input be in a single string so we have to
2041 # do this up front.
2042 isa_desc = read_and_flatten(isa_desc_file)
2043
2044 # Initialize filename stack with outer file.
2045 fileNameStack.push((isa_desc_file, 0))
2046
2047 # Parse it.
2048 (isa_name, namespace, global_code, namespace_code) = \
2049 parser.parse(isa_desc, lexer=lexer)
2050
2051 # grab the last three path components of isa_desc_file to put in
2052 # the output
2053 filename = '/'.join(isa_desc_file.split('/')[-3:])
2054
2055 # generate decoder.hh
2056 includes = '#include "base/bitfield.hh" // for bitfield support'
2057 global_output = global_code.header_output
2058 namespace_output = namespace_code.header_output
2059 decode_function = ''
2060 update_if_needed(output_dir + '/decoder.hh', file_template % vars())
2061
2062 # generate decoder.cc
2063 includes = '#include "decoder.hh"'
2064 global_output = global_code.decoder_output
2065 namespace_output = namespace_code.decoder_output
2066 # namespace_output += namespace_code.decode_block
2067 decode_function = namespace_code.decode_block
2068 update_if_needed(output_dir + '/decoder.cc', file_template % vars())
2069
2070 # generate per-cpu exec files
2071 for cpu in cpu_models:
2072 includes = '#include "decoder.hh"\n'
2073 includes += cpu.includes
2074 global_output = global_code.exec_output[cpu.name]
2075 namespace_output = namespace_code.exec_output[cpu.name]
2076 decode_function = ''
2077 update_if_needed(output_dir + '/' + cpu.filename,
2078 file_template % vars())
2079
2080 # The variable names here are hacky, but this will creat local variables
2081 # which will be referenced in vars() which have the value of the globals.
2082 global maxInstSrcRegs
2083 MaxInstSrcRegs = maxInstSrcRegs
2084 global maxInstDestRegs
2085 MaxInstDestRegs = maxInstDestRegs
2086 # max_inst_regs.hh
2087 update_if_needed(output_dir + '/max_inst_regs.hh', \
2088 max_inst_regs_template % vars())
2089
2090# global list of CpuModel objects (see cpu_models.py)
2091cpu_models = []
2092
2093# Called as script: get args from command line.
2094# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2095if __name__ == '__main__':
2096 execfile(sys.argv[1]) # read in CpuModel definitions
2097 cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
2098 parse_isa_desc(sys.argv[2], sys.argv[3])
1434class ControlBitfieldOperand(ControlRegOperand):
1435 def makeRead(self):
1436 bit_select = 0
1437 if (self.ctype == 'float' or self.ctype == 'double'):
1438 error(0, 'Attempt to read control register as FP')
1439 if self.read_code != None:
1440 return self.buildReadCode('readMiscReg')
1441 base = 'xc->readMiscReg(%s)' % self.reg_spec
1442 name = self.base_name
1443 return '%s = bits(%s, %s_HI, %s_LO);' % \
1444 (name, base, name, name)
1445
1446 def makeWrite(self):
1447 if (self.ctype == 'float' or self.ctype == 'double'):
1448 error(0, 'Attempt to write control register as FP')
1449 if self.write_code != None:
1450 return self.buildWriteCode('setMiscReg')
1451 base = 'xc->readMiscReg(%s)' % self.reg_spec
1452 name = self.base_name
1453 wb_val = 'insertBits(%s, %s_HI, %s_LO, %s)' % \
1454 (base, name, name, self.base_name)
1455 wb = 'xc->setMiscRegOperand(this, %s, %s );\n' % (self.dest_reg_idx, wb_val)
1456 wb += 'if (traceData) { traceData->setData(%s); }' % \
1457 self.base_name
1458 return wb
1459
1460class MemOperand(Operand):
1461 def isMem(self):
1462 return 1
1463
1464 def makeConstructor(self):
1465 return ''
1466
1467 def makeDecl(self):
1468 # Note that initializations in the declarations are solely
1469 # to avoid 'uninitialized variable' errors from the compiler.
1470 # Declare memory data variable.
1471 if self.ctype in ['Twin32_t','Twin64_t']:
1472 return "%s %s; %s.a = 0; %s.b = 0;\n" % (self.ctype, self.base_name,
1473 self.base_name, self.base_name)
1474 c = '%s %s = 0;\n' % (self.ctype, self.base_name)
1475 return c
1476
1477 def makeRead(self):
1478 if self.read_code != None:
1479 return self.buildReadCode()
1480 return ''
1481
1482 def makeWrite(self):
1483 if self.write_code != None:
1484 return self.buildWriteCode()
1485 return ''
1486
1487 # Return the memory access size *in bits*, suitable for
1488 # forming a type via "uint%d_t". Divide by 8 if you want bytes.
1489 def makeAccSize(self):
1490 return self.size
1491
1492class UPCOperand(Operand):
1493 def makeConstructor(self):
1494 return ''
1495
1496 def makeRead(self):
1497 if self.read_code != None:
1498 return self.buildReadCode('readMicroPC')
1499 return '%s = xc->readMicroPC();\n' % self.base_name
1500
1501 def makeWrite(self):
1502 if self.write_code != None:
1503 return self.buildWriteCode('setMicroPC')
1504 return 'xc->setMicroPC(%s);\n' % self.base_name
1505
1506class NUPCOperand(Operand):
1507 def makeConstructor(self):
1508 return ''
1509
1510 def makeRead(self):
1511 if self.read_code != None:
1512 return self.buildReadCode('readNextMicroPC')
1513 return '%s = xc->readNextMicroPC();\n' % self.base_name
1514
1515 def makeWrite(self):
1516 if self.write_code != None:
1517 return self.buildWriteCode('setNextMicroPC')
1518 return 'xc->setNextMicroPC(%s);\n' % self.base_name
1519
1520class NPCOperand(Operand):
1521 def makeConstructor(self):
1522 return ''
1523
1524 def makeRead(self):
1525 if self.read_code != None:
1526 return self.buildReadCode('readNextPC')
1527 return '%s = xc->readNextPC();\n' % self.base_name
1528
1529 def makeWrite(self):
1530 if self.write_code != None:
1531 return self.buildWriteCode('setNextPC')
1532 return 'xc->setNextPC(%s);\n' % self.base_name
1533
1534class NNPCOperand(Operand):
1535 def makeConstructor(self):
1536 return ''
1537
1538 def makeRead(self):
1539 if self.read_code != None:
1540 return self.buildReadCode('readNextNPC')
1541 return '%s = xc->readNextNPC();\n' % self.base_name
1542
1543 def makeWrite(self):
1544 if self.write_code != None:
1545 return self.buildWriteCode('setNextNPC')
1546 return 'xc->setNextNPC(%s);\n' % self.base_name
1547
1548def buildOperandNameMap(userDict, lineno):
1549 global operandNameMap
1550 operandNameMap = {}
1551 for (op_name, val) in userDict.iteritems():
1552 (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val[:5]
1553 if len(val) > 5:
1554 read_code = val[5]
1555 else:
1556 read_code = None
1557 if len(val) > 6:
1558 write_code = val[6]
1559 else:
1560 write_code = None
1561 if len(val) > 7:
1562 error(lineno,
1563 'error: too many attributes for operand "%s"' %
1564 base_cls_name)
1565
1566 (dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext]
1567 # Canonical flag structure is a triple of lists, where each list
1568 # indicates the set of flags implied by this operand always, when
1569 # used as a source, and when used as a dest, respectively.
1570 # For simplicity this can be initialized using a variety of fairly
1571 # obvious shortcuts; we convert these to canonical form here.
1572 if not flags:
1573 # no flags specified (e.g., 'None')
1574 flags = ( [], [], [] )
1575 elif isinstance(flags, str):
1576 # a single flag: assumed to be unconditional
1577 flags = ( [ flags ], [], [] )
1578 elif isinstance(flags, list):
1579 # a list of flags: also assumed to be unconditional
1580 flags = ( flags, [], [] )
1581 elif isinstance(flags, tuple):
1582 # it's a tuple: it should be a triple,
1583 # but each item could be a single string or a list
1584 (uncond_flags, src_flags, dest_flags) = flags
1585 flags = (makeList(uncond_flags),
1586 makeList(src_flags), makeList(dest_flags))
1587 # Accumulate attributes of new operand class in tmp_dict
1588 tmp_dict = {}
1589 for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
1590 'dflt_size', 'dflt_ctype', 'dflt_is_signed',
1591 'read_code', 'write_code'):
1592 tmp_dict[attr] = eval(attr)
1593 tmp_dict['base_name'] = op_name
1594 # New class name will be e.g. "IntReg_Ra"
1595 cls_name = base_cls_name + '_' + op_name
1596 # Evaluate string arg to get class object. Note that the
1597 # actual base class for "IntReg" is "IntRegOperand", i.e. we
1598 # have to append "Operand".
1599 try:
1600 base_cls = eval(base_cls_name + 'Operand')
1601 except NameError:
1602 error(lineno,
1603 'error: unknown operand base class "%s"' % base_cls_name)
1604 # The following statement creates a new class called
1605 # <cls_name> as a subclass of <base_cls> with the attributes
1606 # in tmp_dict, just as if we evaluated a class declaration.
1607 operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict)
1608
1609 # Define operand variables.
1610 operands = userDict.keys()
1611
1612 operandsREString = (r'''
1613 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
1614 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
1615 (?![\w\.]) # neg. lookahead assertion: prevent partial matches
1616 '''
1617 % string.join(operands, '|'))
1618
1619 global operandsRE
1620 operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
1621
1622 # Same as operandsREString, but extension is mandatory, and only two
1623 # groups are returned (base and ext, not full name as above).
1624 # Used for subtituting '_' for '.' to make C++ identifiers.
1625 operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
1626 % string.join(operands, '|'))
1627
1628 global operandsWithExtRE
1629 operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)
1630
1631maxInstSrcRegs = 0
1632maxInstDestRegs = 0
1633
1634class OperandList:
1635
1636 # Find all the operands in the given code block. Returns an operand
1637 # descriptor list (instance of class OperandList).
1638 def __init__(self, code):
1639 self.items = []
1640 self.bases = {}
1641 # delete comments so we don't match on reg specifiers inside
1642 code = commentRE.sub('', code)
1643 # search for operands
1644 next_pos = 0
1645 while 1:
1646 match = operandsRE.search(code, next_pos)
1647 if not match:
1648 # no more matches: we're done
1649 break
1650 op = match.groups()
1651 # regexp groups are operand full name, base, and extension
1652 (op_full, op_base, op_ext) = op
1653 # if the token following the operand is an assignment, this is
1654 # a destination (LHS), else it's a source (RHS)
1655 is_dest = (assignRE.match(code, match.end()) != None)
1656 is_src = not is_dest
1657 # see if we've already seen this one
1658 op_desc = self.find_base(op_base)
1659 if op_desc:
1660 if op_desc.ext != op_ext:
1661 error(0, 'Inconsistent extensions for operand %s' % \
1662 op_base)
1663 op_desc.is_src = op_desc.is_src or is_src
1664 op_desc.is_dest = op_desc.is_dest or is_dest
1665 else:
1666 # new operand: create new descriptor
1667 op_desc = operandNameMap[op_base](op_full, op_ext,
1668 is_src, is_dest)
1669 self.append(op_desc)
1670 # start next search after end of current match
1671 next_pos = match.end()
1672 self.sort()
1673 # enumerate source & dest register operands... used in building
1674 # constructor later
1675 self.numSrcRegs = 0
1676 self.numDestRegs = 0
1677 self.numFPDestRegs = 0
1678 self.numIntDestRegs = 0
1679 self.memOperand = None
1680 for op_desc in self.items:
1681 if op_desc.isReg():
1682 if op_desc.is_src:
1683 op_desc.src_reg_idx = self.numSrcRegs
1684 self.numSrcRegs += 1
1685 if op_desc.is_dest:
1686 op_desc.dest_reg_idx = self.numDestRegs
1687 self.numDestRegs += 1
1688 if op_desc.isFloatReg():
1689 self.numFPDestRegs += 1
1690 elif op_desc.isIntReg():
1691 self.numIntDestRegs += 1
1692 elif op_desc.isMem():
1693 if self.memOperand:
1694 error(0, "Code block has more than one memory operand.")
1695 self.memOperand = op_desc
1696 global maxInstSrcRegs
1697 global maxInstDestRegs
1698 if maxInstSrcRegs < self.numSrcRegs:
1699 maxInstSrcRegs = self.numSrcRegs
1700 if maxInstDestRegs < self.numDestRegs:
1701 maxInstDestRegs = self.numDestRegs
1702 # now make a final pass to finalize op_desc fields that may depend
1703 # on the register enumeration
1704 for op_desc in self.items:
1705 op_desc.finalize()
1706
1707 def __len__(self):
1708 return len(self.items)
1709
1710 def __getitem__(self, index):
1711 return self.items[index]
1712
1713 def append(self, op_desc):
1714 self.items.append(op_desc)
1715 self.bases[op_desc.base_name] = op_desc
1716
1717 def find_base(self, base_name):
1718 # like self.bases[base_name], but returns None if not found
1719 # (rather than raising exception)
1720 return self.bases.get(base_name)
1721
1722 # internal helper function for concat[Some]Attr{Strings|Lists}
1723 def __internalConcatAttrs(self, attr_name, filter, result):
1724 for op_desc in self.items:
1725 if filter(op_desc):
1726 result += getattr(op_desc, attr_name)
1727 return result
1728
1729 # return a single string that is the concatenation of the (string)
1730 # values of the specified attribute for all operands
1731 def concatAttrStrings(self, attr_name):
1732 return self.__internalConcatAttrs(attr_name, lambda x: 1, '')
1733
1734 # like concatAttrStrings, but only include the values for the operands
1735 # for which the provided filter function returns true
1736 def concatSomeAttrStrings(self, filter, attr_name):
1737 return self.__internalConcatAttrs(attr_name, filter, '')
1738
1739 # return a single list that is the concatenation of the (list)
1740 # values of the specified attribute for all operands
1741 def concatAttrLists(self, attr_name):
1742 return self.__internalConcatAttrs(attr_name, lambda x: 1, [])
1743
1744 # like concatAttrLists, but only include the values for the operands
1745 # for which the provided filter function returns true
1746 def concatSomeAttrLists(self, filter, attr_name):
1747 return self.__internalConcatAttrs(attr_name, filter, [])
1748
1749 def sort(self):
1750 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
1751
1752class SubOperandList(OperandList):
1753
1754 # Find all the operands in the given code block. Returns an operand
1755 # descriptor list (instance of class OperandList).
1756 def __init__(self, code, master_list):
1757 self.items = []
1758 self.bases = {}
1759 # delete comments so we don't match on reg specifiers inside
1760 code = commentRE.sub('', code)
1761 # search for operands
1762 next_pos = 0
1763 while 1:
1764 match = operandsRE.search(code, next_pos)
1765 if not match:
1766 # no more matches: we're done
1767 break
1768 op = match.groups()
1769 # regexp groups are operand full name, base, and extension
1770 (op_full, op_base, op_ext) = op
1771 # find this op in the master list
1772 op_desc = master_list.find_base(op_base)
1773 if not op_desc:
1774 error(0, 'Found operand %s which is not in the master list!' \
1775 ' This is an internal error' % \
1776 op_base)
1777 else:
1778 # See if we've already found this operand
1779 op_desc = self.find_base(op_base)
1780 if not op_desc:
1781 # if not, add a reference to it to this sub list
1782 self.append(master_list.bases[op_base])
1783
1784 # start next search after end of current match
1785 next_pos = match.end()
1786 self.sort()
1787 self.memOperand = None
1788 for op_desc in self.items:
1789 if op_desc.isMem():
1790 if self.memOperand:
1791 error(0, "Code block has more than one memory operand.")
1792 self.memOperand = op_desc
1793
1794# Regular expression object to match C++ comments
1795# (used in findOperands())
1796commentRE = re.compile(r'//.*\n')
1797
1798# Regular expression object to match assignment statements
1799# (used in findOperands())
1800assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
1801
1802# Munge operand names in code string to make legal C++ variable names.
1803# This means getting rid of the type extension if any.
1804# (Will match base_name attribute of Operand object.)
1805def substMungedOpNames(code):
1806 return operandsWithExtRE.sub(r'\1', code)
1807
1808# Fix up code snippets for final substitution in templates.
1809def mungeSnippet(s):
1810 if isinstance(s, str):
1811 return substMungedOpNames(substBitOps(s))
1812 else:
1813 return s
1814
1815def makeFlagConstructor(flag_list):
1816 if len(flag_list) == 0:
1817 return ''
1818 # filter out repeated flags
1819 flag_list.sort()
1820 i = 1
1821 while i < len(flag_list):
1822 if flag_list[i] == flag_list[i-1]:
1823 del flag_list[i]
1824 else:
1825 i += 1
1826 pre = '\n\tflags['
1827 post = '] = true;'
1828 code = pre + string.join(flag_list, post + pre) + post
1829 return code
1830
1831# Assume all instruction flags are of the form 'IsFoo'
1832instFlagRE = re.compile(r'Is.*')
1833
1834# OpClass constants end in 'Op' except No_OpClass
1835opClassRE = re.compile(r'.*Op|No_OpClass')
1836
1837class InstObjParams:
1838 def __init__(self, mnem, class_name, base_class = '',
1839 snippets = {}, opt_args = []):
1840 self.mnemonic = mnem
1841 self.class_name = class_name
1842 self.base_class = base_class
1843 if not isinstance(snippets, dict):
1844 snippets = {'code' : snippets}
1845 compositeCode = ' '.join(map(str, snippets.values()))
1846 self.snippets = snippets
1847
1848 self.operands = OperandList(compositeCode)
1849 self.constructor = self.operands.concatAttrStrings('constructor')
1850 self.constructor += \
1851 '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
1852 self.constructor += \
1853 '\n\t_numDestRegs = %d;' % self.operands.numDestRegs
1854 self.constructor += \
1855 '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs
1856 self.constructor += \
1857 '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
1858 self.flags = self.operands.concatAttrLists('flags')
1859
1860 # Make a basic guess on the operand class (function unit type).
1861 # These are good enough for most cases, and can be overridden
1862 # later otherwise.
1863 if 'IsStore' in self.flags:
1864 self.op_class = 'MemWriteOp'
1865 elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags:
1866 self.op_class = 'MemReadOp'
1867 elif 'IsFloating' in self.flags:
1868 self.op_class = 'FloatAddOp'
1869 else:
1870 self.op_class = 'IntAluOp'
1871
1872 # Optional arguments are assumed to be either StaticInst flags
1873 # or an OpClass value. To avoid having to import a complete
1874 # list of these values to match against, we do it ad-hoc
1875 # with regexps.
1876 for oa in opt_args:
1877 if instFlagRE.match(oa):
1878 self.flags.append(oa)
1879 elif opClassRE.match(oa):
1880 self.op_class = oa
1881 else:
1882 error(0, 'InstObjParams: optional arg "%s" not recognized '
1883 'as StaticInst::Flag or OpClass.' % oa)
1884
1885 # add flag initialization to contructor here to include
1886 # any flags added via opt_args
1887 self.constructor += makeFlagConstructor(self.flags)
1888
1889 # if 'IsFloating' is set, add call to the FP enable check
1890 # function (which should be provided by isa_desc via a declare)
1891 if 'IsFloating' in self.flags:
1892 self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
1893 else:
1894 self.fp_enable_check = ''
1895
1896#######################
1897#
1898# Output file template
1899#
1900
1901file_template = '''
1902/*
1903 * DO NOT EDIT THIS FILE!!!
1904 *
1905 * It was automatically generated from the ISA description in %(filename)s
1906 */
1907
1908%(includes)s
1909
1910%(global_output)s
1911
1912namespace %(namespace)s {
1913
1914%(namespace_output)s
1915
1916} // namespace %(namespace)s
1917
1918%(decode_function)s
1919'''
1920
1921max_inst_regs_template = '''
1922/*
1923 * DO NOT EDIT THIS FILE!!!
1924 *
1925 * It was automatically generated from the ISA description in %(filename)s
1926 */
1927
1928namespace %(namespace)s {
1929
1930 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
1931 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
1932
1933} // namespace %(namespace)s
1934
1935'''
1936
1937
1938# Update the output file only if the new contents are different from
1939# the current contents. Minimizes the files that need to be rebuilt
1940# after minor changes.
1941def update_if_needed(file, contents):
1942 update = False
1943 if os.access(file, os.R_OK):
1944 f = open(file, 'r')
1945 old_contents = f.read()
1946 f.close()
1947 if contents != old_contents:
1948 print 'Updating', file
1949 os.remove(file) # in case it's write-protected
1950 update = True
1951 else:
1952 print 'File', file, 'is unchanged'
1953 else:
1954 print 'Generating', file
1955 update = True
1956 if update:
1957 f = open(file, 'w')
1958 f.write(contents)
1959 f.close()
1960
1961# This regular expression matches '##include' directives
1962includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
1963 re.MULTILINE)
1964
1965# Function to replace a matched '##include' directive with the
1966# contents of the specified file (with nested ##includes replaced
1967# recursively). 'matchobj' is an re match object (from a match of
1968# includeRE) and 'dirname' is the directory relative to which the file
1969# path should be resolved.
1970def replace_include(matchobj, dirname):
1971 fname = matchobj.group('filename')
1972 full_fname = os.path.normpath(os.path.join(dirname, fname))
1973 contents = '##newfile "%s"\n%s\n##endfile\n' % \
1974 (full_fname, read_and_flatten(full_fname))
1975 return contents
1976
1977# Read a file and recursively flatten nested '##include' files.
1978def read_and_flatten(filename):
1979 current_dir = os.path.dirname(filename)
1980 try:
1981 contents = open(filename).read()
1982 except IOError:
1983 error(0, 'Error including file "%s"' % filename)
1984 fileNameStack.push((filename, 0))
1985 # Find any includes and include them
1986 contents = includeRE.sub(lambda m: replace_include(m, current_dir),
1987 contents)
1988 fileNameStack.pop()
1989 return contents
1990
1991#
1992# Read in and parse the ISA description.
1993#
1994def parse_isa_desc(isa_desc_file, output_dir):
1995 # Read file and (recursively) all included files into a string.
1996 # PLY requires that the input be in a single string so we have to
1997 # do this up front.
1998 isa_desc = read_and_flatten(isa_desc_file)
1999
2000 # Initialize filename stack with outer file.
2001 fileNameStack.push((isa_desc_file, 0))
2002
2003 # Parse it.
2004 (isa_name, namespace, global_code, namespace_code) = \
2005 parser.parse(isa_desc, lexer=lexer)
2006
2007 # grab the last three path components of isa_desc_file to put in
2008 # the output
2009 filename = '/'.join(isa_desc_file.split('/')[-3:])
2010
2011 # generate decoder.hh
2012 includes = '#include "base/bitfield.hh" // for bitfield support'
2013 global_output = global_code.header_output
2014 namespace_output = namespace_code.header_output
2015 decode_function = ''
2016 update_if_needed(output_dir + '/decoder.hh', file_template % vars())
2017
2018 # generate decoder.cc
2019 includes = '#include "decoder.hh"'
2020 global_output = global_code.decoder_output
2021 namespace_output = namespace_code.decoder_output
2022 # namespace_output += namespace_code.decode_block
2023 decode_function = namespace_code.decode_block
2024 update_if_needed(output_dir + '/decoder.cc', file_template % vars())
2025
2026 # generate per-cpu exec files
2027 for cpu in cpu_models:
2028 includes = '#include "decoder.hh"\n'
2029 includes += cpu.includes
2030 global_output = global_code.exec_output[cpu.name]
2031 namespace_output = namespace_code.exec_output[cpu.name]
2032 decode_function = ''
2033 update_if_needed(output_dir + '/' + cpu.filename,
2034 file_template % vars())
2035
2036 # The variable names here are hacky, but this will creat local variables
2037 # which will be referenced in vars() which have the value of the globals.
2038 global maxInstSrcRegs
2039 MaxInstSrcRegs = maxInstSrcRegs
2040 global maxInstDestRegs
2041 MaxInstDestRegs = maxInstDestRegs
2042 # max_inst_regs.hh
2043 update_if_needed(output_dir + '/max_inst_regs.hh', \
2044 max_inst_regs_template % vars())
2045
2046# global list of CpuModel objects (see cpu_models.py)
2047cpu_models = []
2048
2049# Called as script: get args from command line.
2050# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2051if __name__ == '__main__':
2052 execfile(sys.argv[1]) # read in CpuModel definitions
2053 cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
2054 parse_isa_desc(sys.argv[2], sys.argv[3])