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