a8f9852ea76cf6c3487cd88021e338887932a41b
1 # Copyright (c) 2003-2005 The Regents of The University of Michigan
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.
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.
27 # Authors: Steve Reinhardt
33 import inspect
, traceback
37 from m5
.util
.grammar
import Grammar
43 # Indent every line in string 's' by two spaces
44 # (except preprocessor directives).
45 # Used to make nested code blocks look pretty.
48 return re
.sub(r
'(?m)^(?!#)', ' ', s
)
51 # Munge a somewhat arbitrarily formatted piece of Python code
52 # (e.g. from a format 'let' block) into something whose indentation
53 # will get by the Python parser.
55 # The two keys here are that Python will give a syntax error if
56 # there's any whitespace at the beginning of the first line, and that
57 # all lines at the same lexical nesting level must have identical
58 # indentation. Unfortunately the way code literals work, an entire
59 # let block tends to have some initial indentation. Rather than
60 # trying to figure out what that is and strip it off, we prepend 'if
61 # 1:' to make the let code the nested block inside the if (and have
62 # the parser automatically deal with the indentation for us).
64 # We don't want to do this if (1) the code block is empty or (2) the
65 # first line of the block doesn't have any whitespace at the front.
67 def fixPythonIndentation(s
):
68 # get rid of blank lines first
69 s
= re
.sub(r
'(?m)^\s*\n', '', s
);
70 if (s
!= '' and re
.match(r
'[ \t]', s
[0])):
74 class ISAParserError(Exception):
75 """Error handler for parser errors"""
76 def __init__(self
, first
, second
=None):
81 if hasattr(first
, 'lexer'):
82 first
= first
.lexer
.lineno
86 def display(self
, filename_stack
, print_traceback
=False):
87 # Output formatted to work under Emacs compile-mode. Optional
88 # 'print_traceback' arg, if set to True, prints a Python stack
89 # backtrace too (can be handy when trying to debug the parser
93 for (filename
, line
) in filename_stack
[:-1]:
94 print "%sIn file included from %s:" % (spaces
, filename
)
97 # Print a Python stack backtrace if requested.
98 if print_traceback
or not self
.lineno
:
101 line_str
= "%s:" % (filename_stack
[-1][0], )
103 line_str
+= "%d:" % (self
.lineno
, )
105 return "%s%s %s" % (spaces
, line_str
, self
.string
)
107 def exit(self
, filename_stack
, print_traceback
=False):
110 sys
.exit(self
.display(filename_stack
, print_traceback
))
113 raise ISAParserError(*args
)
118 # Template objects are format strings that allow substitution from
119 # the attribute spaces of other objects (e.g. InstObjParams instances).
121 labelRE
= re
.compile(r
'(?<!%)%\(([^\)]+)\)[sd]')
123 class Template(object):
124 def __init__(self
, t
):
130 # Protect non-Python-dict substitutions (e.g. if there's a printf
131 # in the templated C++ code)
132 template
= protect_non_subst_percents(self
.template
)
133 # CPU-model-specific substitutions are handled later (in GenCode).
134 template
= protect_cpu_symbols(template
)
136 # Build a dict ('myDict') to use for the template substitution.
137 # Start with the template namespace. Make a copy since we're
138 # going to modify it.
139 myDict
= parser
.templateMap
.copy()
141 if isinstance(d
, InstObjParams
):
142 # If we're dealing with an InstObjParams object, we need
143 # to be a little more sophisticated. The instruction-wide
144 # parameters are already formed, but the parameters which
145 # are only function wide still need to be generated.
148 myDict
.update(d
.__dict
__)
149 # The "operands" and "snippets" attributes of the InstObjParams
150 # objects are for internal use and not substitution.
151 del myDict
['operands']
152 del myDict
['snippets']
154 snippetLabels
= [l
for l
in labelRE
.findall(template
)
155 if d
.snippets
.has_key(l
)]
157 snippets
= dict([(s
, mungeSnippet(d
.snippets
[s
]))
158 for s
in snippetLabels
])
160 myDict
.update(snippets
)
162 compositeCode
= ' '.join(map(str, snippets
.values()))
164 # Add in template itself in case it references any
165 # operands explicitly (like Mem)
166 compositeCode
+= ' ' + template
168 operands
= SubOperandList(compositeCode
, d
.operands
)
170 myDict
['op_decl'] = operands
.concatAttrStrings('op_decl')
172 is_src
= lambda op
: op
.is_src
173 is_dest
= lambda op
: op
.is_dest
175 myDict
['op_src_decl'] = \
176 operands
.concatSomeAttrStrings(is_src
, 'op_src_decl')
177 myDict
['op_dest_decl'] = \
178 operands
.concatSomeAttrStrings(is_dest
, 'op_dest_decl')
180 myDict
['op_rd'] = operands
.concatAttrStrings('op_rd')
181 myDict
['op_wb'] = operands
.concatAttrStrings('op_wb')
183 if d
.operands
.memOperand
:
184 myDict
['mem_acc_size'] = d
.operands
.memOperand
.mem_acc_size
185 myDict
['mem_acc_type'] = d
.operands
.memOperand
.mem_acc_type
187 elif isinstance(d
, dict):
188 # if the argument is a dictionary, we just use it.
190 elif hasattr(d
, '__dict__'):
191 # if the argument is an object, we use its attribute map.
192 myDict
.update(d
.__dict
__)
194 raise TypeError, "Template.subst() arg must be or have dictionary"
195 return template
% myDict
197 # Convert to string. This handles the case when a template with a
198 # CPU-specific term gets interpolated into another template or into
201 return expand_cpu_symbols_to_string(self
.template
)
206 # A format object encapsulates an instruction format. It must provide
207 # a defineInst() method that generates the code for an instruction
210 exportContextSymbols
= ('InstObjParams', 'makeList', 're', 'string')
214 def updateExportContext():
215 exportContext
.update(exportDict(*exportContextSymbols
))
216 exportContext
.update(parser
.templateMap
)
218 def exportDict(*symNames
):
219 return dict([(s
, eval(s
)) for s
in symNames
])
222 class Format(object):
223 def __init__(self
, id, params
, code
):
224 # constructor: just save away arguments
227 label
= 'def format ' + id
228 self
.user_code
= compile(fixPythonIndentation(code
), label
, 'exec')
229 param_list
= string
.join(params
, ", ")
230 f
= '''def defInst(_code, _context, %s):
231 my_locals = vars().copy()
232 exec _code in _context, my_locals
233 return my_locals\n''' % param_list
234 c
= compile(f
, label
+ ' wrapper', 'exec')
238 def defineInst(self
, name
, args
, lineno
):
240 updateExportContext()
241 context
.update(exportContext
)
243 Name
= name
[0].upper()
246 context
.update({ 'name': name
, 'Name': Name
})
248 vars = self
.func(self
.user_code
, context
, *args
[0], **args
[1])
249 except Exception, exc
:
250 error(lineno
, 'error defining "%s": %s.' % (name
, exc
))
251 for k
in vars.keys():
252 if k
not in ('header_output', 'decoder_output',
253 'exec_output', 'decode_block'):
255 return GenCode(**vars)
257 # Special null format to catch an implicit-format instruction
258 # definition outside of any format block.
259 class NoFormat(object):
261 self
.defaultInst
= ''
263 def defineInst(self
, name
, args
, lineno
):
265 'instruction definition "%s" with no active format!' % name
)
267 # This dictionary maps format name strings to Format objects.
270 # Define a new format
271 def defFormat(id, params
, code
, lineno
):
272 # make sure we haven't already defined this one
273 if formatMap
.get(id, None) != None:
274 error(lineno
, 'format %s redefined.' % id)
275 # create new object and store in global map
276 formatMap
[id] = Format(id, params
, code
)
278 #####################################################################
282 #####################################################################
284 # Expand template with CPU-specific references into a dictionary with
285 # an entry for each CPU model name. The entry key is the model name
286 # and the corresponding value is the template with the CPU-specific
287 # refs substituted for that model.
288 def expand_cpu_symbols_to_dict(template
):
289 # Protect '%'s that don't go with CPU-specific terms
290 t
= re
.sub(r
'%(?!\(CPU_)', '%%', template
)
292 for cpu
in cpu_models
:
293 result
[cpu
.name
] = t
% cpu
.strings
296 # *If* the template has CPU-specific references, return a single
297 # string containing a copy of the template for each CPU model with the
298 # corresponding values substituted in. If the template has no
299 # CPU-specific references, it is returned unmodified.
300 def expand_cpu_symbols_to_string(template
):
301 if template
.find('%(CPU_') != -1:
302 return reduce(lambda x
,y
: x
+y
,
303 expand_cpu_symbols_to_dict(template
).values())
307 # Protect CPU-specific references by doubling the corresponding '%'s
308 # (in preparation for substituting a different set of references into
310 def protect_cpu_symbols(template
):
311 return re
.sub(r
'%(?=\(CPU_)', '%%', template
)
313 # Protect any non-dict-substitution '%'s in a format string
314 # (i.e. those not followed by '(')
315 def protect_non_subst_percents(s
):
316 return re
.sub(r
'%(?!\()', '%%', s
)
321 # The GenCode class encapsulates generated code destined for various
322 # output files. The header_output and decoder_output attributes are
323 # strings containing code destined for decoder.hh and decoder.cc
324 # respectively. The decode_block attribute contains code to be
325 # incorporated in the decode function itself (that will also end up in
326 # decoder.cc). The exec_output attribute is a dictionary with a key
327 # for each CPU model name; the value associated with a particular key
328 # is the string of code for that CPU model's exec.cc file. The
329 # has_decode_default attribute is used in the decode block to allow
330 # explicit default clauses to override default default clauses.
332 class GenCode(object):
333 # Constructor. At this point we substitute out all CPU-specific
334 # symbols. For the exec output, these go into the per-model
335 # dictionary. For all other output types they get collapsed into
338 header_output
= '', decoder_output
= '', exec_output
= '',
339 decode_block
= '', has_decode_default
= False):
340 self
.header_output
= expand_cpu_symbols_to_string(header_output
)
341 self
.decoder_output
= expand_cpu_symbols_to_string(decoder_output
)
342 if isinstance(exec_output
, dict):
343 self
.exec_output
= exec_output
344 elif isinstance(exec_output
, str):
345 # If the exec_output arg is a single string, we replicate
346 # it for each of the CPU models, substituting and
347 # %(CPU_foo)s params appropriately.
348 self
.exec_output
= expand_cpu_symbols_to_dict(exec_output
)
349 self
.decode_block
= expand_cpu_symbols_to_string(decode_block
)
350 self
.has_decode_default
= has_decode_default
352 # Override '+' operator: generate a new GenCode object that
353 # concatenates all the individual strings in the operands.
354 def __add__(self
, other
):
356 for cpu
in cpu_models
:
358 exec_output
[n
] = self
.exec_output
[n
] + other
.exec_output
[n
]
359 return GenCode(self
.header_output
+ other
.header_output
,
360 self
.decoder_output
+ other
.decoder_output
,
362 self
.decode_block
+ other
.decode_block
,
363 self
.has_decode_default
or other
.has_decode_default
)
365 # Prepend a string (typically a comment) to all the strings.
366 def prepend_all(self
, pre
):
367 self
.header_output
= pre
+ self
.header_output
368 self
.decoder_output
= pre
+ self
.decoder_output
369 self
.decode_block
= pre
+ self
.decode_block
370 for cpu
in cpu_models
:
371 self
.exec_output
[cpu
.name
] = pre
+ self
.exec_output
[cpu
.name
]
373 # Wrap the decode block in a pair of strings (e.g., 'case foo:'
374 # and 'break;'). Used to build the big nested switch statement.
375 def wrap_decode_block(self
, pre
, post
= ''):
376 self
.decode_block
= pre
+ indent(self
.decode_block
) + post
378 #####################################################################
380 # Bitfield Operator Support
382 #####################################################################
384 bitOp1ArgRE
= re
.compile(r
'<\s*(\w+)\s*:\s*>')
386 bitOpWordRE
= re
.compile(r
'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
387 bitOpExprRE
= re
.compile(r
'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
389 def substBitOps(code
):
390 # first convert single-bit selectors to two-index form
391 # i.e., <n> --> <n:n>
392 code
= bitOp1ArgRE
.sub(r
'<\1:\1>', code
)
393 # simple case: selector applied to ID (name)
394 # i.e., foo<a:b> --> bits(foo, a, b)
395 code
= bitOpWordRE
.sub(r
'bits(\1, \2, \3)', code
)
396 # if selector is applied to expression (ending in ')'),
397 # we need to search backward for matching '('
398 match
= bitOpExprRE
.search(code
)
400 exprEnd
= match
.start()
404 if code
[here
] == '(':
406 elif code
[here
] == ')':
410 sys
.exit("Didn't find '('!")
412 newExpr
= r
'bits(%s, %s, %s)' % (code
[exprStart
:exprEnd
+1],
413 match
.group(1), match
.group(2))
414 code
= code
[:exprStart
] + newExpr
+ code
[match
.end():]
415 match
= bitOpExprRE
.search(code
)
419 #####################################################################
423 # The remaining code is the support for automatically extracting
424 # instruction characteristics from pseudocode.
426 #####################################################################
428 # Force the argument to be a list. Useful for flags, where a caller
429 # can specify a singleton flag or a list of flags. Also usful for
430 # converting tuples to lists so they can be modified.
432 if isinstance(arg
, list):
434 elif isinstance(arg
, tuple):
441 # Generate operandTypeMap from the user's 'def operand_types'
443 def buildOperandTypeMap(user_dict
, lineno
):
444 global operandTypeMap
446 for (ext
, (desc
, size
)) in user_dict
.iteritems():
447 if desc
== 'signed int':
448 ctype
= 'int%d_t' % size
450 elif desc
== 'unsigned int':
451 ctype
= 'uint%d_t' % size
453 elif desc
== 'float':
454 is_signed
= 1 # shouldn't really matter
459 elif desc
== 'twin64 int':
462 elif desc
== 'twin32 int':
466 error(lineno
, 'Unrecognized type description "%s" in user_dict')
467 operandTypeMap
[ext
] = (size
, ctype
, is_signed
)
469 class Operand(object):
470 '''Base class for operand descriptors. An instance of this class
471 (or actually a class derived from this one) represents a specific
472 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
473 derived classes encapsulates the traits of a particular operand
474 type (e.g., "32-bit integer register").'''
476 def buildReadCode(self
, func
= None):
477 code
= self
.read_code
% {"name": self
.base_name
,
479 "op_idx": self
.src_reg_idx
,
480 "reg_idx": self
.reg_spec
,
483 if self
.size
!= self
.dflt_size
:
484 return '%s = bits(%s, %d, 0);\n' % \
485 (self
.base_name
, code
, self
.size
-1)
487 return '%s = %s;\n' % \
488 (self
.base_name
, code
)
490 def buildWriteCode(self
, func
= None):
491 if (self
.size
!= self
.dflt_size
and self
.is_signed
):
492 final_val
= 'sext<%d>(%s)' % (self
.size
, self
.base_name
)
494 final_val
= self
.base_name
495 code
= self
.write_code
% {"name": self
.base_name
,
497 "op_idx": self
.dest_reg_idx
,
498 "reg_idx": self
.reg_spec
,
501 "final_val": final_val
}
506 if (traceData) { traceData->setData(final_val); }
507 }''' % (self
.dflt_ctype
, final_val
, code
)
509 def __init__(self
, full_name
, ext
, is_src
, is_dest
):
510 self
.full_name
= full_name
513 self
.is_dest
= is_dest
514 # The 'effective extension' (eff_ext) is either the actual
515 # extension, if one was explicitly provided, or the default.
519 self
.eff_ext
= self
.dflt_ext
521 (self
.size
, self
.ctype
, self
.is_signed
) = operandTypeMap
[self
.eff_ext
]
523 # note that mem_acc_size is undefined for non-mem operands...
524 # template must be careful not to use it if it doesn't apply.
526 self
.mem_acc_size
= self
.makeAccSize()
527 if self
.ctype
in ['Twin32_t', 'Twin64_t']:
528 self
.mem_acc_type
= 'Twin'
530 self
.mem_acc_type
= 'uint'
532 # Finalize additional fields (primarily code fields). This step
533 # is done separately since some of these fields may depend on the
534 # register index enumeration that hasn't been performed yet at the
535 # time of __init__().
537 self
.flags
= self
.getFlags()
538 self
.constructor
= self
.makeConstructor()
539 self
.op_decl
= self
.makeDecl()
542 self
.op_rd
= self
.makeRead()
543 self
.op_src_decl
= self
.makeDecl()
546 self
.op_src_decl
= ''
549 self
.op_wb
= self
.makeWrite()
550 self
.op_dest_decl
= self
.makeDecl()
553 self
.op_dest_decl
= ''
561 def isFloatReg(self
):
567 def isControlReg(self
):
571 # note the empty slice '[:]' gives us a copy of self.flags[0]
572 # instead of a reference to it
573 my_flags
= self
.flags
[0][:]
575 my_flags
+= self
.flags
[1]
577 my_flags
+= self
.flags
[2]
581 # Note that initializations in the declarations are solely
582 # to avoid 'uninitialized variable' errors from the compiler.
583 return self
.ctype
+ ' ' + self
.base_name
+ ' = 0;\n';
585 class IntRegOperand(Operand
):
592 def makeConstructor(self
):
595 c
+= '\n\t_srcRegIdx[%d] = %s;' % \
596 (self
.src_reg_idx
, self
.reg_spec
)
598 c
+= '\n\t_destRegIdx[%d] = %s;' % \
599 (self
.dest_reg_idx
, self
.reg_spec
)
603 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
604 error('Attempt to read integer register as FP')
605 if self
.read_code
!= None:
606 return self
.buildReadCode('readIntRegOperand')
607 if (self
.size
== self
.dflt_size
):
608 return '%s = xc->readIntRegOperand(this, %d);\n' % \
609 (self
.base_name
, self
.src_reg_idx
)
610 elif (self
.size
> self
.dflt_size
):
611 int_reg_val
= 'xc->readIntRegOperand(this, %d)' % \
614 int_reg_val
= 'sext<%d>(%s)' % (self
.dflt_size
, int_reg_val
)
615 return '%s = %s;\n' % (self
.base_name
, int_reg_val
)
617 return '%s = bits(xc->readIntRegOperand(this, %d), %d, 0);\n' % \
618 (self
.base_name
, self
.src_reg_idx
, self
.size
-1)
621 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
622 error('Attempt to write integer register as FP')
623 if self
.write_code
!= None:
624 return self
.buildWriteCode('setIntRegOperand')
625 if (self
.size
!= self
.dflt_size
and self
.is_signed
):
626 final_val
= 'sext<%d>(%s)' % (self
.size
, self
.base_name
)
628 final_val
= self
.base_name
632 xc->setIntRegOperand(this, %d, final_val);\n
633 if (traceData) { traceData->setData(final_val); }
634 }''' % (self
.dflt_ctype
, final_val
, self
.dest_reg_idx
)
637 class FloatRegOperand(Operand
):
641 def isFloatReg(self
):
644 def makeConstructor(self
):
647 c
+= '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
648 (self
.src_reg_idx
, self
.reg_spec
)
650 c
+= '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
651 (self
.dest_reg_idx
, self
.reg_spec
)
656 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
657 func
= 'readFloatRegOperand'
659 func
= 'readFloatRegOperandBits'
660 if (self
.size
!= self
.dflt_size
):
662 base
= 'xc->%s(this, %d)' % (func
, self
.src_reg_idx
)
663 if self
.read_code
!= None:
664 return self
.buildReadCode(func
)
666 return '%s = bits(%s, %d, 0);\n' % \
667 (self
.base_name
, base
, self
.size
-1)
669 return '%s = %s;\n' % (self
.base_name
, base
)
672 final_val
= self
.base_name
673 final_ctype
= self
.ctype
674 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
675 func
= 'setFloatRegOperand'
676 elif (self
.ctype
== 'uint32_t' or self
.ctype
== 'uint64_t'):
677 func
= 'setFloatRegOperandBits'
679 func
= 'setFloatRegOperandBits'
680 final_ctype
= 'uint%d_t' % self
.dflt_size
681 if (self
.size
!= self
.dflt_size
and self
.is_signed
):
682 final_val
= 'sext<%d>(%s)' % (self
.size
, self
.base_name
)
683 if self
.write_code
!= None:
684 return self
.buildWriteCode(func
)
688 xc->%s(this, %d, final_val);\n
689 if (traceData) { traceData->setData(final_val); }
690 }''' % (final_ctype
, final_val
, func
, self
.dest_reg_idx
)
693 class ControlRegOperand(Operand
):
697 def isControlReg(self
):
700 def makeConstructor(self
):
703 c
+= '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
704 (self
.src_reg_idx
, self
.reg_spec
)
706 c
+= '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
707 (self
.dest_reg_idx
, self
.reg_spec
)
712 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
713 error('Attempt to read control register as FP')
714 if self
.read_code
!= None:
715 return self
.buildReadCode('readMiscRegOperand')
716 base
= 'xc->readMiscRegOperand(this, %s)' % self
.src_reg_idx
717 if self
.size
== self
.dflt_size
:
718 return '%s = %s;\n' % (self
.base_name
, base
)
720 return '%s = bits(%s, %d, 0);\n' % \
721 (self
.base_name
, base
, self
.size
-1)
724 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
725 error('Attempt to write control register as FP')
726 if self
.write_code
!= None:
727 return self
.buildWriteCode('setMiscRegOperand')
728 wb
= 'xc->setMiscRegOperand(this, %s, %s);\n' % \
729 (self
.dest_reg_idx
, self
.base_name
)
730 wb
+= 'if (traceData) { traceData->setData(%s); }' % \
734 class MemOperand(Operand
):
738 def makeConstructor(self
):
742 # Note that initializations in the declarations are solely
743 # to avoid 'uninitialized variable' errors from the compiler.
744 # Declare memory data variable.
745 if self
.ctype
in ['Twin32_t','Twin64_t']:
746 return "%s %s; %s.a = 0; %s.b = 0;\n" % \
747 (self
.ctype
, self
.base_name
, self
.base_name
, self
.base_name
)
748 return '%s %s = 0;\n' % (self
.ctype
, self
.base_name
)
751 if self
.read_code
!= None:
752 return self
.buildReadCode()
756 if self
.write_code
!= None:
757 return self
.buildWriteCode()
760 # Return the memory access size *in bits*, suitable for
761 # forming a type via "uint%d_t". Divide by 8 if you want bytes.
762 def makeAccSize(self
):
765 class PCOperand(Operand
):
766 def makeConstructor(self
):
770 return '%s = xc->readPC();\n' % self
.base_name
773 return 'xc->setPC(%s);\n' % self
.base_name
775 class UPCOperand(Operand
):
776 def makeConstructor(self
):
780 if self
.read_code
!= None:
781 return self
.buildReadCode('readMicroPC')
782 return '%s = xc->readMicroPC();\n' % self
.base_name
785 if self
.write_code
!= None:
786 return self
.buildWriteCode('setMicroPC')
787 return 'xc->setMicroPC(%s);\n' % self
.base_name
789 class NUPCOperand(Operand
):
790 def makeConstructor(self
):
794 if self
.read_code
!= None:
795 return self
.buildReadCode('readNextMicroPC')
796 return '%s = xc->readNextMicroPC();\n' % self
.base_name
799 if self
.write_code
!= None:
800 return self
.buildWriteCode('setNextMicroPC')
801 return 'xc->setNextMicroPC(%s);\n' % self
.base_name
803 class NPCOperand(Operand
):
804 def makeConstructor(self
):
808 if self
.read_code
!= None:
809 return self
.buildReadCode('readNextPC')
810 return '%s = xc->readNextPC();\n' % self
.base_name
813 if self
.write_code
!= None:
814 return self
.buildWriteCode('setNextPC')
815 return 'xc->setNextPC(%s);\n' % self
.base_name
817 class NNPCOperand(Operand
):
818 def makeConstructor(self
):
822 if self
.read_code
!= None:
823 return self
.buildReadCode('readNextNPC')
824 return '%s = xc->readNextNPC();\n' % self
.base_name
827 if self
.write_code
!= None:
828 return self
.buildWriteCode('setNextNPC')
829 return 'xc->setNextNPC(%s);\n' % self
.base_name
831 def buildOperandNameMap(user_dict
, lineno
):
832 global operandNameMap
834 for (op_name
, val
) in user_dict
.iteritems():
835 (base_cls_name
, dflt_ext
, reg_spec
, flags
, sort_pri
) = val
[:5]
846 'error: too many attributes for operand "%s"' %
849 (dflt_size
, dflt_ctype
, dflt_is_signed
) = operandTypeMap
[dflt_ext
]
850 # Canonical flag structure is a triple of lists, where each list
851 # indicates the set of flags implied by this operand always, when
852 # used as a source, and when used as a dest, respectively.
853 # For simplicity this can be initialized using a variety of fairly
854 # obvious shortcuts; we convert these to canonical form here.
856 # no flags specified (e.g., 'None')
857 flags
= ( [], [], [] )
858 elif isinstance(flags
, str):
859 # a single flag: assumed to be unconditional
860 flags
= ( [ flags
], [], [] )
861 elif isinstance(flags
, list):
862 # a list of flags: also assumed to be unconditional
863 flags
= ( flags
, [], [] )
864 elif isinstance(flags
, tuple):
865 # it's a tuple: it should be a triple,
866 # but each item could be a single string or a list
867 (uncond_flags
, src_flags
, dest_flags
) = flags
868 flags
= (makeList(uncond_flags
),
869 makeList(src_flags
), makeList(dest_flags
))
870 # Accumulate attributes of new operand class in tmp_dict
872 for attr
in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
873 'dflt_size', 'dflt_ctype', 'dflt_is_signed',
874 'read_code', 'write_code'):
875 tmp_dict
[attr
] = eval(attr
)
876 tmp_dict
['base_name'] = op_name
877 # New class name will be e.g. "IntReg_Ra"
878 cls_name
= base_cls_name
+ '_' + op_name
879 # Evaluate string arg to get class object. Note that the
880 # actual base class for "IntReg" is "IntRegOperand", i.e. we
881 # have to append "Operand".
883 base_cls
= eval(base_cls_name
+ 'Operand')
886 'error: unknown operand base class "%s"' % base_cls_name
)
887 # The following statement creates a new class called
888 # <cls_name> as a subclass of <base_cls> with the attributes
889 # in tmp_dict, just as if we evaluated a class declaration.
890 operandNameMap
[op_name
] = type(cls_name
, (base_cls
,), tmp_dict
)
892 # Define operand variables.
893 operands
= user_dict
.keys()
895 operandsREString
= (r
'''
896 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
897 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
898 (?![\w\.]) # neg. lookahead assertion: prevent partial matches
900 % string
.join(operands
, '|'))
903 operandsRE
= re
.compile(operandsREString
, re
.MULTILINE|re
.VERBOSE
)
905 # Same as operandsREString, but extension is mandatory, and only two
906 # groups are returned (base and ext, not full name as above).
907 # Used for subtituting '_' for '.' to make C++ identifiers.
908 operandsWithExtREString
= (r
'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
909 % string
.join(operands
, '|'))
911 global operandsWithExtRE
912 operandsWithExtRE
= re
.compile(operandsWithExtREString
, re
.MULTILINE
)
917 class OperandList(object):
918 '''Find all the operands in the given code block. Returns an operand
919 descriptor list (instance of class OperandList).'''
920 def __init__(self
, code
):
923 # delete comments so we don't match on reg specifiers inside
924 code
= commentRE
.sub('', code
)
925 # search for operands
928 match
= operandsRE
.search(code
, next_pos
)
930 # no more matches: we're done
933 # regexp groups are operand full name, base, and extension
934 (op_full
, op_base
, op_ext
) = op
935 # if the token following the operand is an assignment, this is
936 # a destination (LHS), else it's a source (RHS)
937 is_dest
= (assignRE
.match(code
, match
.end()) != None)
939 # see if we've already seen this one
940 op_desc
= self
.find_base(op_base
)
942 if op_desc
.ext
!= op_ext
:
943 error('Inconsistent extensions for operand %s' % \
945 op_desc
.is_src
= op_desc
.is_src
or is_src
946 op_desc
.is_dest
= op_desc
.is_dest
or is_dest
948 # new operand: create new descriptor
949 op_desc
= operandNameMap
[op_base
](op_full
, op_ext
,
952 # start next search after end of current match
953 next_pos
= match
.end()
955 # enumerate source & dest register operands... used in building
959 self
.numFPDestRegs
= 0
960 self
.numIntDestRegs
= 0
961 self
.memOperand
= None
962 for op_desc
in self
.items
:
965 op_desc
.src_reg_idx
= self
.numSrcRegs
968 op_desc
.dest_reg_idx
= self
.numDestRegs
969 self
.numDestRegs
+= 1
970 if op_desc
.isFloatReg():
971 self
.numFPDestRegs
+= 1
972 elif op_desc
.isIntReg():
973 self
.numIntDestRegs
+= 1
974 elif op_desc
.isMem():
976 error("Code block has more than one memory operand.")
977 self
.memOperand
= op_desc
978 global maxInstSrcRegs
979 global maxInstDestRegs
980 if maxInstSrcRegs
< self
.numSrcRegs
:
981 maxInstSrcRegs
= self
.numSrcRegs
982 if maxInstDestRegs
< self
.numDestRegs
:
983 maxInstDestRegs
= self
.numDestRegs
984 # now make a final pass to finalize op_desc fields that may depend
985 # on the register enumeration
986 for op_desc
in self
.items
:
990 return len(self
.items
)
992 def __getitem__(self
, index
):
993 return self
.items
[index
]
995 def append(self
, op_desc
):
996 self
.items
.append(op_desc
)
997 self
.bases
[op_desc
.base_name
] = op_desc
999 def find_base(self
, base_name
):
1000 # like self.bases[base_name], but returns None if not found
1001 # (rather than raising exception)
1002 return self
.bases
.get(base_name
)
1004 # internal helper function for concat[Some]Attr{Strings|Lists}
1005 def __internalConcatAttrs(self
, attr_name
, filter, result
):
1006 for op_desc
in self
.items
:
1008 result
+= getattr(op_desc
, attr_name
)
1011 # return a single string that is the concatenation of the (string)
1012 # values of the specified attribute for all operands
1013 def concatAttrStrings(self
, attr_name
):
1014 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, '')
1016 # like concatAttrStrings, but only include the values for the operands
1017 # for which the provided filter function returns true
1018 def concatSomeAttrStrings(self
, filter, attr_name
):
1019 return self
.__internalConcatAttrs
(attr_name
, filter, '')
1021 # return a single list that is the concatenation of the (list)
1022 # values of the specified attribute for all operands
1023 def concatAttrLists(self
, attr_name
):
1024 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, [])
1026 # like concatAttrLists, but only include the values for the operands
1027 # for which the provided filter function returns true
1028 def concatSomeAttrLists(self
, filter, attr_name
):
1029 return self
.__internalConcatAttrs
(attr_name
, filter, [])
1032 self
.items
.sort(lambda a
, b
: a
.sort_pri
- b
.sort_pri
)
1034 class SubOperandList(OperandList
):
1035 '''Find all the operands in the given code block. Returns an operand
1036 descriptor list (instance of class OperandList).'''
1037 def __init__(self
, code
, master_list
):
1040 # delete comments so we don't match on reg specifiers inside
1041 code
= commentRE
.sub('', code
)
1042 # search for operands
1045 match
= operandsRE
.search(code
, next_pos
)
1047 # no more matches: we're done
1050 # regexp groups are operand full name, base, and extension
1051 (op_full
, op_base
, op_ext
) = op
1052 # find this op in the master list
1053 op_desc
= master_list
.find_base(op_base
)
1055 error('Found operand %s which is not in the master list!' \
1056 ' This is an internal error' % op_base
)
1058 # See if we've already found this operand
1059 op_desc
= self
.find_base(op_base
)
1061 # if not, add a reference to it to this sub list
1062 self
.append(master_list
.bases
[op_base
])
1064 # start next search after end of current match
1065 next_pos
= match
.end()
1067 self
.memOperand
= None
1068 for op_desc
in self
.items
:
1071 error("Code block has more than one memory operand.")
1072 self
.memOperand
= op_desc
1074 # Regular expression object to match C++ comments
1075 # (used in findOperands())
1076 commentRE
= re
.compile(r
'//.*\n')
1078 # Regular expression object to match assignment statements
1079 # (used in findOperands())
1080 assignRE
= re
.compile(r
'\s*=(?!=)', re
.MULTILINE
)
1082 # Munge operand names in code string to make legal C++ variable names.
1083 # This means getting rid of the type extension if any.
1084 # (Will match base_name attribute of Operand object.)
1085 def substMungedOpNames(code
):
1086 return operandsWithExtRE
.sub(r
'\1', code
)
1088 # Fix up code snippets for final substitution in templates.
1089 def mungeSnippet(s
):
1090 if isinstance(s
, str):
1091 return substMungedOpNames(substBitOps(s
))
1095 def makeFlagConstructor(flag_list
):
1096 if len(flag_list
) == 0:
1098 # filter out repeated flags
1101 while i
< len(flag_list
):
1102 if flag_list
[i
] == flag_list
[i
-1]:
1108 code
= pre
+ string
.join(flag_list
, post
+ pre
) + post
1111 # Assume all instruction flags are of the form 'IsFoo'
1112 instFlagRE
= re
.compile(r
'Is.*')
1114 # OpClass constants end in 'Op' except No_OpClass
1115 opClassRE
= re
.compile(r
'.*Op|No_OpClass')
1117 class InstObjParams(object):
1118 def __init__(self
, mnem
, class_name
, base_class
= '',
1119 snippets
= {}, opt_args
= []):
1120 self
.mnemonic
= mnem
1121 self
.class_name
= class_name
1122 self
.base_class
= base_class
1123 if not isinstance(snippets
, dict):
1124 snippets
= {'code' : snippets
}
1125 compositeCode
= ' '.join(map(str, snippets
.values()))
1126 self
.snippets
= snippets
1128 self
.operands
= OperandList(compositeCode
)
1129 self
.constructor
= self
.operands
.concatAttrStrings('constructor')
1130 self
.constructor
+= \
1131 '\n\t_numSrcRegs = %d;' % self
.operands
.numSrcRegs
1132 self
.constructor
+= \
1133 '\n\t_numDestRegs = %d;' % self
.operands
.numDestRegs
1134 self
.constructor
+= \
1135 '\n\t_numFPDestRegs = %d;' % self
.operands
.numFPDestRegs
1136 self
.constructor
+= \
1137 '\n\t_numIntDestRegs = %d;' % self
.operands
.numIntDestRegs
1138 self
.flags
= self
.operands
.concatAttrLists('flags')
1140 # Make a basic guess on the operand class (function unit type).
1141 # These are good enough for most cases, and can be overridden
1143 if 'IsStore' in self
.flags
:
1144 self
.op_class
= 'MemWriteOp'
1145 elif 'IsLoad' in self
.flags
or 'IsPrefetch' in self
.flags
:
1146 self
.op_class
= 'MemReadOp'
1147 elif 'IsFloating' in self
.flags
:
1148 self
.op_class
= 'FloatAddOp'
1150 self
.op_class
= 'IntAluOp'
1152 # Optional arguments are assumed to be either StaticInst flags
1153 # or an OpClass value. To avoid having to import a complete
1154 # list of these values to match against, we do it ad-hoc
1157 if instFlagRE
.match(oa
):
1158 self
.flags
.append(oa
)
1159 elif opClassRE
.match(oa
):
1162 error('InstObjParams: optional arg "%s" not recognized '
1163 'as StaticInst::Flag or OpClass.' % oa
)
1165 # add flag initialization to contructor here to include
1166 # any flags added via opt_args
1167 self
.constructor
+= makeFlagConstructor(self
.flags
)
1169 # if 'IsFloating' is set, add call to the FP enable check
1170 # function (which should be provided by isa_desc via a declare)
1171 if 'IsFloating' in self
.flags
:
1172 self
.fp_enable_check
= 'fault = checkFpEnableFault(xc);'
1174 self
.fp_enable_check
= ''
1177 # Stack: a simple stack object. Used for both formats (formatStack)
1178 # and default cases (defaultStack). Simply wraps a list to give more
1179 # stack-like syntax and enable initialization with an argument list
1180 # (as opposed to an argument that's a list).
1183 def __init__(self
, *items
):
1184 list.__init
__(self
, items
)
1186 def push(self
, item
):
1192 # The global format stack.
1193 formatStack
= Stack(NoFormat())
1195 # The global default case stack.
1196 defaultStack
= Stack(None)
1198 # Global stack that tracks current file and line number.
1199 # Each element is a tuple (filename, lineno) that records the
1200 # *current* filename and the line number in the *previous* file where
1202 fileNameStack
= Stack()
1205 #######################
1207 # Output file template
1212 * DO NOT EDIT THIS FILE!!!
1214 * It was automatically generated from the ISA description in %(filename)s
1221 namespace %(namespace)s {
1223 %(namespace_output)s
1225 } // namespace %(namespace)s
1230 max_inst_regs_template
= '''
1232 * DO NOT EDIT THIS FILE!!!
1234 * It was automatically generated from the ISA description in %(filename)s
1237 namespace %(namespace)s {
1239 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
1240 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
1242 } // namespace %(namespace)s
1246 class ISAParser(Grammar
):
1247 def __init__(self
, output_dir
):
1248 super(ISAParser
, self
).__init
__()
1249 self
.output_dir
= output_dir
1251 self
.templateMap
= {}
1253 #####################################################################
1257 # The PLY lexer module takes two things as input:
1258 # - A list of token names (the string list 'tokens')
1259 # - A regular expression describing a match for each token. The
1260 # regexp for token FOO can be provided in two ways:
1261 # - as a string variable named t_FOO
1262 # - as the doc string for a function named t_FOO. In this case,
1263 # the function is also executed, allowing an action to be
1264 # associated with each token match.
1266 #####################################################################
1268 # Reserved words. These are listed separately as they are matched
1269 # using the same regexp as generic IDs, but distinguished in the
1270 # t_ID() function. The PLY documentation suggests this approach.
1272 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
1273 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
1274 'OUTPUT', 'SIGNED', 'TEMPLATE'
1277 # List of tokens. The lex module requires this.
1278 tokens
= reserved
+ (
1291 # ( ) [ ] { } < > , ; . : :: *
1293 'LBRACKET', 'RBRACKET',
1295 'LESS', 'GREATER', 'EQUALS',
1296 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON',
1299 # C preprocessor directives
1302 # The following are matched but never returned. commented out to
1303 # suppress PLY warning
1311 # Regular expressions for token matching
1328 # Identifiers and reserved words
1331 reserved_map
[r
.lower()] = r
1335 t
.type = self
.reserved_map
.get(t
.value
, 'ID')
1339 def t_INTLIT(self
, t
):
1340 r
'-?(0x[\da-fA-F]+)|\d+'
1342 t
.value
= int(t
.value
,0)
1344 error(t
, 'Integer value "%s" too large' % t
.value
)
1348 # String literal. Note that these use only single quotes, and
1349 # can span multiple lines.
1350 def t_STRLIT(self
, t
):
1353 t
.value
= t
.value
[1:-1]
1354 t
.lexer
.lineno
+= t
.value
.count('\n')
1358 # "Code literal"... like a string literal, but delimiters are
1359 # '{{' and '}}' so they get formatted nicely under emacs c-mode
1360 def t_CODELIT(self
, t
):
1361 r
"(?m)\{\{([^\}]|}(?!\}))+\}\}"
1363 t
.value
= t
.value
[2:-2]
1364 t
.lexer
.lineno
+= t
.value
.count('\n')
1367 def t_CPPDIRECTIVE(self
, t
):
1369 t
.lexer
.lineno
+= t
.value
.count('\n')
1372 def t_NEWFILE(self
, t
):
1373 r
'^\#\#newfile\s+"[\w/.-]*"'
1374 fileNameStack
.push((t
.value
[11:-1], t
.lexer
.lineno
))
1377 def t_ENDFILE(self
, t
):
1379 (old_filename
, t
.lexer
.lineno
) = fileNameStack
.pop()
1382 # The functions t_NEWLINE, t_ignore, and t_error are
1383 # special for the lex module.
1387 def t_NEWLINE(self
, t
):
1389 t
.lexer
.lineno
+= t
.value
.count('\n')
1392 def t_comment(self
, t
):
1395 # Completely ignored characters
1396 t_ignore
= ' \t\x0c'
1399 def t_error(self
, t
):
1400 error(t
, "illegal character '%s'" % t
.value
[0])
1403 #####################################################################
1407 # Every function whose name starts with 'p_' defines a grammar
1408 # rule. The rule is encoded in the function's doc string, while
1409 # the function body provides the action taken when the rule is
1410 # matched. The argument to each function is a list of the values
1411 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the
1412 # symbols on the RHS. For tokens, the value is copied from the
1413 # t.value attribute provided by the lexer. For non-terminals, the
1414 # value is assigned by the producing rule; i.e., the job of the
1415 # grammar rule function is to set the value for the non-terminal
1416 # on the LHS (by assigning to t[0]).
1417 #####################################################################
1419 # The LHS of the first grammar rule is used as the start symbol
1420 # (in this case, 'specification'). Note that this rule enforces
1421 # that there will be exactly one namespace declaration, with 0 or
1422 # more global defs/decls before and after it. The defs & decls
1423 # before the namespace decl will be outside the namespace; those
1424 # after will be inside. The decoder function is always inside the
1426 def p_specification(self
, t
):
1427 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
1430 namespace
= isa_name
+ "Inst"
1431 # wrap the decode block as a function definition
1432 t
[4].wrap_decode_block('''
1434 %(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst)
1436 using namespace %(namespace)s;
1438 # both the latter output blocks and the decode block are in
1440 namespace_code
= t
[3] + t
[4]
1441 # pass it all back to the caller of yacc.parse()
1442 t
[0] = (isa_name
, namespace
, global_code
, namespace_code
)
1444 # ISA name declaration looks like "namespace <foo>;"
1445 def p_name_decl(self
, t
):
1446 'name_decl : NAMESPACE ID SEMI'
1449 # 'opt_defs_and_outputs' is a possibly empty sequence of
1450 # def and/or output statements.
1451 def p_opt_defs_and_outputs_0(self
, t
):
1452 'opt_defs_and_outputs : empty'
1455 def p_opt_defs_and_outputs_1(self
, t
):
1456 'opt_defs_and_outputs : defs_and_outputs'
1459 def p_defs_and_outputs_0(self
, t
):
1460 'defs_and_outputs : def_or_output'
1463 def p_defs_and_outputs_1(self
, t
):
1464 'defs_and_outputs : defs_and_outputs def_or_output'
1467 # The list of possible definition/output statements.
1468 def p_def_or_output(self
, t
):
1469 '''def_or_output : def_format
1471 | def_bitfield_struct
1481 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1482 # directly to the appropriate output section.
1484 # Massage output block by substituting in template definitions and
1485 # bit operators. We handle '%'s embedded in the string that don't
1486 # indicate template substitutions (or CPU-specific symbols, which
1487 # get handled in GenCode) by doubling them first so that the
1488 # format operation will reduce them back to single '%'s.
1489 def process_output(self
, s
):
1490 s
= protect_non_subst_percents(s
)
1491 # protects cpu-specific symbols too
1492 s
= protect_cpu_symbols(s
)
1493 return substBitOps(s
% self
.templateMap
)
1495 def p_output_header(self
, t
):
1496 'output_header : OUTPUT HEADER CODELIT SEMI'
1497 t
[0] = GenCode(header_output
= self
.process_output(t
[3]))
1499 def p_output_decoder(self
, t
):
1500 'output_decoder : OUTPUT DECODER CODELIT SEMI'
1501 t
[0] = GenCode(decoder_output
= self
.process_output(t
[3]))
1503 def p_output_exec(self
, t
):
1504 'output_exec : OUTPUT EXEC CODELIT SEMI'
1505 t
[0] = GenCode(exec_output
= self
.process_output(t
[3]))
1507 # global let blocks 'let {{...}}' (Python code blocks) are
1508 # executed directly when seen. Note that these execute in a
1509 # special variable context 'exportContext' to prevent the code
1510 # from polluting this script's namespace.
1511 def p_global_let(self
, t
):
1512 'global_let : LET CODELIT SEMI'
1513 updateExportContext()
1514 exportContext
["header_output"] = ''
1515 exportContext
["decoder_output"] = ''
1516 exportContext
["exec_output"] = ''
1517 exportContext
["decode_block"] = ''
1519 exec fixPythonIndentation(t
[2]) in exportContext
1520 except Exception, exc
:
1521 error(t
, 'error: %s in global let block "%s".' % (exc
, t
[2]))
1522 t
[0] = GenCode(header_output
= exportContext
["header_output"],
1523 decoder_output
= exportContext
["decoder_output"],
1524 exec_output
= exportContext
["exec_output"],
1525 decode_block
= exportContext
["decode_block"])
1527 # Define the mapping from operand type extensions to C++ types and
1528 # bit widths (stored in operandTypeMap).
1529 def p_def_operand_types(self
, t
):
1530 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1532 user_dict
= eval('{' + t
[3] + '}')
1533 except Exception, exc
:
1535 'error: %s in def operand_types block "%s".' % (exc
, t
[3]))
1536 buildOperandTypeMap(user_dict
, t
.lexer
.lineno
)
1537 t
[0] = GenCode() # contributes nothing to the output C++ file
1539 # Define the mapping from operand names to operand classes and
1540 # other traits. Stored in operandNameMap.
1541 def p_def_operands(self
, t
):
1542 'def_operands : DEF OPERANDS CODELIT SEMI'
1543 if not globals().has_key('operandTypeMap'):
1544 error(t
, 'error: operand types must be defined before operands')
1546 user_dict
= eval('{' + t
[3] + '}', exportContext
)
1547 except Exception, exc
:
1548 error(t
, 'error: %s in def operands block "%s".' % (exc
, t
[3]))
1549 buildOperandNameMap(user_dict
, t
.lexer
.lineno
)
1550 t
[0] = GenCode() # contributes nothing to the output C++ file
1552 # A bitfield definition looks like:
1553 # 'def [signed] bitfield <ID> [<first>:<last>]'
1554 # This generates a preprocessor macro in the output file.
1555 def p_def_bitfield_0(self
, t
):
1556 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
1557 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[8])
1558 if (t
[2] == 'signed'):
1559 expr
= 'sext<%d>(%s)' % (t
[6] - t
[8] + 1, expr
)
1560 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1561 t
[0] = GenCode(header_output
= hash_define
)
1563 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
1564 def p_def_bitfield_1(self
, t
):
1565 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
1566 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[6])
1567 if (t
[2] == 'signed'):
1568 expr
= 'sext<%d>(%s)' % (1, expr
)
1569 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1570 t
[0] = GenCode(header_output
= hash_define
)
1572 # alternate form for structure member: 'def bitfield <ID> <ID>'
1573 def p_def_bitfield_struct(self
, t
):
1574 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI'
1576 error(t
, 'error: structure bitfields are always unsigned.')
1577 expr
= 'machInst.%s' % t
[5]
1578 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1579 t
[0] = GenCode(header_output
= hash_define
)
1581 def p_id_with_dot_0(self
, t
):
1585 def p_id_with_dot_1(self
, t
):
1586 'id_with_dot : ID DOT id_with_dot'
1587 t
[0] = t
[1] + t
[2] + t
[3]
1589 def p_opt_signed_0(self
, t
):
1590 'opt_signed : SIGNED'
1593 def p_opt_signed_1(self
, t
):
1594 'opt_signed : empty'
1597 def p_def_template(self
, t
):
1598 'def_template : DEF TEMPLATE ID CODELIT SEMI'
1599 self
.templateMap
[t
[3]] = Template(t
[4])
1602 # An instruction format definition looks like
1603 # "def format <fmt>(<params>) {{...}};"
1604 def p_def_format(self
, t
):
1605 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1606 (id, params
, code
) = (t
[3], t
[5], t
[7])
1607 defFormat(id, params
, code
, t
.lexer
.lineno
)
1610 # The formal parameter list for an instruction format is a
1611 # possibly empty list of comma-separated parameters. Positional
1612 # (standard, non-keyword) parameters must come first, followed by
1613 # keyword parameters, followed by a '*foo' parameter that gets
1614 # excess positional arguments (as in Python). Each of these three
1615 # parameter categories is optional.
1617 # Note that we do not support the '**foo' parameter for collecting
1618 # otherwise undefined keyword args. Otherwise the parameter list
1619 # is (I believe) identical to what is supported in Python.
1621 # The param list generates a tuple, where the first element is a
1622 # list of the positional params and the second element is a dict
1623 # containing the keyword params.
1624 def p_param_list_0(self
, t
):
1625 'param_list : positional_param_list COMMA nonpositional_param_list'
1628 def p_param_list_1(self
, t
):
1629 '''param_list : positional_param_list
1630 | nonpositional_param_list'''
1633 def p_positional_param_list_0(self
, t
):
1634 'positional_param_list : empty'
1637 def p_positional_param_list_1(self
, t
):
1638 'positional_param_list : ID'
1641 def p_positional_param_list_2(self
, t
):
1642 'positional_param_list : positional_param_list COMMA ID'
1643 t
[0] = t
[1] + [t
[3]]
1645 def p_nonpositional_param_list_0(self
, t
):
1646 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
1649 def p_nonpositional_param_list_1(self
, t
):
1650 '''nonpositional_param_list : keyword_param_list
1651 | excess_args_param'''
1654 def p_keyword_param_list_0(self
, t
):
1655 'keyword_param_list : keyword_param'
1658 def p_keyword_param_list_1(self
, t
):
1659 'keyword_param_list : keyword_param_list COMMA keyword_param'
1660 t
[0] = t
[1] + [t
[3]]
1662 def p_keyword_param(self
, t
):
1663 'keyword_param : ID EQUALS expr'
1664 t
[0] = t
[1] + ' = ' + t
[3].__repr
__()
1666 def p_excess_args_param(self
, t
):
1667 'excess_args_param : ASTERISK ID'
1668 # Just concatenate them: '*ID'. Wrap in list to be consistent
1669 # with positional_param_list and keyword_param_list.
1670 t
[0] = [t
[1] + t
[2]]
1672 # End of format definition-related rules.
1676 # A decode block looks like:
1677 # decode <field1> [, <field2>]* [default <inst>] { ... }
1679 def p_decode_block(self
, t
):
1680 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
1681 default_defaults
= defaultStack
.pop()
1683 # use the "default defaults" only if there was no explicit
1684 # default statement in decode_stmt_list
1685 if not codeObj
.has_decode_default
:
1686 codeObj
+= default_defaults
1687 codeObj
.wrap_decode_block('switch (%s) {\n' % t
[2], '}\n')
1690 # The opt_default statement serves only to push the "default
1691 # defaults" onto defaultStack. This value will be used by nested
1692 # decode blocks, and used and popped off when the current
1693 # decode_block is processed (in p_decode_block() above).
1694 def p_opt_default_0(self
, t
):
1695 'opt_default : empty'
1696 # no default specified: reuse the one currently at the top of
1698 defaultStack
.push(defaultStack
.top())
1699 # no meaningful value returned
1702 def p_opt_default_1(self
, t
):
1703 'opt_default : DEFAULT inst'
1704 # push the new default
1706 codeObj
.wrap_decode_block('\ndefault:\n', 'break;\n')
1707 defaultStack
.push(codeObj
)
1708 # no meaningful value returned
1711 def p_decode_stmt_list_0(self
, t
):
1712 'decode_stmt_list : decode_stmt'
1715 def p_decode_stmt_list_1(self
, t
):
1716 'decode_stmt_list : decode_stmt decode_stmt_list'
1717 if (t
[1].has_decode_default
and t
[2].has_decode_default
):
1718 error(t
, 'Two default cases in decode block')
1722 # Decode statement rules
1724 # There are four types of statements allowed in a decode block:
1725 # 1. Format blocks 'format <foo> { ... }'
1726 # 2. Nested decode blocks
1727 # 3. Instruction definitions.
1728 # 4. C preprocessor directives.
1731 # Preprocessor directives found in a decode statement list are
1732 # passed through to the output, replicated to all of the output
1733 # code streams. This works well for ifdefs, so we can ifdef out
1734 # both the declarations and the decode cases generated by an
1735 # instruction definition. Handling them as part of the grammar
1736 # makes it easy to keep them in the right place with respect to
1737 # the code generated by the other statements.
1738 def p_decode_stmt_cpp(self
, t
):
1739 'decode_stmt : CPPDIRECTIVE'
1740 t
[0] = GenCode(t
[1], t
[1], t
[1], t
[1])
1742 # A format block 'format <foo> { ... }' sets the default
1743 # instruction format used to handle instruction definitions inside
1744 # the block. This format can be overridden by using an explicit
1745 # format on the instruction definition or with a nested format
1747 def p_decode_stmt_format(self
, t
):
1748 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
1749 # The format will be pushed on the stack when 'push_format_id'
1750 # is processed (see below). Once the parser has recognized
1751 # the full production (though the right brace), we're done
1752 # with the format, so now we can pop it.
1756 # This rule exists so we can set the current format (& push the
1757 # stack) when we recognize the format name part of the format
1759 def p_push_format_id(self
, t
):
1760 'push_format_id : ID'
1762 formatStack
.push(formatMap
[t
[1]])
1763 t
[0] = ('', '// format %s' % t
[1])
1765 error(t
, 'instruction format "%s" not defined.' % t
[1])
1767 # Nested decode block: if the value of the current field matches
1768 # the specified constant, do a nested decode on some other field.
1769 def p_decode_stmt_decode(self
, t
):
1770 'decode_stmt : case_label COLON decode_block'
1773 # just wrap the decoding code from the block as a case in the
1774 # outer switch statement.
1775 codeObj
.wrap_decode_block('\n%s:\n' % label
)
1776 codeObj
.has_decode_default
= (label
== 'default')
1779 # Instruction definition (finally!).
1780 def p_decode_stmt_inst(self
, t
):
1781 'decode_stmt : case_label COLON inst SEMI'
1784 codeObj
.wrap_decode_block('\n%s:' % label
, 'break;\n')
1785 codeObj
.has_decode_default
= (label
== 'default')
1788 # The case label is either a list of one or more constants or
1790 def p_case_label_0(self
, t
):
1791 'case_label : intlit_list'
1792 def make_case(intlit
):
1794 return 'case ULL(%#x)' % intlit
1796 return 'case %#x' % intlit
1797 t
[0] = ': '.join(map(make_case
, t
[1]))
1799 def p_case_label_1(self
, t
):
1800 'case_label : DEFAULT'
1804 # The constant list for a decode case label must be non-empty, but
1805 # may have one or more comma-separated integer literals in it.
1807 def p_intlit_list_0(self
, t
):
1808 'intlit_list : INTLIT'
1811 def p_intlit_list_1(self
, t
):
1812 'intlit_list : intlit_list COMMA INTLIT'
1816 # Define an instruction using the current instruction format
1817 # (specified by an enclosing format block).
1818 # "<mnemonic>(<args>)"
1819 def p_inst_0(self
, t
):
1820 'inst : ID LPAREN arg_list RPAREN'
1821 # Pass the ID and arg list to the current format class to deal with.
1822 currentFormat
= formatStack
.top()
1823 codeObj
= currentFormat
.defineInst(t
[1], t
[3], t
.lexer
.lineno
)
1824 args
= ','.join(map(str, t
[3]))
1825 args
= re
.sub('(?m)^', '//', args
)
1826 args
= re
.sub('^//', '', args
)
1827 comment
= '\n// %s::%s(%s)\n' % (currentFormat
.id, t
[1], args
)
1828 codeObj
.prepend_all(comment
)
1831 # Define an instruction using an explicitly specified format:
1832 # "<fmt>::<mnemonic>(<args>)"
1833 def p_inst_1(self
, t
):
1834 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1836 format
= formatMap
[t
[1]]
1838 error(t
, 'instruction format "%s" not defined.' % t
[1])
1839 codeObj
= format
.defineInst(t
[3], t
[5], t
.lexer
.lineno
)
1840 comment
= '\n// %s::%s(%s)\n' % (t
[1], t
[3], t
[5])
1841 codeObj
.prepend_all(comment
)
1844 # The arg list generates a tuple, where the first element is a
1845 # list of the positional args and the second element is a dict
1846 # containing the keyword args.
1847 def p_arg_list_0(self
, t
):
1848 'arg_list : positional_arg_list COMMA keyword_arg_list'
1849 t
[0] = ( t
[1], t
[3] )
1851 def p_arg_list_1(self
, t
):
1852 'arg_list : positional_arg_list'
1855 def p_arg_list_2(self
, t
):
1856 'arg_list : keyword_arg_list'
1859 def p_positional_arg_list_0(self
, t
):
1860 'positional_arg_list : empty'
1863 def p_positional_arg_list_1(self
, t
):
1864 'positional_arg_list : expr'
1867 def p_positional_arg_list_2(self
, t
):
1868 'positional_arg_list : positional_arg_list COMMA expr'
1869 t
[0] = t
[1] + [t
[3]]
1871 def p_keyword_arg_list_0(self
, t
):
1872 'keyword_arg_list : keyword_arg'
1875 def p_keyword_arg_list_1(self
, t
):
1876 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
1880 def p_keyword_arg(self
, t
):
1881 'keyword_arg : ID EQUALS expr'
1882 t
[0] = { t
[1] : t
[3] }
1885 # Basic expressions. These constitute the argument values of
1886 # "function calls" (i.e. instruction definitions in the decode
1887 # block) and default values for formal parameters of format
1890 # Right now, these are either strings, integers, or (recursively)
1891 # lists of exprs (using Python square-bracket list syntax). Note
1892 # that bare identifiers are trated as string constants here (since
1893 # there isn't really a variable namespace to refer to).
1895 def p_expr_0(self
, t
):
1902 def p_expr_1(self
, t
):
1903 '''expr : LBRACKET list_expr RBRACKET'''
1906 def p_list_expr_0(self
, t
):
1910 def p_list_expr_1(self
, t
):
1911 'list_expr : list_expr COMMA expr'
1912 t
[0] = t
[1] + [t
[3]]
1914 def p_list_expr_2(self
, t
):
1919 # Empty production... use in other rules for readability.
1921 def p_empty(self
, t
):
1925 # Parse error handler. Note that the argument here is the
1926 # offending *token*, not a grammar symbol (hence the need to use
1928 def p_error(self
, t
):
1930 error(t
, "syntax error at '%s'" % t
.value
)
1932 error("unknown syntax error")
1934 # END OF GRAMMAR RULES
1936 def update_if_needed(self
, file, contents
):
1937 '''Update the output file only if the new contents are
1938 different from the current contents. Minimizes the files that
1939 need to be rebuilt after minor changes.'''
1941 file = os
.path
.join(self
.output_dir
, file)
1943 if os
.access(file, os
.R_OK
):
1945 old_contents
= f
.read()
1947 if contents
!= old_contents
:
1948 print 'Updating', file
1949 os
.remove(file) # in case it's write-protected
1952 print 'File', file, 'is unchanged'
1954 print 'Generating', file
1961 # This regular expression matches '##include' directives
1962 includeRE
= re
.compile(r
'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
1965 def replace_include(self
, matchobj
, dirname
):
1966 """Function to replace a matched '##include' directive with the
1967 contents of the specified file (with nested ##includes
1968 replaced recursively). 'matchobj' is an re match object
1969 (from a match of includeRE) and 'dirname' is the directory
1970 relative to which the file path should be resolved."""
1972 fname
= matchobj
.group('filename')
1973 full_fname
= os
.path
.normpath(os
.path
.join(dirname
, fname
))
1974 contents
= '##newfile "%s"\n%s\n##endfile\n' % \
1975 (full_fname
, self
.read_and_flatten(full_fname
))
1978 def read_and_flatten(self
, filename
):
1979 """Read a file and recursively flatten nested '##include' files."""
1981 current_dir
= os
.path
.dirname(filename
)
1983 contents
= open(filename
).read()
1985 error('Error including file "%s"' % filename
)
1987 fileNameStack
.push((filename
, 0))
1989 # Find any includes and include them
1990 def replace(matchobj
):
1991 return self
.replace_include(matchobj
, current_dir
)
1992 contents
= self
.includeRE
.sub(replace
, contents
)
1997 def _parse_isa_desc(self
, isa_desc_file
):
1998 '''Read in and parse the ISA description.'''
2000 # Read file and (recursively) all included files into a string.
2001 # PLY requires that the input be in a single string so we have to
2003 isa_desc
= self
.read_and_flatten(isa_desc_file
)
2005 # Initialize filename stack with outer file.
2006 fileNameStack
.push((isa_desc_file
, 0))
2009 (isa_name
, namespace
, global_code
, namespace_code
) = \
2010 self
.parse(isa_desc
)
2012 # grab the last three path components of isa_desc_file to put in
2014 filename
= '/'.join(isa_desc_file
.split('/')[-3:])
2016 # generate decoder.hh
2017 includes
= '#include "base/bitfield.hh" // for bitfield support'
2018 global_output
= global_code
.header_output
2019 namespace_output
= namespace_code
.header_output
2020 decode_function
= ''
2021 self
.update_if_needed('decoder.hh', file_template
% vars())
2023 # generate decoder.cc
2024 includes
= '#include "decoder.hh"'
2025 global_output
= global_code
.decoder_output
2026 namespace_output
= namespace_code
.decoder_output
2027 # namespace_output += namespace_code.decode_block
2028 decode_function
= namespace_code
.decode_block
2029 self
.update_if_needed('decoder.cc', file_template
% vars())
2031 # generate per-cpu exec files
2032 for cpu
in cpu_models
:
2033 includes
= '#include "decoder.hh"\n'
2034 includes
+= cpu
.includes
2035 global_output
= global_code
.exec_output
[cpu
.name
]
2036 namespace_output
= namespace_code
.exec_output
[cpu
.name
]
2037 decode_function
= ''
2038 self
.update_if_needed(cpu
.filename
, file_template
% vars())
2040 # The variable names here are hacky, but this will creat local
2041 # variables which will be referenced in vars() which have the
2042 # value of the globals.
2043 global maxInstSrcRegs
2044 MaxInstSrcRegs
= maxInstSrcRegs
2045 global maxInstDestRegs
2046 MaxInstDestRegs
= maxInstDestRegs
2048 self
.update_if_needed('max_inst_regs.hh',
2049 max_inst_regs_template
% vars())
2051 def parse_isa_desc(self
, *args
, **kwargs
):
2053 self
._parse
_isa
_desc
(*args
, **kwargs
)
2054 except ISAParserError
, e
:
2055 e
.exit(fileNameStack
)
2057 # global list of CpuModel objects (see cpu_models.py)
2060 # Called as script: get args from command line.
2061 # Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2062 if __name__
== '__main__':
2063 execfile(sys
.argv
[1]) # read in CpuModel definitions
2064 cpu_models
= [CpuModel
.dict[cpu
] for cpu
in sys
.argv
[4:]]
2065 parser
= ISAParser(sys
.argv
[3])
2066 parser
.parse_isa_desc(sys
.argv
[2])