1 # Copyright (c) 2003-2005 The Regents of The University of Michigan
2 # Copyright (c) 2013 Advanced Micro Devices, Inc.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met: redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer;
9 # redistributions in binary form must reproduce the above copyright
10 # notice, this list of conditions and the following disclaimer in the
11 # documentation and/or other materials provided with the distribution;
12 # neither the name of the copyright holders nor the names of its
13 # contributors may be used to endorse or promote products derived from
14 # this software without specific prior written permission.
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 # Authors: Steve Reinhardt
34 import inspect
, traceback
38 from m5
.util
.grammar
import Grammar
46 # Indent every line in string 's' by two spaces
47 # (except preprocessor directives).
48 # Used to make nested code blocks look pretty.
51 return re
.sub(r
'(?m)^(?!#)', ' ', s
)
54 # Munge a somewhat arbitrarily formatted piece of Python code
55 # (e.g. from a format 'let' block) into something whose indentation
56 # will get by the Python parser.
58 # The two keys here are that Python will give a syntax error if
59 # there's any whitespace at the beginning of the first line, and that
60 # all lines at the same lexical nesting level must have identical
61 # indentation. Unfortunately the way code literals work, an entire
62 # let block tends to have some initial indentation. Rather than
63 # trying to figure out what that is and strip it off, we prepend 'if
64 # 1:' to make the let code the nested block inside the if (and have
65 # the parser automatically deal with the indentation for us).
67 # We don't want to do this if (1) the code block is empty or (2) the
68 # first line of the block doesn't have any whitespace at the front.
70 def fixPythonIndentation(s
):
71 # get rid of blank lines first
72 s
= re
.sub(r
'(?m)^\s*\n', '', s
);
73 if (s
!= '' and re
.match(r
'[ \t]', s
[0])):
77 class ISAParserError(Exception):
78 """Error handler for parser errors"""
79 def __init__(self
, first
, second
=None):
84 if hasattr(first
, 'lexer'):
85 first
= first
.lexer
.lineno
89 def display(self
, filename_stack
, print_traceback
=debug
):
90 # Output formatted to work under Emacs compile-mode. Optional
91 # 'print_traceback' arg, if set to True, prints a Python stack
92 # backtrace too (can be handy when trying to debug the parser
96 for (filename
, line
) in filename_stack
[:-1]:
97 print "%sIn file included from %s:" % (spaces
, filename
)
100 # Print a Python stack backtrace if requested.
101 if print_traceback
or not self
.lineno
:
102 traceback
.print_exc()
104 line_str
= "%s:" % (filename_stack
[-1][0], )
106 line_str
+= "%d:" % (self
.lineno
, )
108 return "%s%s %s" % (spaces
, line_str
, self
.string
)
110 def exit(self
, filename_stack
, print_traceback
=debug
):
113 sys
.exit(self
.display(filename_stack
, print_traceback
))
116 raise ISAParserError(*args
)
121 # Template objects are format strings that allow substitution from
122 # the attribute spaces of other objects (e.g. InstObjParams instances).
124 labelRE
= re
.compile(r
'(?<!%)%\(([^\)]+)\)[sd]')
126 class Template(object):
127 def __init__(self
, parser
, t
):
134 # Protect non-Python-dict substitutions (e.g. if there's a printf
135 # in the templated C++ code)
136 template
= self
.parser
.protectNonSubstPercents(self
.template
)
137 # CPU-model-specific substitutions are handled later (in GenCode).
138 template
= self
.parser
.protectCpuSymbols(template
)
140 # Build a dict ('myDict') to use for the template substitution.
141 # Start with the template namespace. Make a copy since we're
142 # going to modify it.
143 myDict
= self
.parser
.templateMap
.copy()
145 if isinstance(d
, InstObjParams
):
146 # If we're dealing with an InstObjParams object, we need
147 # to be a little more sophisticated. The instruction-wide
148 # parameters are already formed, but the parameters which
149 # are only function wide still need to be generated.
152 myDict
.update(d
.__dict
__)
153 # The "operands" and "snippets" attributes of the InstObjParams
154 # objects are for internal use and not substitution.
155 del myDict
['operands']
156 del myDict
['snippets']
158 snippetLabels
= [l
for l
in labelRE
.findall(template
)
159 if d
.snippets
.has_key(l
)]
161 snippets
= dict([(s
, self
.parser
.mungeSnippet(d
.snippets
[s
]))
162 for s
in snippetLabels
])
164 myDict
.update(snippets
)
166 compositeCode
= ' '.join(map(str, snippets
.values()))
168 # Add in template itself in case it references any
169 # operands explicitly (like Mem)
170 compositeCode
+= ' ' + template
172 operands
= SubOperandList(self
.parser
, compositeCode
, d
.operands
)
174 myDict
['op_decl'] = operands
.concatAttrStrings('op_decl')
175 if operands
.readPC
or operands
.setPC
:
176 myDict
['op_decl'] += 'TheISA::PCState __parserAutoPCState;\n'
178 # In case there are predicated register reads and write, declare
179 # the variables for register indicies. It is being assumed that
180 # all the operands in the OperandList are also in the
181 # SubOperandList and in the same order. Otherwise, it is
182 # expected that predication would not be used for the operands.
183 if operands
.predRead
:
184 myDict
['op_decl'] += 'uint8_t _sourceIndex = 0;\n'
185 if operands
.predWrite
:
186 myDict
['op_decl'] += 'uint8_t M5_VAR_USED _destIndex = 0;\n'
188 is_src
= lambda op
: op
.is_src
189 is_dest
= lambda op
: op
.is_dest
191 myDict
['op_src_decl'] = \
192 operands
.concatSomeAttrStrings(is_src
, 'op_src_decl')
193 myDict
['op_dest_decl'] = \
194 operands
.concatSomeAttrStrings(is_dest
, 'op_dest_decl')
196 myDict
['op_src_decl'] += \
197 'TheISA::PCState __parserAutoPCState;\n'
199 myDict
['op_dest_decl'] += \
200 'TheISA::PCState __parserAutoPCState;\n'
202 myDict
['op_rd'] = operands
.concatAttrStrings('op_rd')
204 myDict
['op_rd'] = '__parserAutoPCState = xc->pcState();\n' + \
207 # Compose the op_wb string. If we're going to write back the
208 # PC state because we changed some of its elements, we'll need to
209 # do that as early as possible. That allows later uncoordinated
210 # modifications to the PC to layer appropriately.
211 reordered
= list(operands
.items
)
214 pcWbStr
= 'xc->pcState(__parserAutoPCState);\n'
215 for op_desc
in reordered
:
216 if op_desc
.isPCPart() and op_desc
.is_dest
:
217 op_wb_str
= op_desc
.op_wb
+ pcWbStr
+ op_wb_str
220 op_wb_str
= op_desc
.op_wb
+ op_wb_str
221 myDict
['op_wb'] = op_wb_str
223 elif isinstance(d
, dict):
224 # if the argument is a dictionary, we just use it.
226 elif hasattr(d
, '__dict__'):
227 # if the argument is an object, we use its attribute map.
228 myDict
.update(d
.__dict
__)
230 raise TypeError, "Template.subst() arg must be or have dictionary"
231 return template
% myDict
233 # Convert to string. This handles the case when a template with a
234 # CPU-specific term gets interpolated into another template or into
237 return self
.parser
.expandCpuSymbolsToString(self
.template
)
242 # A format object encapsulates an instruction format. It must provide
243 # a defineInst() method that generates the code for an instruction
246 class Format(object):
247 def __init__(self
, id, params
, code
):
250 label
= 'def format ' + id
251 self
.user_code
= compile(fixPythonIndentation(code
), label
, 'exec')
252 param_list
= string
.join(params
, ", ")
253 f
= '''def defInst(_code, _context, %s):
254 my_locals = vars().copy()
255 exec _code in _context, my_locals
256 return my_locals\n''' % param_list
257 c
= compile(f
, label
+ ' wrapper', 'exec')
261 def defineInst(self
, parser
, name
, args
, lineno
):
262 parser
.updateExportContext()
263 context
= parser
.exportContext
.copy()
265 Name
= name
[0].upper()
268 context
.update({ 'name' : name
, 'Name' : Name
})
270 vars = self
.func(self
.user_code
, context
, *args
[0], **args
[1])
271 except Exception, exc
:
274 error(lineno
, 'error defining "%s": %s.' % (name
, exc
))
275 for k
in vars.keys():
276 if k
not in ('header_output', 'decoder_output',
277 'exec_output', 'decode_block'):
279 return GenCode(parser
, **vars)
281 # Special null format to catch an implicit-format instruction
282 # definition outside of any format block.
283 class NoFormat(object):
285 self
.defaultInst
= ''
287 def defineInst(self
, parser
, name
, args
, lineno
):
289 'instruction definition "%s" with no active format!' % name
)
294 # The GenCode class encapsulates generated code destined for various
295 # output files. The header_output and decoder_output attributes are
296 # strings containing code destined for decoder.hh and decoder.cc
297 # respectively. The decode_block attribute contains code to be
298 # incorporated in the decode function itself (that will also end up in
299 # decoder.cc). The exec_output attribute is a dictionary with a key
300 # for each CPU model name; the value associated with a particular key
301 # is the string of code for that CPU model's exec.cc file. The
302 # has_decode_default attribute is used in the decode block to allow
303 # explicit default clauses to override default default clauses.
305 class GenCode(object):
306 # Constructor. At this point we substitute out all CPU-specific
307 # symbols. For the exec output, these go into the per-model
308 # dictionary. For all other output types they get collapsed into
310 def __init__(self
, parser
,
311 header_output
= '', decoder_output
= '', exec_output
= '',
312 decode_block
= '', has_decode_default
= False):
314 self
.header_output
= parser
.expandCpuSymbolsToString(header_output
)
315 self
.decoder_output
= parser
.expandCpuSymbolsToString(decoder_output
)
316 if isinstance(exec_output
, dict):
317 self
.exec_output
= exec_output
318 elif isinstance(exec_output
, str):
319 # If the exec_output arg is a single string, we replicate
320 # it for each of the CPU models, substituting and
321 # %(CPU_foo)s params appropriately.
322 self
.exec_output
= parser
.expandCpuSymbolsToDict(exec_output
)
323 self
.decode_block
= parser
.expandCpuSymbolsToString(decode_block
)
324 self
.has_decode_default
= has_decode_default
326 # Override '+' operator: generate a new GenCode object that
327 # concatenates all the individual strings in the operands.
328 def __add__(self
, other
):
330 for cpu
in self
.parser
.cpuModels
:
332 exec_output
[n
] = self
.exec_output
[n
] + other
.exec_output
[n
]
333 return GenCode(self
.parser
,
334 self
.header_output
+ other
.header_output
,
335 self
.decoder_output
+ other
.decoder_output
,
337 self
.decode_block
+ other
.decode_block
,
338 self
.has_decode_default
or other
.has_decode_default
)
340 # Prepend a string (typically a comment) to all the strings.
341 def prepend_all(self
, pre
):
342 self
.header_output
= pre
+ self
.header_output
343 self
.decoder_output
= pre
+ self
.decoder_output
344 self
.decode_block
= pre
+ self
.decode_block
345 for cpu
in self
.parser
.cpuModels
:
346 self
.exec_output
[cpu
.name
] = pre
+ self
.exec_output
[cpu
.name
]
348 # Wrap the decode block in a pair of strings (e.g., 'case foo:'
349 # and 'break;'). Used to build the big nested switch statement.
350 def wrap_decode_block(self
, pre
, post
= ''):
351 self
.decode_block
= pre
+ indent(self
.decode_block
) + post
353 #####################################################################
355 # Bitfield Operator Support
357 #####################################################################
359 bitOp1ArgRE
= re
.compile(r
'<\s*(\w+)\s*:\s*>')
361 bitOpWordRE
= re
.compile(r
'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
362 bitOpExprRE
= re
.compile(r
'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
364 def substBitOps(code
):
365 # first convert single-bit selectors to two-index form
366 # i.e., <n> --> <n:n>
367 code
= bitOp1ArgRE
.sub(r
'<\1:\1>', code
)
368 # simple case: selector applied to ID (name)
369 # i.e., foo<a:b> --> bits(foo, a, b)
370 code
= bitOpWordRE
.sub(r
'bits(\1, \2, \3)', code
)
371 # if selector is applied to expression (ending in ')'),
372 # we need to search backward for matching '('
373 match
= bitOpExprRE
.search(code
)
375 exprEnd
= match
.start()
379 if code
[here
] == '(':
381 elif code
[here
] == ')':
385 sys
.exit("Didn't find '('!")
387 newExpr
= r
'bits(%s, %s, %s)' % (code
[exprStart
:exprEnd
+1],
388 match
.group(1), match
.group(2))
389 code
= code
[:exprStart
] + newExpr
+ code
[match
.end():]
390 match
= bitOpExprRE
.search(code
)
394 #####################################################################
398 # The remaining code is the support for automatically extracting
399 # instruction characteristics from pseudocode.
401 #####################################################################
403 # Force the argument to be a list. Useful for flags, where a caller
404 # can specify a singleton flag or a list of flags. Also usful for
405 # converting tuples to lists so they can be modified.
407 if isinstance(arg
, list):
409 elif isinstance(arg
, tuple):
416 class Operand(object):
417 '''Base class for operand descriptors. An instance of this class
418 (or actually a class derived from this one) represents a specific
419 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
420 derived classes encapsulates the traits of a particular operand
421 type (e.g., "32-bit integer register").'''
423 def buildReadCode(self
, func
= None):
424 subst_dict
= {"name": self
.base_name
,
426 "reg_idx": self
.reg_spec
,
428 if hasattr(self
, 'src_reg_idx'):
429 subst_dict
['op_idx'] = self
.src_reg_idx
430 code
= self
.read_code
% subst_dict
431 return '%s = %s;\n' % (self
.base_name
, code
)
433 def buildWriteCode(self
, func
= None):
434 subst_dict
= {"name": self
.base_name
,
436 "reg_idx": self
.reg_spec
,
438 "final_val": self
.base_name
}
439 if hasattr(self
, 'dest_reg_idx'):
440 subst_dict
['op_idx'] = self
.dest_reg_idx
441 code
= self
.write_code
% subst_dict
446 if (traceData) { traceData->setData(final_val); }
447 }''' % (self
.dflt_ctype
, self
.base_name
, code
)
449 def __init__(self
, parser
, full_name
, ext
, is_src
, is_dest
):
450 self
.full_name
= full_name
453 self
.is_dest
= is_dest
454 # The 'effective extension' (eff_ext) is either the actual
455 # extension, if one was explicitly provided, or the default.
458 elif hasattr(self
, 'dflt_ext'):
459 self
.eff_ext
= self
.dflt_ext
461 if hasattr(self
, 'eff_ext'):
462 self
.ctype
= parser
.operandTypeMap
[self
.eff_ext
]
464 # Finalize additional fields (primarily code fields). This step
465 # is done separately since some of these fields may depend on the
466 # register index enumeration that hasn't been performed yet at the
467 # time of __init__(). The register index enumeration is affected
468 # by predicated register reads/writes. Hence, we forward the flags
469 # that indicate whether or not predication is in use.
470 def finalize(self
, predRead
, predWrite
):
471 self
.flags
= self
.getFlags()
472 self
.constructor
= self
.makeConstructor(predRead
, predWrite
)
473 self
.op_decl
= self
.makeDecl()
476 self
.op_rd
= self
.makeRead(predRead
)
477 self
.op_src_decl
= self
.makeDecl()
480 self
.op_src_decl
= ''
483 self
.op_wb
= self
.makeWrite(predWrite
)
484 self
.op_dest_decl
= self
.makeDecl()
487 self
.op_dest_decl
= ''
495 def isFloatReg(self
):
504 def isControlReg(self
):
511 return self
.isPCState() and self
.reg_spec
513 def hasReadPred(self
):
514 return self
.read_predicate
!= None
516 def hasWritePred(self
):
517 return self
.write_predicate
!= None
520 # note the empty slice '[:]' gives us a copy of self.flags[0]
521 # instead of a reference to it
522 my_flags
= self
.flags
[0][:]
524 my_flags
+= self
.flags
[1]
526 my_flags
+= self
.flags
[2]
530 # Note that initializations in the declarations are solely
531 # to avoid 'uninitialized variable' errors from the compiler.
532 return self
.ctype
+ ' ' + self
.base_name
+ ' = 0;\n';
534 class IntRegOperand(Operand
):
541 def makeConstructor(self
, predRead
, predWrite
):
546 c_src
= '\n\t_srcRegIdx[_numSrcRegs++] = %s;' % (self
.reg_spec
)
547 if self
.hasReadPred():
548 c_src
= '\n\tif (%s) {%s\n\t}' % \
549 (self
.read_predicate
, c_src
)
552 c_dest
= '\n\t_destRegIdx[_numDestRegs++] = %s;' % \
554 c_dest
+= '\n\t_numIntDestRegs++;'
555 if self
.hasWritePred():
556 c_dest
= '\n\tif (%s) {%s\n\t}' % \
557 (self
.write_predicate
, c_dest
)
559 return c_src
+ c_dest
561 def makeRead(self
, predRead
):
562 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
563 error('Attempt to read integer register as FP')
564 if self
.read_code
!= None:
565 return self
.buildReadCode('readIntRegOperand')
569 int_reg_val
= 'xc->readIntRegOperand(this, _sourceIndex++)'
570 if self
.hasReadPred():
571 int_reg_val
= '(%s) ? %s : 0' % \
572 (self
.read_predicate
, int_reg_val
)
574 int_reg_val
= 'xc->readIntRegOperand(this, %d)' % self
.src_reg_idx
576 return '%s = %s;\n' % (self
.base_name
, int_reg_val
)
578 def makeWrite(self
, predWrite
):
579 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
580 error('Attempt to write integer register as FP')
581 if self
.write_code
!= None:
582 return self
.buildWriteCode('setIntRegOperand')
586 if self
.hasWritePred():
587 wp
= self
.write_predicate
589 wcond
= 'if (%s)' % (wp
)
590 windex
= '_destIndex++'
593 windex
= '%d' % self
.dest_reg_idx
599 xc->setIntRegOperand(this, %s, final_val);\n
600 if (traceData) { traceData->setData(final_val); }
601 }''' % (wcond
, self
.ctype
, self
.base_name
, windex
)
605 class FloatRegOperand(Operand
):
609 def isFloatReg(self
):
612 def makeConstructor(self
, predRead
, predWrite
):
617 c_src
= '\n\t_srcRegIdx[_numSrcRegs++] = %s + FP_Reg_Base;' % \
622 '\n\t_destRegIdx[_numDestRegs++] = %s + FP_Reg_Base;' % \
624 c_dest
+= '\n\t_numFPDestRegs++;'
626 return c_src
+ c_dest
628 def makeRead(self
, predRead
):
630 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
631 func
= 'readFloatRegOperand'
633 func
= 'readFloatRegOperandBits'
634 if self
.read_code
!= None:
635 return self
.buildReadCode(func
)
638 rindex
= '_sourceIndex++'
640 rindex
= '%d' % self
.src_reg_idx
642 return '%s = xc->%s(this, %s);\n' % \
643 (self
.base_name
, func
, rindex
)
645 def makeWrite(self
, predWrite
):
646 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
647 func
= 'setFloatRegOperand'
649 func
= 'setFloatRegOperandBits'
650 if self
.write_code
!= None:
651 return self
.buildWriteCode(func
)
656 wp
= '%d' % self
.dest_reg_idx
657 wp
= 'xc->%s(this, %s, final_val);' % (func
, wp
)
663 if (traceData) { traceData->setData(final_val); }
664 }''' % (self
.ctype
, self
.base_name
, wp
)
667 class CCRegOperand(Operand
):
674 def makeConstructor(self
, predRead
, predWrite
):
679 c_src
= '\n\t_srcRegIdx[_numSrcRegs++] = %s + CC_Reg_Base;' % \
681 if self
.hasReadPred():
682 c_src
= '\n\tif (%s) {%s\n\t}' % \
683 (self
.read_predicate
, c_src
)
687 '\n\t_destRegIdx[_numDestRegs++] = %s + CC_Reg_Base;' % \
689 c_dest
+= '\n\t_numCCDestRegs++;'
690 if self
.hasWritePred():
691 c_dest
= '\n\tif (%s) {%s\n\t}' % \
692 (self
.write_predicate
, c_dest
)
694 return c_src
+ c_dest
696 def makeRead(self
, predRead
):
697 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
698 error('Attempt to read condition-code register as FP')
699 if self
.read_code
!= None:
700 return self
.buildReadCode('readCCRegOperand')
704 int_reg_val
= 'xc->readCCRegOperand(this, _sourceIndex++)'
705 if self
.hasReadPred():
706 int_reg_val
= '(%s) ? %s : 0' % \
707 (self
.read_predicate
, int_reg_val
)
709 int_reg_val
= 'xc->readCCRegOperand(this, %d)' % self
.src_reg_idx
711 return '%s = %s;\n' % (self
.base_name
, int_reg_val
)
713 def makeWrite(self
, predWrite
):
714 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
715 error('Attempt to write condition-code register as FP')
716 if self
.write_code
!= None:
717 return self
.buildWriteCode('setCCRegOperand')
721 if self
.hasWritePred():
722 wp
= self
.write_predicate
724 wcond
= 'if (%s)' % (wp
)
725 windex
= '_destIndex++'
728 windex
= '%d' % self
.dest_reg_idx
734 xc->setCCRegOperand(this, %s, final_val);\n
735 if (traceData) { traceData->setData(final_val); }
736 }''' % (wcond
, self
.ctype
, self
.base_name
, windex
)
740 class ControlRegOperand(Operand
):
744 def isControlReg(self
):
747 def makeConstructor(self
, predRead
, predWrite
):
753 '\n\t_srcRegIdx[_numSrcRegs++] = %s + Misc_Reg_Base;' % \
758 '\n\t_destRegIdx[_numDestRegs++] = %s + Misc_Reg_Base;' % \
761 return c_src
+ c_dest
763 def makeRead(self
, predRead
):
765 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
766 error('Attempt to read control register as FP')
767 if self
.read_code
!= None:
768 return self
.buildReadCode('readMiscRegOperand')
771 rindex
= '_sourceIndex++'
773 rindex
= '%d' % self
.src_reg_idx
775 return '%s = xc->readMiscRegOperand(this, %s);\n' % \
776 (self
.base_name
, rindex
)
778 def makeWrite(self
, predWrite
):
779 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
780 error('Attempt to write control register as FP')
781 if self
.write_code
!= None:
782 return self
.buildWriteCode('setMiscRegOperand')
785 windex
= '_destIndex++'
787 windex
= '%d' % self
.dest_reg_idx
789 wb
= 'xc->setMiscRegOperand(this, %s, %s);\n' % \
790 (windex
, self
.base_name
)
791 wb
+= 'if (traceData) { traceData->setData(%s); }' % \
796 class MemOperand(Operand
):
800 def makeConstructor(self
, predRead
, predWrite
):
804 # Note that initializations in the declarations are solely
805 # to avoid 'uninitialized variable' errors from the compiler.
806 # Declare memory data variable.
807 return '%s %s = 0;\n' % (self
.ctype
, self
.base_name
)
809 def makeRead(self
, predRead
):
810 if self
.read_code
!= None:
811 return self
.buildReadCode()
814 def makeWrite(self
, predWrite
):
815 if self
.write_code
!= None:
816 return self
.buildWriteCode()
819 class PCStateOperand(Operand
):
820 def makeConstructor(self
, predRead
, predWrite
):
823 def makeRead(self
, predRead
):
825 # A component of the PC state.
826 return '%s = __parserAutoPCState.%s();\n' % \
827 (self
.base_name
, self
.reg_spec
)
829 # The whole PC state itself.
830 return '%s = xc->pcState();\n' % self
.base_name
832 def makeWrite(self
, predWrite
):
834 # A component of the PC state.
835 return '__parserAutoPCState.%s(%s);\n' % \
836 (self
.reg_spec
, self
.base_name
)
838 # The whole PC state itself.
839 return 'xc->pcState(%s);\n' % self
.base_name
842 ctype
= 'TheISA::PCState'
845 return "%s %s;\n" % (ctype
, self
.base_name
)
850 class OperandList(object):
851 '''Find all the operands in the given code block. Returns an operand
852 descriptor list (instance of class OperandList).'''
853 def __init__(self
, parser
, code
):
856 # delete strings and comments so we don't match on operands inside
857 for regEx
in (stringRE
, commentRE
):
858 code
= regEx
.sub('', code
)
859 # search for operands
862 match
= parser
.operandsRE
.search(code
, next_pos
)
864 # no more matches: we're done
867 # regexp groups are operand full name, base, and extension
868 (op_full
, op_base
, op_ext
) = op
869 # if the token following the operand is an assignment, this is
870 # a destination (LHS), else it's a source (RHS)
871 is_dest
= (assignRE
.match(code
, match
.end()) != None)
873 # see if we've already seen this one
874 op_desc
= self
.find_base(op_base
)
876 if op_desc
.ext
!= op_ext
:
877 error('Inconsistent extensions for operand %s' % \
879 op_desc
.is_src
= op_desc
.is_src
or is_src
880 op_desc
.is_dest
= op_desc
.is_dest
or is_dest
882 # new operand: create new descriptor
883 op_desc
= parser
.operandNameMap
[op_base
](parser
,
884 op_full
, op_ext
, is_src
, is_dest
)
886 # start next search after end of current match
887 next_pos
= match
.end()
889 # enumerate source & dest register operands... used in building
893 self
.numFPDestRegs
= 0
894 self
.numIntDestRegs
= 0
895 self
.numCCDestRegs
= 0
896 self
.numMiscDestRegs
= 0
897 self
.memOperand
= None
899 # Flags to keep track if one or more operands are to be read/written
901 self
.predRead
= False
902 self
.predWrite
= False
904 for op_desc
in self
.items
:
907 op_desc
.src_reg_idx
= self
.numSrcRegs
910 op_desc
.dest_reg_idx
= self
.numDestRegs
911 self
.numDestRegs
+= 1
912 if op_desc
.isFloatReg():
913 self
.numFPDestRegs
+= 1
914 elif op_desc
.isIntReg():
915 self
.numIntDestRegs
+= 1
916 elif op_desc
.isCCReg():
917 self
.numCCDestRegs
+= 1
918 elif op_desc
.isControlReg():
919 self
.numMiscDestRegs
+= 1
920 elif op_desc
.isMem():
922 error("Code block has more than one memory operand.")
923 self
.memOperand
= op_desc
925 # Check if this operand has read/write predication. If true, then
926 # the microop will dynamically index source/dest registers.
927 self
.predRead
= self
.predRead
or op_desc
.hasReadPred()
928 self
.predWrite
= self
.predWrite
or op_desc
.hasWritePred()
930 if parser
.maxInstSrcRegs
< self
.numSrcRegs
:
931 parser
.maxInstSrcRegs
= self
.numSrcRegs
932 if parser
.maxInstDestRegs
< self
.numDestRegs
:
933 parser
.maxInstDestRegs
= self
.numDestRegs
934 if parser
.maxMiscDestRegs
< self
.numMiscDestRegs
:
935 parser
.maxMiscDestRegs
= self
.numMiscDestRegs
937 # now make a final pass to finalize op_desc fields that may depend
938 # on the register enumeration
939 for op_desc
in self
.items
:
940 op_desc
.finalize(self
.predRead
, self
.predWrite
)
943 return len(self
.items
)
945 def __getitem__(self
, index
):
946 return self
.items
[index
]
948 def append(self
, op_desc
):
949 self
.items
.append(op_desc
)
950 self
.bases
[op_desc
.base_name
] = op_desc
952 def find_base(self
, base_name
):
953 # like self.bases[base_name], but returns None if not found
954 # (rather than raising exception)
955 return self
.bases
.get(base_name
)
957 # internal helper function for concat[Some]Attr{Strings|Lists}
958 def __internalConcatAttrs(self
, attr_name
, filter, result
):
959 for op_desc
in self
.items
:
961 result
+= getattr(op_desc
, attr_name
)
964 # return a single string that is the concatenation of the (string)
965 # values of the specified attribute for all operands
966 def concatAttrStrings(self
, attr_name
):
967 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, '')
969 # like concatAttrStrings, but only include the values for the operands
970 # for which the provided filter function returns true
971 def concatSomeAttrStrings(self
, filter, attr_name
):
972 return self
.__internalConcatAttrs
(attr_name
, filter, '')
974 # return a single list that is the concatenation of the (list)
975 # values of the specified attribute for all operands
976 def concatAttrLists(self
, attr_name
):
977 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, [])
979 # like concatAttrLists, but only include the values for the operands
980 # for which the provided filter function returns true
981 def concatSomeAttrLists(self
, filter, attr_name
):
982 return self
.__internalConcatAttrs
(attr_name
, filter, [])
985 self
.items
.sort(lambda a
, b
: a
.sort_pri
- b
.sort_pri
)
987 class SubOperandList(OperandList
):
988 '''Find all the operands in the given code block. Returns an operand
989 descriptor list (instance of class OperandList).'''
990 def __init__(self
, parser
, code
, master_list
):
993 # delete strings and comments so we don't match on operands inside
994 for regEx
in (stringRE
, commentRE
):
995 code
= regEx
.sub('', code
)
996 # search for operands
999 match
= parser
.operandsRE
.search(code
, next_pos
)
1001 # no more matches: we're done
1004 # regexp groups are operand full name, base, and extension
1005 (op_full
, op_base
, op_ext
) = op
1006 # find this op in the master list
1007 op_desc
= master_list
.find_base(op_base
)
1009 error('Found operand %s which is not in the master list!' \
1010 ' This is an internal error' % op_base
)
1012 # See if we've already found this operand
1013 op_desc
= self
.find_base(op_base
)
1015 # if not, add a reference to it to this sub list
1016 self
.append(master_list
.bases
[op_base
])
1018 # start next search after end of current match
1019 next_pos
= match
.end()
1021 self
.memOperand
= None
1022 # Whether the whole PC needs to be read so parts of it can be accessed
1024 # Whether the whole PC needs to be written after parts of it were
1027 # Whether this instruction manipulates the whole PC or parts of it.
1028 # Mixing the two is a bad idea and flagged as an error.
1031 # Flags to keep track if one or more operands are to be read/written
1033 self
.predRead
= False
1034 self
.predWrite
= False
1036 for op_desc
in self
.items
:
1037 if op_desc
.isPCPart():
1042 if op_desc
.isPCState():
1043 if self
.pcPart
is not None:
1044 if self
.pcPart
and not op_desc
.isPCPart() or \
1045 not self
.pcPart
and op_desc
.isPCPart():
1046 error("Mixed whole and partial PC state operands.")
1047 self
.pcPart
= op_desc
.isPCPart()
1051 error("Code block has more than one memory operand.")
1052 self
.memOperand
= op_desc
1054 # Check if this operand has read/write predication. If true, then
1055 # the microop will dynamically index source/dest registers.
1056 self
.predRead
= self
.predRead
or op_desc
.hasReadPred()
1057 self
.predWrite
= self
.predWrite
or op_desc
.hasWritePred()
1059 # Regular expression object to match C++ strings
1060 stringRE
= re
.compile(r
'"([^"\\]|\\.)*"')
1062 # Regular expression object to match C++ comments
1063 # (used in findOperands())
1064 commentRE
= re
.compile(r
'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
1065 re
.DOTALL | re
.MULTILINE
)
1067 # Regular expression object to match assignment statements
1068 # (used in findOperands())
1069 assignRE
= re
.compile(r
'\s*=(?!=)', re
.MULTILINE
)
1071 def makeFlagConstructor(flag_list
):
1072 if len(flag_list
) == 0:
1074 # filter out repeated flags
1077 while i
< len(flag_list
):
1078 if flag_list
[i
] == flag_list
[i
-1]:
1084 code
= pre
+ string
.join(flag_list
, post
+ pre
) + post
1087 # Assume all instruction flags are of the form 'IsFoo'
1088 instFlagRE
= re
.compile(r
'Is.*')
1090 # OpClass constants end in 'Op' except No_OpClass
1091 opClassRE
= re
.compile(r
'.*Op|No_OpClass')
1093 class InstObjParams(object):
1094 def __init__(self
, parser
, mnem
, class_name
, base_class
= '',
1095 snippets
= {}, opt_args
= []):
1096 self
.mnemonic
= mnem
1097 self
.class_name
= class_name
1098 self
.base_class
= base_class
1099 if not isinstance(snippets
, dict):
1100 snippets
= {'code' : snippets
}
1101 compositeCode
= ' '.join(map(str, snippets
.values()))
1102 self
.snippets
= snippets
1104 self
.operands
= OperandList(parser
, compositeCode
)
1106 # The header of the constructor declares the variables to be used
1107 # in the body of the constructor.
1109 header
+= '\n\t_numSrcRegs = 0;'
1110 header
+= '\n\t_numDestRegs = 0;'
1111 header
+= '\n\t_numFPDestRegs = 0;'
1112 header
+= '\n\t_numIntDestRegs = 0;'
1113 header
+= '\n\t_numCCDestRegs = 0;'
1115 self
.constructor
= header
+ \
1116 self
.operands
.concatAttrStrings('constructor')
1118 self
.flags
= self
.operands
.concatAttrLists('flags')
1120 # Make a basic guess on the operand class (function unit type).
1121 # These are good enough for most cases, and can be overridden
1123 if 'IsStore' in self
.flags
:
1124 self
.op_class
= 'MemWriteOp'
1125 elif 'IsLoad' in self
.flags
or 'IsPrefetch' in self
.flags
:
1126 self
.op_class
= 'MemReadOp'
1127 elif 'IsFloating' in self
.flags
:
1128 self
.op_class
= 'FloatAddOp'
1130 self
.op_class
= 'IntAluOp'
1132 # Optional arguments are assumed to be either StaticInst flags
1133 # or an OpClass value. To avoid having to import a complete
1134 # list of these values to match against, we do it ad-hoc
1137 if instFlagRE
.match(oa
):
1138 self
.flags
.append(oa
)
1139 elif opClassRE
.match(oa
):
1142 error('InstObjParams: optional arg "%s" not recognized '
1143 'as StaticInst::Flag or OpClass.' % oa
)
1145 # add flag initialization to contructor here to include
1146 # any flags added via opt_args
1147 self
.constructor
+= makeFlagConstructor(self
.flags
)
1149 # if 'IsFloating' is set, add call to the FP enable check
1150 # function (which should be provided by isa_desc via a declare)
1151 if 'IsFloating' in self
.flags
:
1152 self
.fp_enable_check
= 'fault = checkFpEnableFault(xc);'
1154 self
.fp_enable_check
= ''
1157 # Stack: a simple stack object. Used for both formats (formatStack)
1158 # and default cases (defaultStack). Simply wraps a list to give more
1159 # stack-like syntax and enable initialization with an argument list
1160 # (as opposed to an argument that's a list).
1163 def __init__(self
, *items
):
1164 list.__init
__(self
, items
)
1166 def push(self
, item
):
1172 #######################
1174 # Output file template
1179 * DO NOT EDIT THIS FILE!!!
1181 * It was automatically generated from the ISA description in %(filename)s
1188 namespace %(namespace)s {
1190 %(namespace_output)s
1192 } // namespace %(namespace)s
1197 max_inst_regs_template
= '''
1199 * DO NOT EDIT THIS FILE!!!
1201 * It was automatically generated from the ISA description in %(filename)s
1204 namespace %(namespace)s {
1206 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
1207 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
1208 const int MaxMiscDestRegs = %(MaxMiscDestRegs)d;
1210 } // namespace %(namespace)s
1214 class ISAParser(Grammar
):
1215 def __init__(self
, output_dir
, cpu_models
):
1216 super(ISAParser
, self
).__init
__()
1217 self
.output_dir
= output_dir
1219 self
.cpuModels
= cpu_models
1221 # variable to hold templates
1222 self
.templateMap
= {}
1224 # This dictionary maps format name strings to Format objects.
1228 self
.formatStack
= Stack(NoFormat())
1230 # The default case stack.
1231 self
.defaultStack
= Stack(None)
1233 # Stack that tracks current file and line number. Each
1234 # element is a tuple (filename, lineno) that records the
1235 # *current* filename and the line number in the *previous*
1236 # file where it was included.
1237 self
.fileNameStack
= Stack()
1239 symbols
= ('makeList', 're', 'string')
1240 self
.exportContext
= dict([(s
, eval(s
)) for s
in symbols
])
1242 self
.maxInstSrcRegs
= 0
1243 self
.maxInstDestRegs
= 0
1244 self
.maxMiscDestRegs
= 0
1246 #####################################################################
1250 # The PLY lexer module takes two things as input:
1251 # - A list of token names (the string list 'tokens')
1252 # - A regular expression describing a match for each token. The
1253 # regexp for token FOO can be provided in two ways:
1254 # - as a string variable named t_FOO
1255 # - as the doc string for a function named t_FOO. In this case,
1256 # the function is also executed, allowing an action to be
1257 # associated with each token match.
1259 #####################################################################
1261 # Reserved words. These are listed separately as they are matched
1262 # using the same regexp as generic IDs, but distinguished in the
1263 # t_ID() function. The PLY documentation suggests this approach.
1265 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
1266 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
1267 'OUTPUT', 'SIGNED', 'TEMPLATE'
1270 # List of tokens. The lex module requires this.
1271 tokens
= reserved
+ (
1284 # ( ) [ ] { } < > , ; . : :: *
1286 'LBRACKET', 'RBRACKET',
1288 'LESS', 'GREATER', 'EQUALS',
1289 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON',
1292 # C preprocessor directives
1295 # The following are matched but never returned. commented out to
1296 # suppress PLY warning
1304 # Regular expressions for token matching
1321 # Identifiers and reserved words
1324 reserved_map
[r
.lower()] = r
1328 t
.type = self
.reserved_map
.get(t
.value
, 'ID')
1332 def t_INTLIT(self
, t
):
1333 r
'-?(0x[\da-fA-F]+)|\d+'
1335 t
.value
= int(t
.value
,0)
1337 error(t
, 'Integer value "%s" too large' % t
.value
)
1341 # String literal. Note that these use only single quotes, and
1342 # can span multiple lines.
1343 def t_STRLIT(self
, t
):
1346 t
.value
= t
.value
[1:-1]
1347 t
.lexer
.lineno
+= t
.value
.count('\n')
1351 # "Code literal"... like a string literal, but delimiters are
1352 # '{{' and '}}' so they get formatted nicely under emacs c-mode
1353 def t_CODELIT(self
, t
):
1354 r
"(?m)\{\{([^\}]|}(?!\}))+\}\}"
1356 t
.value
= t
.value
[2:-2]
1357 t
.lexer
.lineno
+= t
.value
.count('\n')
1360 def t_CPPDIRECTIVE(self
, t
):
1362 t
.lexer
.lineno
+= t
.value
.count('\n')
1365 def t_NEWFILE(self
, t
):
1366 r
'^\#\#newfile\s+"[^"]*"'
1367 self
.fileNameStack
.push((t
.value
[11:-1], t
.lexer
.lineno
))
1370 def t_ENDFILE(self
, t
):
1372 (old_filename
, t
.lexer
.lineno
) = self
.fileNameStack
.pop()
1375 # The functions t_NEWLINE, t_ignore, and t_error are
1376 # special for the lex module.
1380 def t_NEWLINE(self
, t
):
1382 t
.lexer
.lineno
+= t
.value
.count('\n')
1385 def t_comment(self
, t
):
1388 # Completely ignored characters
1389 t_ignore
= ' \t\x0c'
1392 def t_error(self
, t
):
1393 error(t
, "illegal character '%s'" % t
.value
[0])
1396 #####################################################################
1400 # Every function whose name starts with 'p_' defines a grammar
1401 # rule. The rule is encoded in the function's doc string, while
1402 # the function body provides the action taken when the rule is
1403 # matched. The argument to each function is a list of the values
1404 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the
1405 # symbols on the RHS. For tokens, the value is copied from the
1406 # t.value attribute provided by the lexer. For non-terminals, the
1407 # value is assigned by the producing rule; i.e., the job of the
1408 # grammar rule function is to set the value for the non-terminal
1409 # on the LHS (by assigning to t[0]).
1410 #####################################################################
1412 # The LHS of the first grammar rule is used as the start symbol
1413 # (in this case, 'specification'). Note that this rule enforces
1414 # that there will be exactly one namespace declaration, with 0 or
1415 # more global defs/decls before and after it. The defs & decls
1416 # before the namespace decl will be outside the namespace; those
1417 # after will be inside. The decoder function is always inside the
1419 def p_specification(self
, t
):
1420 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
1423 namespace
= isa_name
+ "Inst"
1424 # wrap the decode block as a function definition
1425 t
[4].wrap_decode_block('''
1427 %(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst)
1429 using namespace %(namespace)s;
1431 # both the latter output blocks and the decode block are in
1433 namespace_code
= t
[3] + t
[4]
1434 # pass it all back to the caller of yacc.parse()
1435 t
[0] = (isa_name
, namespace
, global_code
, namespace_code
)
1437 # ISA name declaration looks like "namespace <foo>;"
1438 def p_name_decl(self
, t
):
1439 'name_decl : NAMESPACE ID SEMI'
1442 # 'opt_defs_and_outputs' is a possibly empty sequence of
1443 # def and/or output statements.
1444 def p_opt_defs_and_outputs_0(self
, t
):
1445 'opt_defs_and_outputs : empty'
1446 t
[0] = GenCode(self
)
1448 def p_opt_defs_and_outputs_1(self
, t
):
1449 'opt_defs_and_outputs : defs_and_outputs'
1452 def p_defs_and_outputs_0(self
, t
):
1453 'defs_and_outputs : def_or_output'
1456 def p_defs_and_outputs_1(self
, t
):
1457 'defs_and_outputs : defs_and_outputs def_or_output'
1460 # The list of possible definition/output statements.
1461 def p_def_or_output(self
, t
):
1462 '''def_or_output : def_format
1464 | def_bitfield_struct
1474 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1475 # directly to the appropriate output section.
1477 # Massage output block by substituting in template definitions and
1478 # bit operators. We handle '%'s embedded in the string that don't
1479 # indicate template substitutions (or CPU-specific symbols, which
1480 # get handled in GenCode) by doubling them first so that the
1481 # format operation will reduce them back to single '%'s.
1482 def process_output(self
, s
):
1483 s
= self
.protectNonSubstPercents(s
)
1484 # protects cpu-specific symbols too
1485 s
= self
.protectCpuSymbols(s
)
1486 return substBitOps(s
% self
.templateMap
)
1488 def p_output_header(self
, t
):
1489 'output_header : OUTPUT HEADER CODELIT SEMI'
1490 t
[0] = GenCode(self
, header_output
= self
.process_output(t
[3]))
1492 def p_output_decoder(self
, t
):
1493 'output_decoder : OUTPUT DECODER CODELIT SEMI'
1494 t
[0] = GenCode(self
, decoder_output
= self
.process_output(t
[3]))
1496 def p_output_exec(self
, t
):
1497 'output_exec : OUTPUT EXEC CODELIT SEMI'
1498 t
[0] = GenCode(self
, exec_output
= self
.process_output(t
[3]))
1500 # global let blocks 'let {{...}}' (Python code blocks) are
1501 # executed directly when seen. Note that these execute in a
1502 # special variable context 'exportContext' to prevent the code
1503 # from polluting this script's namespace.
1504 def p_global_let(self
, t
):
1505 'global_let : LET CODELIT SEMI'
1506 self
.updateExportContext()
1507 self
.exportContext
["header_output"] = ''
1508 self
.exportContext
["decoder_output"] = ''
1509 self
.exportContext
["exec_output"] = ''
1510 self
.exportContext
["decode_block"] = ''
1512 exec fixPythonIndentation(t
[2]) in self
.exportContext
1513 except Exception, exc
:
1516 error(t
, 'error: %s in global let block "%s".' % (exc
, t
[2]))
1517 t
[0] = GenCode(self
,
1518 header_output
=self
.exportContext
["header_output"],
1519 decoder_output
=self
.exportContext
["decoder_output"],
1520 exec_output
=self
.exportContext
["exec_output"],
1521 decode_block
=self
.exportContext
["decode_block"])
1523 # Define the mapping from operand type extensions to C++ types and
1524 # bit widths (stored in operandTypeMap).
1525 def p_def_operand_types(self
, t
):
1526 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1528 self
.operandTypeMap
= eval('{' + t
[3] + '}')
1529 except Exception, exc
:
1533 'error: %s in def operand_types block "%s".' % (exc
, t
[3]))
1534 t
[0] = GenCode(self
) # contributes nothing to the output C++ file
1536 # Define the mapping from operand names to operand classes and
1537 # other traits. Stored in operandNameMap.
1538 def p_def_operands(self
, t
):
1539 'def_operands : DEF OPERANDS CODELIT SEMI'
1540 if not hasattr(self
, 'operandTypeMap'):
1541 error(t
, 'error: operand types must be defined before operands')
1543 user_dict
= eval('{' + t
[3] + '}', self
.exportContext
)
1544 except Exception, exc
:
1547 error(t
, 'error: %s in def operands block "%s".' % (exc
, t
[3]))
1548 self
.buildOperandNameMap(user_dict
, t
.lexer
.lineno
)
1549 t
[0] = GenCode(self
) # contributes nothing to the output C++ file
1551 # A bitfield definition looks like:
1552 # 'def [signed] bitfield <ID> [<first>:<last>]'
1553 # This generates a preprocessor macro in the output file.
1554 def p_def_bitfield_0(self
, t
):
1555 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
1556 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[8])
1557 if (t
[2] == 'signed'):
1558 expr
= 'sext<%d>(%s)' % (t
[6] - t
[8] + 1, expr
)
1559 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1560 t
[0] = GenCode(self
, header_output
=hash_define
)
1562 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
1563 def p_def_bitfield_1(self
, t
):
1564 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
1565 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[6])
1566 if (t
[2] == 'signed'):
1567 expr
= 'sext<%d>(%s)' % (1, expr
)
1568 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1569 t
[0] = GenCode(self
, header_output
=hash_define
)
1571 # alternate form for structure member: 'def bitfield <ID> <ID>'
1572 def p_def_bitfield_struct(self
, t
):
1573 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI'
1575 error(t
, 'error: structure bitfields are always unsigned.')
1576 expr
= 'machInst.%s' % t
[5]
1577 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1578 t
[0] = GenCode(self
, header_output
=hash_define
)
1580 def p_id_with_dot_0(self
, t
):
1584 def p_id_with_dot_1(self
, t
):
1585 'id_with_dot : ID DOT id_with_dot'
1586 t
[0] = t
[1] + t
[2] + t
[3]
1588 def p_opt_signed_0(self
, t
):
1589 'opt_signed : SIGNED'
1592 def p_opt_signed_1(self
, t
):
1593 'opt_signed : empty'
1596 def p_def_template(self
, t
):
1597 'def_template : DEF TEMPLATE ID CODELIT SEMI'
1598 self
.templateMap
[t
[3]] = Template(self
, t
[4])
1599 t
[0] = GenCode(self
)
1601 # An instruction format definition looks like
1602 # "def format <fmt>(<params>) {{...}};"
1603 def p_def_format(self
, t
):
1604 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1605 (id, params
, code
) = (t
[3], t
[5], t
[7])
1606 self
.defFormat(id, params
, code
, t
.lexer
.lineno
)
1607 t
[0] = GenCode(self
)
1609 # The formal parameter list for an instruction format is a
1610 # possibly empty list of comma-separated parameters. Positional
1611 # (standard, non-keyword) parameters must come first, followed by
1612 # keyword parameters, followed by a '*foo' parameter that gets
1613 # excess positional arguments (as in Python). Each of these three
1614 # parameter categories is optional.
1616 # Note that we do not support the '**foo' parameter for collecting
1617 # otherwise undefined keyword args. Otherwise the parameter list
1618 # is (I believe) identical to what is supported in Python.
1620 # The param list generates a tuple, where the first element is a
1621 # list of the positional params and the second element is a dict
1622 # containing the keyword params.
1623 def p_param_list_0(self
, t
):
1624 'param_list : positional_param_list COMMA nonpositional_param_list'
1627 def p_param_list_1(self
, t
):
1628 '''param_list : positional_param_list
1629 | nonpositional_param_list'''
1632 def p_positional_param_list_0(self
, t
):
1633 'positional_param_list : empty'
1636 def p_positional_param_list_1(self
, t
):
1637 'positional_param_list : ID'
1640 def p_positional_param_list_2(self
, t
):
1641 'positional_param_list : positional_param_list COMMA ID'
1642 t
[0] = t
[1] + [t
[3]]
1644 def p_nonpositional_param_list_0(self
, t
):
1645 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
1648 def p_nonpositional_param_list_1(self
, t
):
1649 '''nonpositional_param_list : keyword_param_list
1650 | excess_args_param'''
1653 def p_keyword_param_list_0(self
, t
):
1654 'keyword_param_list : keyword_param'
1657 def p_keyword_param_list_1(self
, t
):
1658 'keyword_param_list : keyword_param_list COMMA keyword_param'
1659 t
[0] = t
[1] + [t
[3]]
1661 def p_keyword_param(self
, t
):
1662 'keyword_param : ID EQUALS expr'
1663 t
[0] = t
[1] + ' = ' + t
[3].__repr
__()
1665 def p_excess_args_param(self
, t
):
1666 'excess_args_param : ASTERISK ID'
1667 # Just concatenate them: '*ID'. Wrap in list to be consistent
1668 # with positional_param_list and keyword_param_list.
1669 t
[0] = [t
[1] + t
[2]]
1671 # End of format definition-related rules.
1675 # A decode block looks like:
1676 # decode <field1> [, <field2>]* [default <inst>] { ... }
1678 def p_decode_block(self
, t
):
1679 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
1680 default_defaults
= self
.defaultStack
.pop()
1682 # use the "default defaults" only if there was no explicit
1683 # default statement in decode_stmt_list
1684 if not codeObj
.has_decode_default
:
1685 codeObj
+= default_defaults
1686 codeObj
.wrap_decode_block('switch (%s) {\n' % t
[2], '}\n')
1689 # The opt_default statement serves only to push the "default
1690 # defaults" onto defaultStack. This value will be used by nested
1691 # decode blocks, and used and popped off when the current
1692 # decode_block is processed (in p_decode_block() above).
1693 def p_opt_default_0(self
, t
):
1694 'opt_default : empty'
1695 # no default specified: reuse the one currently at the top of
1697 self
.defaultStack
.push(self
.defaultStack
.top())
1698 # no meaningful value returned
1701 def p_opt_default_1(self
, t
):
1702 'opt_default : DEFAULT inst'
1703 # push the new default
1705 codeObj
.wrap_decode_block('\ndefault:\n', 'break;\n')
1706 self
.defaultStack
.push(codeObj
)
1707 # no meaningful value returned
1710 def p_decode_stmt_list_0(self
, t
):
1711 'decode_stmt_list : decode_stmt'
1714 def p_decode_stmt_list_1(self
, t
):
1715 'decode_stmt_list : decode_stmt decode_stmt_list'
1716 if (t
[1].has_decode_default
and t
[2].has_decode_default
):
1717 error(t
, 'Two default cases in decode block')
1721 # Decode statement rules
1723 # There are four types of statements allowed in a decode block:
1724 # 1. Format blocks 'format <foo> { ... }'
1725 # 2. Nested decode blocks
1726 # 3. Instruction definitions.
1727 # 4. C preprocessor directives.
1730 # Preprocessor directives found in a decode statement list are
1731 # passed through to the output, replicated to all of the output
1732 # code streams. This works well for ifdefs, so we can ifdef out
1733 # both the declarations and the decode cases generated by an
1734 # instruction definition. Handling them as part of the grammar
1735 # makes it easy to keep them in the right place with respect to
1736 # the code generated by the other statements.
1737 def p_decode_stmt_cpp(self
, t
):
1738 'decode_stmt : CPPDIRECTIVE'
1739 t
[0] = GenCode(self
, t
[1], t
[1], t
[1], t
[1])
1741 # A format block 'format <foo> { ... }' sets the default
1742 # instruction format used to handle instruction definitions inside
1743 # the block. This format can be overridden by using an explicit
1744 # format on the instruction definition or with a nested format
1746 def p_decode_stmt_format(self
, t
):
1747 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
1748 # The format will be pushed on the stack when 'push_format_id'
1749 # is processed (see below). Once the parser has recognized
1750 # the full production (though the right brace), we're done
1751 # with the format, so now we can pop it.
1752 self
.formatStack
.pop()
1755 # This rule exists so we can set the current format (& push the
1756 # stack) when we recognize the format name part of the format
1758 def p_push_format_id(self
, t
):
1759 'push_format_id : ID'
1761 self
.formatStack
.push(self
.formatMap
[t
[1]])
1762 t
[0] = ('', '// format %s' % t
[1])
1764 error(t
, 'instruction format "%s" not defined.' % t
[1])
1766 # Nested decode block: if the value of the current field matches
1767 # the specified constant, do a nested decode on some other field.
1768 def p_decode_stmt_decode(self
, t
):
1769 'decode_stmt : case_label COLON decode_block'
1772 # just wrap the decoding code from the block as a case in the
1773 # outer switch statement.
1774 codeObj
.wrap_decode_block('\n%s:\n' % label
)
1775 codeObj
.has_decode_default
= (label
== 'default')
1778 # Instruction definition (finally!).
1779 def p_decode_stmt_inst(self
, t
):
1780 'decode_stmt : case_label COLON inst SEMI'
1783 codeObj
.wrap_decode_block('\n%s:' % label
, 'break;\n')
1784 codeObj
.has_decode_default
= (label
== 'default')
1787 # The case label is either a list of one or more constants or
1789 def p_case_label_0(self
, t
):
1790 'case_label : intlit_list'
1791 def make_case(intlit
):
1793 return 'case ULL(%#x)' % intlit
1795 return 'case %#x' % intlit
1796 t
[0] = ': '.join(map(make_case
, t
[1]))
1798 def p_case_label_1(self
, t
):
1799 'case_label : DEFAULT'
1803 # The constant list for a decode case label must be non-empty, but
1804 # may have one or more comma-separated integer literals in it.
1806 def p_intlit_list_0(self
, t
):
1807 'intlit_list : INTLIT'
1810 def p_intlit_list_1(self
, t
):
1811 'intlit_list : intlit_list COMMA INTLIT'
1815 # Define an instruction using the current instruction format
1816 # (specified by an enclosing format block).
1817 # "<mnemonic>(<args>)"
1818 def p_inst_0(self
, t
):
1819 'inst : ID LPAREN arg_list RPAREN'
1820 # Pass the ID and arg list to the current format class to deal with.
1821 currentFormat
= self
.formatStack
.top()
1822 codeObj
= currentFormat
.defineInst(self
, t
[1], t
[3], t
.lexer
.lineno
)
1823 args
= ','.join(map(str, t
[3]))
1824 args
= re
.sub('(?m)^', '//', args
)
1825 args
= re
.sub('^//', '', args
)
1826 comment
= '\n// %s::%s(%s)\n' % (currentFormat
.id, t
[1], args
)
1827 codeObj
.prepend_all(comment
)
1830 # Define an instruction using an explicitly specified format:
1831 # "<fmt>::<mnemonic>(<args>)"
1832 def p_inst_1(self
, t
):
1833 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1835 format
= self
.formatMap
[t
[1]]
1837 error(t
, 'instruction format "%s" not defined.' % t
[1])
1839 codeObj
= format
.defineInst(self
, 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 updateExportContext(self
):
1938 # create a continuation that allows us to grab the current parser
1939 def wrapInstObjParams(*args
):
1940 return InstObjParams(self
, *args
)
1941 self
.exportContext
['InstObjParams'] = wrapInstObjParams
1942 self
.exportContext
.update(self
.templateMap
)
1944 def defFormat(self
, id, params
, code
, lineno
):
1945 '''Define a new format'''
1947 # make sure we haven't already defined this one
1948 if id in self
.formatMap
:
1949 error(lineno
, 'format %s redefined.' % id)
1951 # create new object and store in global map
1952 self
.formatMap
[id] = Format(id, params
, code
)
1954 def expandCpuSymbolsToDict(self
, template
):
1955 '''Expand template with CPU-specific references into a
1956 dictionary with an entry for each CPU model name. The entry
1957 key is the model name and the corresponding value is the
1958 template with the CPU-specific refs substituted for that
1961 # Protect '%'s that don't go with CPU-specific terms
1962 t
= re
.sub(r
'%(?!\(CPU_)', '%%', template
)
1964 for cpu
in self
.cpuModels
:
1965 result
[cpu
.name
] = t
% cpu
.strings
1968 def expandCpuSymbolsToString(self
, template
):
1969 '''*If* the template has CPU-specific references, return a
1970 single string containing a copy of the template for each CPU
1971 model with the corresponding values substituted in. If the
1972 template has no CPU-specific references, it is returned
1975 if template
.find('%(CPU_') != -1:
1976 return reduce(lambda x
,y
: x
+y
,
1977 self
.expandCpuSymbolsToDict(template
).values())
1981 def protectCpuSymbols(self
, template
):
1982 '''Protect CPU-specific references by doubling the
1983 corresponding '%'s (in preparation for substituting a different
1984 set of references into the template).'''
1986 return re
.sub(r
'%(?=\(CPU_)', '%%', template
)
1988 def protectNonSubstPercents(self
, s
):
1989 '''Protect any non-dict-substitution '%'s in a format string
1990 (i.e. those not followed by '(')'''
1992 return re
.sub(r
'%(?!\()', '%%', s
)
1994 def buildOperandNameMap(self
, user_dict
, lineno
):
1996 for op_name
, val
in user_dict
.iteritems():
1998 # Check if extra attributes have been specified.
2000 error(lineno
, 'error: too many attributes for operand "%s"' %
2003 # Pad val with None in case optional args are missing
2004 val
+= (None, None, None, None)
2005 base_cls_name
, dflt_ext
, reg_spec
, flags
, sort_pri
, \
2006 read_code
, write_code
, read_predicate
, write_predicate
= val
[:9]
2008 # Canonical flag structure is a triple of lists, where each list
2009 # indicates the set of flags implied by this operand always, when
2010 # used as a source, and when used as a dest, respectively.
2011 # For simplicity this can be initialized using a variety of fairly
2012 # obvious shortcuts; we convert these to canonical form here.
2014 # no flags specified (e.g., 'None')
2015 flags
= ( [], [], [] )
2016 elif isinstance(flags
, str):
2017 # a single flag: assumed to be unconditional
2018 flags
= ( [ flags
], [], [] )
2019 elif isinstance(flags
, list):
2020 # a list of flags: also assumed to be unconditional
2021 flags
= ( flags
, [], [] )
2022 elif isinstance(flags
, tuple):
2023 # it's a tuple: it should be a triple,
2024 # but each item could be a single string or a list
2025 (uncond_flags
, src_flags
, dest_flags
) = flags
2026 flags
= (makeList(uncond_flags
),
2027 makeList(src_flags
), makeList(dest_flags
))
2029 # Accumulate attributes of new operand class in tmp_dict
2031 attrList
= ['reg_spec', 'flags', 'sort_pri',
2032 'read_code', 'write_code',
2033 'read_predicate', 'write_predicate']
2035 dflt_ctype
= self
.operandTypeMap
[dflt_ext
]
2036 attrList
.extend(['dflt_ctype', 'dflt_ext'])
2037 for attr
in attrList
:
2038 tmp_dict
[attr
] = eval(attr
)
2039 tmp_dict
['base_name'] = op_name
2041 # New class name will be e.g. "IntReg_Ra"
2042 cls_name
= base_cls_name
+ '_' + op_name
2043 # Evaluate string arg to get class object. Note that the
2044 # actual base class for "IntReg" is "IntRegOperand", i.e. we
2045 # have to append "Operand".
2047 base_cls
= eval(base_cls_name
+ 'Operand')
2050 'error: unknown operand base class "%s"' % base_cls_name
)
2051 # The following statement creates a new class called
2052 # <cls_name> as a subclass of <base_cls> with the attributes
2053 # in tmp_dict, just as if we evaluated a class declaration.
2054 operand_name
[op_name
] = type(cls_name
, (base_cls
,), tmp_dict
)
2056 self
.operandNameMap
= operand_name
2058 # Define operand variables.
2059 operands
= user_dict
.keys()
2060 extensions
= self
.operandTypeMap
.keys()
2062 operandsREString
= r
'''
2063 (?<!\w) # neg. lookbehind assertion: prevent partial matches
2064 ((%s)(?:_(%s))?) # match: operand with optional '_' then suffix
2065 (?!\w) # neg. lookahead assertion: prevent partial matches
2066 ''' % (string
.join(operands
, '|'), string
.join(extensions
, '|'))
2068 self
.operandsRE
= re
.compile(operandsREString
, re
.MULTILINE|re
.VERBOSE
)
2070 # Same as operandsREString, but extension is mandatory, and only two
2071 # groups are returned (base and ext, not full name as above).
2072 # Used for subtituting '_' for '.' to make C++ identifiers.
2073 operandsWithExtREString
= r
'(?<!\w)(%s)_(%s)(?!\w)' \
2074 % (string
.join(operands
, '|'), string
.join(extensions
, '|'))
2076 self
.operandsWithExtRE
= \
2077 re
.compile(operandsWithExtREString
, re
.MULTILINE
)
2079 def substMungedOpNames(self
, code
):
2080 '''Munge operand names in code string to make legal C++
2081 variable names. This means getting rid of the type extension
2082 if any. Will match base_name attribute of Operand object.)'''
2083 return self
.operandsWithExtRE
.sub(r
'\1', code
)
2085 def mungeSnippet(self
, s
):
2086 '''Fix up code snippets for final substitution in templates.'''
2087 if isinstance(s
, str):
2088 return self
.substMungedOpNames(substBitOps(s
))
2092 def update(self
, file, contents
):
2093 '''Update the output file. If the contents are unchanged,
2094 the scons hash feature will avoid recompilation.'''
2095 file = os
.path
.join(self
.output_dir
, file)
2100 # This regular expression matches '##include' directives
2101 includeRE
= re
.compile(r
'^\s*##include\s+"(?P<filename>[^"]*)".*$',
2104 def replace_include(self
, matchobj
, dirname
):
2105 """Function to replace a matched '##include' directive with the
2106 contents of the specified file (with nested ##includes
2107 replaced recursively). 'matchobj' is an re match object
2108 (from a match of includeRE) and 'dirname' is the directory
2109 relative to which the file path should be resolved."""
2111 fname
= matchobj
.group('filename')
2112 full_fname
= os
.path
.normpath(os
.path
.join(dirname
, fname
))
2113 contents
= '##newfile "%s"\n%s\n##endfile\n' % \
2114 (full_fname
, self
.read_and_flatten(full_fname
))
2117 def read_and_flatten(self
, filename
):
2118 """Read a file and recursively flatten nested '##include' files."""
2120 current_dir
= os
.path
.dirname(filename
)
2122 contents
= open(filename
).read()
2124 error('Error including file "%s"' % filename
)
2126 self
.fileNameStack
.push((filename
, 0))
2128 # Find any includes and include them
2129 def replace(matchobj
):
2130 return self
.replace_include(matchobj
, current_dir
)
2131 contents
= self
.includeRE
.sub(replace
, contents
)
2133 self
.fileNameStack
.pop()
2136 def _parse_isa_desc(self
, isa_desc_file
):
2137 '''Read in and parse the ISA description.'''
2139 # Read file and (recursively) all included files into a string.
2140 # PLY requires that the input be in a single string so we have to
2142 isa_desc
= self
.read_and_flatten(isa_desc_file
)
2144 # Initialize filename stack with outer file.
2145 self
.fileNameStack
.push((isa_desc_file
, 0))
2148 (isa_name
, namespace
, global_code
, namespace_code
) = \
2149 self
.parse_string(isa_desc
)
2151 # grab the last three path components of isa_desc_file to put in
2153 filename
= '/'.join(isa_desc_file
.split('/')[-3:])
2155 # generate decoder.hh
2156 includes
= '#include "base/bitfield.hh" // for bitfield support'
2157 global_output
= global_code
.header_output
2158 namespace_output
= namespace_code
.header_output
2159 decode_function
= ''
2160 self
.update('decoder.hh', file_template
% vars())
2162 # generate decoder.cc
2163 includes
= '#include "decoder.hh"'
2164 global_output
= global_code
.decoder_output
2165 namespace_output
= namespace_code
.decoder_output
2166 # namespace_output += namespace_code.decode_block
2167 decode_function
= namespace_code
.decode_block
2168 self
.update('decoder.cc', file_template
% vars())
2170 # generate per-cpu exec files
2171 for cpu
in self
.cpuModels
:
2172 includes
= '#include "decoder.hh"\n'
2173 includes
+= cpu
.includes
2174 global_output
= global_code
.exec_output
[cpu
.name
]
2175 namespace_output
= namespace_code
.exec_output
[cpu
.name
]
2176 decode_function
= ''
2177 self
.update(cpu
.filename
, file_template
% vars())
2179 # The variable names here are hacky, but this will creat local
2180 # variables which will be referenced in vars() which have the
2181 # value of the globals.
2182 MaxInstSrcRegs
= self
.maxInstSrcRegs
2183 MaxInstDestRegs
= self
.maxInstDestRegs
2184 MaxMiscDestRegs
= self
.maxMiscDestRegs
2186 self
.update('max_inst_regs.hh',
2187 max_inst_regs_template
% vars())
2189 def parse_isa_desc(self
, *args
, **kwargs
):
2191 self
._parse
_isa
_desc
(*args
, **kwargs
)
2192 except ISAParserError
, e
:
2193 e
.exit(self
.fileNameStack
)
2195 # Called as script: get args from command line.
2196 # Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2197 if __name__
== '__main__':
2198 execfile(sys
.argv
[1]) # read in CpuModel definitions
2199 cpu_models
= [CpuModel
.dict[cpu
] for cpu
in sys
.argv
[4:]]
2200 ISAParser(sys
.argv
[3], cpu_models
).parse_isa_desc(sys
.argv
[2])