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
45 # Indent every line in string 's' by two spaces
46 # (except preprocessor directives).
47 # Used to make nested code blocks look pretty.
50 return re
.sub(r
'(?m)^(?!#)', ' ', s
)
53 # Munge a somewhat arbitrarily formatted piece of Python code
54 # (e.g. from a format 'let' block) into something whose indentation
55 # will get by the Python parser.
57 # The two keys here are that Python will give a syntax error if
58 # there's any whitespace at the beginning of the first line, and that
59 # all lines at the same lexical nesting level must have identical
60 # indentation. Unfortunately the way code literals work, an entire
61 # let block tends to have some initial indentation. Rather than
62 # trying to figure out what that is and strip it off, we prepend 'if
63 # 1:' to make the let code the nested block inside the if (and have
64 # the parser automatically deal with the indentation for us).
66 # We don't want to do this if (1) the code block is empty or (2) the
67 # first line of the block doesn't have any whitespace at the front.
69 def fixPythonIndentation(s
):
70 # get rid of blank lines first
71 s
= re
.sub(r
'(?m)^\s*\n', '', s
);
72 if (s
!= '' and re
.match(r
'[ \t]', s
[0])):
76 class ISAParserError(Exception):
77 """Error handler for parser errors"""
78 def __init__(self
, first
, second
=None):
83 if hasattr(first
, 'lexer'):
84 first
= first
.lexer
.lineno
88 def display(self
, filename_stack
, print_traceback
=debug
):
89 # Output formatted to work under Emacs compile-mode. Optional
90 # 'print_traceback' arg, if set to True, prints a Python stack
91 # backtrace too (can be handy when trying to debug the parser
95 for (filename
, line
) in filename_stack
[:-1]:
96 print "%sIn file included from %s:" % (spaces
, filename
)
99 # Print a Python stack backtrace if requested.
100 if print_traceback
or not self
.lineno
:
101 traceback
.print_exc()
103 line_str
= "%s:" % (filename_stack
[-1][0], )
105 line_str
+= "%d:" % (self
.lineno
, )
107 return "%s%s %s" % (spaces
, line_str
, self
.string
)
109 def exit(self
, filename_stack
, print_traceback
=debug
):
112 sys
.exit(self
.display(filename_stack
, print_traceback
))
115 raise ISAParserError(*args
)
120 # Template objects are format strings that allow substitution from
121 # the attribute spaces of other objects (e.g. InstObjParams instances).
123 labelRE
= re
.compile(r
'(?<!%)%\(([^\)]+)\)[sd]')
125 class Template(object):
126 def __init__(self
, parser
, t
):
133 # Protect non-Python-dict substitutions (e.g. if there's a printf
134 # in the templated C++ code)
135 template
= self
.parser
.protectNonSubstPercents(self
.template
)
136 # CPU-model-specific substitutions are handled later (in GenCode).
137 template
= self
.parser
.protectCpuSymbols(template
)
139 # Build a dict ('myDict') to use for the template substitution.
140 # Start with the template namespace. Make a copy since we're
141 # going to modify it.
142 myDict
= self
.parser
.templateMap
.copy()
144 if isinstance(d
, InstObjParams
):
145 # If we're dealing with an InstObjParams object, we need
146 # to be a little more sophisticated. The instruction-wide
147 # parameters are already formed, but the parameters which
148 # are only function wide still need to be generated.
151 myDict
.update(d
.__dict
__)
152 # The "operands" and "snippets" attributes of the InstObjParams
153 # objects are for internal use and not substitution.
154 del myDict
['operands']
155 del myDict
['snippets']
157 snippetLabels
= [l
for l
in labelRE
.findall(template
)
158 if d
.snippets
.has_key(l
)]
160 snippets
= dict([(s
, self
.parser
.mungeSnippet(d
.snippets
[s
]))
161 for s
in snippetLabels
])
163 myDict
.update(snippets
)
165 compositeCode
= ' '.join(map(str, snippets
.values()))
167 # Add in template itself in case it references any
168 # operands explicitly (like Mem)
169 compositeCode
+= ' ' + template
171 operands
= SubOperandList(self
.parser
, compositeCode
, d
.operands
)
173 myDict
['op_decl'] = operands
.concatAttrStrings('op_decl')
174 if operands
.readPC
or operands
.setPC
:
175 myDict
['op_decl'] += 'TheISA::PCState __parserAutoPCState;\n'
177 is_src
= lambda op
: op
.is_src
178 is_dest
= lambda op
: op
.is_dest
180 myDict
['op_src_decl'] = \
181 operands
.concatSomeAttrStrings(is_src
, 'op_src_decl')
182 myDict
['op_dest_decl'] = \
183 operands
.concatSomeAttrStrings(is_dest
, 'op_dest_decl')
185 myDict
['op_src_decl'] += \
186 'TheISA::PCState __parserAutoPCState;\n'
188 myDict
['op_dest_decl'] += \
189 'TheISA::PCState __parserAutoPCState;\n'
191 myDict
['op_rd'] = operands
.concatAttrStrings('op_rd')
193 myDict
['op_rd'] = '__parserAutoPCState = xc->pcState();\n' + \
196 # Compose the op_wb string. If we're going to write back the
197 # PC state because we changed some of its elements, we'll need to
198 # do that as early as possible. That allows later uncoordinated
199 # modifications to the PC to layer appropriately.
200 reordered
= list(operands
.items
)
203 pcWbStr
= 'xc->pcState(__parserAutoPCState);\n'
204 for op_desc
in reordered
:
205 if op_desc
.isPCPart() and op_desc
.is_dest
:
206 op_wb_str
= op_desc
.op_wb
+ pcWbStr
+ op_wb_str
209 op_wb_str
= op_desc
.op_wb
+ op_wb_str
210 myDict
['op_wb'] = op_wb_str
212 elif isinstance(d
, dict):
213 # if the argument is a dictionary, we just use it.
215 elif hasattr(d
, '__dict__'):
216 # if the argument is an object, we use its attribute map.
217 myDict
.update(d
.__dict
__)
219 raise TypeError, "Template.subst() arg must be or have dictionary"
220 return template
% myDict
222 # Convert to string. This handles the case when a template with a
223 # CPU-specific term gets interpolated into another template or into
226 return self
.parser
.expandCpuSymbolsToString(self
.template
)
231 # A format object encapsulates an instruction format. It must provide
232 # a defineInst() method that generates the code for an instruction
235 class Format(object):
236 def __init__(self
, id, params
, code
):
239 label
= 'def format ' + id
240 self
.user_code
= compile(fixPythonIndentation(code
), label
, 'exec')
241 param_list
= string
.join(params
, ", ")
242 f
= '''def defInst(_code, _context, %s):
243 my_locals = vars().copy()
244 exec _code in _context, my_locals
245 return my_locals\n''' % param_list
246 c
= compile(f
, label
+ ' wrapper', 'exec')
250 def defineInst(self
, parser
, name
, args
, lineno
):
251 parser
.updateExportContext()
252 context
= parser
.exportContext
.copy()
254 Name
= name
[0].upper()
257 context
.update({ 'name' : name
, 'Name' : Name
})
259 vars = self
.func(self
.user_code
, context
, *args
[0], **args
[1])
260 except Exception, exc
:
263 error(lineno
, 'error defining "%s": %s.' % (name
, exc
))
264 for k
in vars.keys():
265 if k
not in ('header_output', 'decoder_output',
266 'exec_output', 'decode_block'):
268 return GenCode(parser
, **vars)
270 # Special null format to catch an implicit-format instruction
271 # definition outside of any format block.
272 class NoFormat(object):
274 self
.defaultInst
= ''
276 def defineInst(self
, parser
, name
, args
, lineno
):
278 'instruction definition "%s" with no active format!' % name
)
283 # The GenCode class encapsulates generated code destined for various
284 # output files. The header_output and decoder_output attributes are
285 # strings containing code destined for decoder.hh and decoder.cc
286 # respectively. The decode_block attribute contains code to be
287 # incorporated in the decode function itself (that will also end up in
288 # decoder.cc). The exec_output attribute is a dictionary with a key
289 # for each CPU model name; the value associated with a particular key
290 # is the string of code for that CPU model's exec.cc file. The
291 # has_decode_default attribute is used in the decode block to allow
292 # explicit default clauses to override default default clauses.
294 class GenCode(object):
295 # Constructor. At this point we substitute out all CPU-specific
296 # symbols. For the exec output, these go into the per-model
297 # dictionary. For all other output types they get collapsed into
299 def __init__(self
, parser
,
300 header_output
= '', decoder_output
= '', exec_output
= '',
301 decode_block
= '', has_decode_default
= False):
303 self
.header_output
= parser
.expandCpuSymbolsToString(header_output
)
304 self
.decoder_output
= parser
.expandCpuSymbolsToString(decoder_output
)
305 if isinstance(exec_output
, dict):
306 self
.exec_output
= exec_output
307 elif isinstance(exec_output
, str):
308 # If the exec_output arg is a single string, we replicate
309 # it for each of the CPU models, substituting and
310 # %(CPU_foo)s params appropriately.
311 self
.exec_output
= parser
.expandCpuSymbolsToDict(exec_output
)
312 self
.decode_block
= parser
.expandCpuSymbolsToString(decode_block
)
313 self
.has_decode_default
= has_decode_default
315 # Override '+' operator: generate a new GenCode object that
316 # concatenates all the individual strings in the operands.
317 def __add__(self
, other
):
319 for cpu
in self
.parser
.cpuModels
:
321 exec_output
[n
] = self
.exec_output
[n
] + other
.exec_output
[n
]
322 return GenCode(self
.parser
,
323 self
.header_output
+ other
.header_output
,
324 self
.decoder_output
+ other
.decoder_output
,
326 self
.decode_block
+ other
.decode_block
,
327 self
.has_decode_default
or other
.has_decode_default
)
329 # Prepend a string (typically a comment) to all the strings.
330 def prepend_all(self
, pre
):
331 self
.header_output
= pre
+ self
.header_output
332 self
.decoder_output
= pre
+ self
.decoder_output
333 self
.decode_block
= pre
+ self
.decode_block
334 for cpu
in self
.parser
.cpuModels
:
335 self
.exec_output
[cpu
.name
] = pre
+ self
.exec_output
[cpu
.name
]
337 # Wrap the decode block in a pair of strings (e.g., 'case foo:'
338 # and 'break;'). Used to build the big nested switch statement.
339 def wrap_decode_block(self
, pre
, post
= ''):
340 self
.decode_block
= pre
+ indent(self
.decode_block
) + post
342 #####################################################################
344 # Bitfield Operator Support
346 #####################################################################
348 bitOp1ArgRE
= re
.compile(r
'<\s*(\w+)\s*:\s*>')
350 bitOpWordRE
= re
.compile(r
'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
351 bitOpExprRE
= re
.compile(r
'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
353 def substBitOps(code
):
354 # first convert single-bit selectors to two-index form
355 # i.e., <n> --> <n:n>
356 code
= bitOp1ArgRE
.sub(r
'<\1:\1>', code
)
357 # simple case: selector applied to ID (name)
358 # i.e., foo<a:b> --> bits(foo, a, b)
359 code
= bitOpWordRE
.sub(r
'bits(\1, \2, \3)', code
)
360 # if selector is applied to expression (ending in ')'),
361 # we need to search backward for matching '('
362 match
= bitOpExprRE
.search(code
)
364 exprEnd
= match
.start()
368 if code
[here
] == '(':
370 elif code
[here
] == ')':
374 sys
.exit("Didn't find '('!")
376 newExpr
= r
'bits(%s, %s, %s)' % (code
[exprStart
:exprEnd
+1],
377 match
.group(1), match
.group(2))
378 code
= code
[:exprStart
] + newExpr
+ code
[match
.end():]
379 match
= bitOpExprRE
.search(code
)
383 #####################################################################
387 # The remaining code is the support for automatically extracting
388 # instruction characteristics from pseudocode.
390 #####################################################################
392 # Force the argument to be a list. Useful for flags, where a caller
393 # can specify a singleton flag or a list of flags. Also usful for
394 # converting tuples to lists so they can be modified.
396 if isinstance(arg
, list):
398 elif isinstance(arg
, tuple):
405 class Operand(object):
406 '''Base class for operand descriptors. An instance of this class
407 (or actually a class derived from this one) represents a specific
408 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
409 derived classes encapsulates the traits of a particular operand
410 type (e.g., "32-bit integer register").'''
412 def buildReadCode(self
, func
= None):
413 subst_dict
= {"name": self
.base_name
,
415 "reg_idx": self
.reg_spec
,
417 if hasattr(self
, 'src_reg_idx'):
418 subst_dict
['op_idx'] = self
.src_reg_idx
419 code
= self
.read_code
% subst_dict
420 return '%s = %s;\n' % (self
.base_name
, code
)
422 def buildWriteCode(self
, func
= None):
423 subst_dict
= {"name": self
.base_name
,
425 "reg_idx": self
.reg_spec
,
427 "final_val": self
.base_name
}
428 if hasattr(self
, 'dest_reg_idx'):
429 subst_dict
['op_idx'] = self
.dest_reg_idx
430 code
= self
.write_code
% subst_dict
435 if (traceData) { traceData->setData(final_val); }
436 }''' % (self
.dflt_ctype
, self
.base_name
, code
)
438 def __init__(self
, parser
, full_name
, ext
, is_src
, is_dest
):
439 self
.full_name
= full_name
442 self
.is_dest
= is_dest
443 # The 'effective extension' (eff_ext) is either the actual
444 # extension, if one was explicitly provided, or the default.
447 elif hasattr(self
, 'dflt_ext'):
448 self
.eff_ext
= self
.dflt_ext
450 if hasattr(self
, 'eff_ext'):
451 self
.ctype
= parser
.operandTypeMap
[self
.eff_ext
]
453 # Finalize additional fields (primarily code fields). This step
454 # is done separately since some of these fields may depend on the
455 # register index enumeration that hasn't been performed yet at the
456 # time of __init__().
458 self
.flags
= self
.getFlags()
459 self
.constructor
= self
.makeConstructor()
460 self
.op_decl
= self
.makeDecl()
463 self
.op_rd
= self
.makeRead()
464 self
.op_src_decl
= self
.makeDecl()
467 self
.op_src_decl
= ''
470 self
.op_wb
= self
.makeWrite()
471 self
.op_dest_decl
= self
.makeDecl()
474 self
.op_dest_decl
= ''
482 def isFloatReg(self
):
488 def isControlReg(self
):
495 return self
.isPCState() and self
.reg_spec
498 # note the empty slice '[:]' gives us a copy of self.flags[0]
499 # instead of a reference to it
500 my_flags
= self
.flags
[0][:]
502 my_flags
+= self
.flags
[1]
504 my_flags
+= self
.flags
[2]
508 # Note that initializations in the declarations are solely
509 # to avoid 'uninitialized variable' errors from the compiler.
510 return self
.ctype
+ ' ' + self
.base_name
+ ' = 0;\n';
512 class IntRegOperand(Operand
):
519 def makeConstructor(self
):
522 c
+= '\n\t_srcRegIdx[%d] = %s;' % \
523 (self
.src_reg_idx
, self
.reg_spec
)
525 c
+= '\n\t_destRegIdx[%d] = %s;' % \
526 (self
.dest_reg_idx
, self
.reg_spec
)
530 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
531 error('Attempt to read integer register as FP')
532 if self
.read_code
!= None:
533 return self
.buildReadCode('readIntRegOperand')
534 int_reg_val
= 'xc->readIntRegOperand(this, %d)' % self
.src_reg_idx
535 return '%s = %s;\n' % (self
.base_name
, int_reg_val
)
538 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
539 error('Attempt to write integer register as FP')
540 if self
.write_code
!= None:
541 return self
.buildWriteCode('setIntRegOperand')
545 xc->setIntRegOperand(this, %d, final_val);\n
546 if (traceData) { traceData->setData(final_val); }
547 }''' % (self
.ctype
, self
.base_name
, self
.dest_reg_idx
)
550 class FloatRegOperand(Operand
):
554 def isFloatReg(self
):
557 def makeConstructor(self
):
560 c
+= '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
561 (self
.src_reg_idx
, self
.reg_spec
)
563 c
+= '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
564 (self
.dest_reg_idx
, self
.reg_spec
)
569 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
570 func
= 'readFloatRegOperand'
572 func
= 'readFloatRegOperandBits'
573 if self
.read_code
!= None:
574 return self
.buildReadCode(func
)
575 return '%s = xc->%s(this, %d);\n' % \
576 (self
.base_name
, func
, self
.src_reg_idx
)
579 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
580 func
= 'setFloatRegOperand'
582 func
= 'setFloatRegOperandBits'
583 if self
.write_code
!= None:
584 return self
.buildWriteCode(func
)
588 xc->%s(this, %d, final_val);\n
589 if (traceData) { traceData->setData(final_val); }
590 }''' % (self
.ctype
, self
.base_name
, func
, self
.dest_reg_idx
)
593 class ControlRegOperand(Operand
):
597 def isControlReg(self
):
600 def makeConstructor(self
):
603 c
+= '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
604 (self
.src_reg_idx
, self
.reg_spec
)
606 c
+= '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
607 (self
.dest_reg_idx
, self
.reg_spec
)
612 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
613 error('Attempt to read control register as FP')
614 if self
.read_code
!= None:
615 return self
.buildReadCode('readMiscRegOperand')
616 return '%s = xc->readMiscRegOperand(this, %s);\n' % \
617 (self
.base_name
, self
.src_reg_idx
)
620 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
621 error('Attempt to write control register as FP')
622 if self
.write_code
!= None:
623 return self
.buildWriteCode('setMiscRegOperand')
624 wb
= 'xc->setMiscRegOperand(this, %s, %s);\n' % \
625 (self
.dest_reg_idx
, self
.base_name
)
626 wb
+= 'if (traceData) { traceData->setData(%s); }' % \
630 class MemOperand(Operand
):
634 def makeConstructor(self
):
638 # Note that initializations in the declarations are solely
639 # to avoid 'uninitialized variable' errors from the compiler.
640 # Declare memory data variable.
641 return '%s %s = 0;\n' % (self
.ctype
, self
.base_name
)
644 if self
.read_code
!= None:
645 return self
.buildReadCode()
649 if self
.write_code
!= None:
650 return self
.buildWriteCode()
653 class PCStateOperand(Operand
):
654 def makeConstructor(self
):
659 # A component of the PC state.
660 return '%s = __parserAutoPCState.%s();\n' % \
661 (self
.base_name
, self
.reg_spec
)
663 # The whole PC state itself.
664 return '%s = xc->pcState();\n' % self
.base_name
668 # A component of the PC state.
669 return '__parserAutoPCState.%s(%s);\n' % \
670 (self
.reg_spec
, self
.base_name
)
672 # The whole PC state itself.
673 return 'xc->pcState(%s);\n' % self
.base_name
676 ctype
= 'TheISA::PCState'
679 return "%s %s;\n" % (ctype
, self
.base_name
)
684 class OperandList(object):
685 '''Find all the operands in the given code block. Returns an operand
686 descriptor list (instance of class OperandList).'''
687 def __init__(self
, parser
, code
):
690 # delete strings and comments so we don't match on operands inside
691 for regEx
in (stringRE
, commentRE
):
692 code
= regEx
.sub('', code
)
693 # search for operands
696 match
= parser
.operandsRE
.search(code
, next_pos
)
698 # no more matches: we're done
701 # regexp groups are operand full name, base, and extension
702 (op_full
, op_base
, op_ext
) = op
703 # if the token following the operand is an assignment, this is
704 # a destination (LHS), else it's a source (RHS)
705 is_dest
= (assignRE
.match(code
, match
.end()) != None)
707 # see if we've already seen this one
708 op_desc
= self
.find_base(op_base
)
710 if op_desc
.ext
!= op_ext
:
711 error('Inconsistent extensions for operand %s' % \
713 op_desc
.is_src
= op_desc
.is_src
or is_src
714 op_desc
.is_dest
= op_desc
.is_dest
or is_dest
716 # new operand: create new descriptor
717 op_desc
= parser
.operandNameMap
[op_base
](parser
,
718 op_full
, op_ext
, is_src
, is_dest
)
720 # start next search after end of current match
721 next_pos
= match
.end()
723 # enumerate source & dest register operands... used in building
727 self
.numFPDestRegs
= 0
728 self
.numIntDestRegs
= 0
729 self
.memOperand
= None
730 for op_desc
in self
.items
:
733 op_desc
.src_reg_idx
= self
.numSrcRegs
736 op_desc
.dest_reg_idx
= self
.numDestRegs
737 self
.numDestRegs
+= 1
738 if op_desc
.isFloatReg():
739 self
.numFPDestRegs
+= 1
740 elif op_desc
.isIntReg():
741 self
.numIntDestRegs
+= 1
742 elif op_desc
.isMem():
744 error("Code block has more than one memory operand.")
745 self
.memOperand
= op_desc
746 if parser
.maxInstSrcRegs
< self
.numSrcRegs
:
747 parser
.maxInstSrcRegs
= self
.numSrcRegs
748 if parser
.maxInstDestRegs
< self
.numDestRegs
:
749 parser
.maxInstDestRegs
= self
.numDestRegs
750 # now make a final pass to finalize op_desc fields that may depend
751 # on the register enumeration
752 for op_desc
in self
.items
:
756 return len(self
.items
)
758 def __getitem__(self
, index
):
759 return self
.items
[index
]
761 def append(self
, op_desc
):
762 self
.items
.append(op_desc
)
763 self
.bases
[op_desc
.base_name
] = op_desc
765 def find_base(self
, base_name
):
766 # like self.bases[base_name], but returns None if not found
767 # (rather than raising exception)
768 return self
.bases
.get(base_name
)
770 # internal helper function for concat[Some]Attr{Strings|Lists}
771 def __internalConcatAttrs(self
, attr_name
, filter, result
):
772 for op_desc
in self
.items
:
774 result
+= getattr(op_desc
, attr_name
)
777 # return a single string that is the concatenation of the (string)
778 # values of the specified attribute for all operands
779 def concatAttrStrings(self
, attr_name
):
780 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, '')
782 # like concatAttrStrings, but only include the values for the operands
783 # for which the provided filter function returns true
784 def concatSomeAttrStrings(self
, filter, attr_name
):
785 return self
.__internalConcatAttrs
(attr_name
, filter, '')
787 # return a single list that is the concatenation of the (list)
788 # values of the specified attribute for all operands
789 def concatAttrLists(self
, attr_name
):
790 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, [])
792 # like concatAttrLists, but only include the values for the operands
793 # for which the provided filter function returns true
794 def concatSomeAttrLists(self
, filter, attr_name
):
795 return self
.__internalConcatAttrs
(attr_name
, filter, [])
798 self
.items
.sort(lambda a
, b
: a
.sort_pri
- b
.sort_pri
)
800 class SubOperandList(OperandList
):
801 '''Find all the operands in the given code block. Returns an operand
802 descriptor list (instance of class OperandList).'''
803 def __init__(self
, parser
, code
, master_list
):
806 # delete strings and comments so we don't match on operands inside
807 for regEx
in (stringRE
, commentRE
):
808 code
= regEx
.sub('', code
)
809 # search for operands
812 match
= parser
.operandsRE
.search(code
, next_pos
)
814 # no more matches: we're done
817 # regexp groups are operand full name, base, and extension
818 (op_full
, op_base
, op_ext
) = op
819 # find this op in the master list
820 op_desc
= master_list
.find_base(op_base
)
822 error('Found operand %s which is not in the master list!' \
823 ' This is an internal error' % op_base
)
825 # See if we've already found this operand
826 op_desc
= self
.find_base(op_base
)
828 # if not, add a reference to it to this sub list
829 self
.append(master_list
.bases
[op_base
])
831 # start next search after end of current match
832 next_pos
= match
.end()
834 self
.memOperand
= None
835 # Whether the whole PC needs to be read so parts of it can be accessed
837 # Whether the whole PC needs to be written after parts of it were
840 # Whether this instruction manipulates the whole PC or parts of it.
841 # Mixing the two is a bad idea and flagged as an error.
843 for op_desc
in self
.items
:
844 if op_desc
.isPCPart():
848 if op_desc
.isPCState():
849 if self
.pcPart
is not None:
850 if self
.pcPart
and not op_desc
.isPCPart() or \
851 not self
.pcPart
and op_desc
.isPCPart():
852 error("Mixed whole and partial PC state operands.")
853 self
.pcPart
= op_desc
.isPCPart()
856 error("Code block has more than one memory operand.")
857 self
.memOperand
= op_desc
859 # Regular expression object to match C++ strings
860 stringRE
= re
.compile(r
'"([^"\\]|\\.)*"')
862 # Regular expression object to match C++ comments
863 # (used in findOperands())
864 commentRE
= re
.compile(r
'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
865 re
.DOTALL | re
.MULTILINE
)
867 # Regular expression object to match assignment statements
868 # (used in findOperands())
869 assignRE
= re
.compile(r
'\s*=(?!=)', re
.MULTILINE
)
871 def makeFlagConstructor(flag_list
):
872 if len(flag_list
) == 0:
874 # filter out repeated flags
877 while i
< len(flag_list
):
878 if flag_list
[i
] == flag_list
[i
-1]:
884 code
= pre
+ string
.join(flag_list
, post
+ pre
) + post
887 # Assume all instruction flags are of the form 'IsFoo'
888 instFlagRE
= re
.compile(r
'Is.*')
890 # OpClass constants end in 'Op' except No_OpClass
891 opClassRE
= re
.compile(r
'.*Op|No_OpClass')
893 class InstObjParams(object):
894 def __init__(self
, parser
, mnem
, class_name
, base_class
= '',
895 snippets
= {}, opt_args
= []):
897 self
.class_name
= class_name
898 self
.base_class
= base_class
899 if not isinstance(snippets
, dict):
900 snippets
= {'code' : snippets
}
901 compositeCode
= ' '.join(map(str, snippets
.values()))
902 self
.snippets
= snippets
904 self
.operands
= OperandList(parser
, compositeCode
)
905 self
.constructor
= self
.operands
.concatAttrStrings('constructor')
906 self
.constructor
+= \
907 '\n\t_numSrcRegs = %d;' % self
.operands
.numSrcRegs
908 self
.constructor
+= \
909 '\n\t_numDestRegs = %d;' % self
.operands
.numDestRegs
910 self
.constructor
+= \
911 '\n\t_numFPDestRegs = %d;' % self
.operands
.numFPDestRegs
912 self
.constructor
+= \
913 '\n\t_numIntDestRegs = %d;' % self
.operands
.numIntDestRegs
914 self
.flags
= self
.operands
.concatAttrLists('flags')
916 # Make a basic guess on the operand class (function unit type).
917 # These are good enough for most cases, and can be overridden
919 if 'IsStore' in self
.flags
:
920 self
.op_class
= 'MemWriteOp'
921 elif 'IsLoad' in self
.flags
or 'IsPrefetch' in self
.flags
:
922 self
.op_class
= 'MemReadOp'
923 elif 'IsFloating' in self
.flags
:
924 self
.op_class
= 'FloatAddOp'
926 self
.op_class
= 'IntAluOp'
928 # Optional arguments are assumed to be either StaticInst flags
929 # or an OpClass value. To avoid having to import a complete
930 # list of these values to match against, we do it ad-hoc
933 if instFlagRE
.match(oa
):
934 self
.flags
.append(oa
)
935 elif opClassRE
.match(oa
):
938 error('InstObjParams: optional arg "%s" not recognized '
939 'as StaticInst::Flag or OpClass.' % oa
)
941 # add flag initialization to contructor here to include
942 # any flags added via opt_args
943 self
.constructor
+= makeFlagConstructor(self
.flags
)
945 # if 'IsFloating' is set, add call to the FP enable check
946 # function (which should be provided by isa_desc via a declare)
947 if 'IsFloating' in self
.flags
:
948 self
.fp_enable_check
= 'fault = checkFpEnableFault(xc);'
950 self
.fp_enable_check
= ''
953 # Stack: a simple stack object. Used for both formats (formatStack)
954 # and default cases (defaultStack). Simply wraps a list to give more
955 # stack-like syntax and enable initialization with an argument list
956 # (as opposed to an argument that's a list).
959 def __init__(self
, *items
):
960 list.__init
__(self
, items
)
962 def push(self
, item
):
968 #######################
970 # Output file template
975 * DO NOT EDIT THIS FILE!!!
977 * It was automatically generated from the ISA description in %(filename)s
984 namespace %(namespace)s {
988 } // namespace %(namespace)s
993 max_inst_regs_template
= '''
995 * DO NOT EDIT THIS FILE!!!
997 * It was automatically generated from the ISA description in %(filename)s
1000 namespace %(namespace)s {
1002 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
1003 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
1005 } // namespace %(namespace)s
1009 class ISAParser(Grammar
):
1010 def __init__(self
, output_dir
, cpu_models
):
1011 super(ISAParser
, self
).__init
__()
1012 self
.output_dir
= output_dir
1014 self
.cpuModels
= cpu_models
1016 # variable to hold templates
1017 self
.templateMap
= {}
1019 # This dictionary maps format name strings to Format objects.
1023 self
.formatStack
= Stack(NoFormat())
1025 # The default case stack.
1026 self
.defaultStack
= Stack(None)
1028 # Stack that tracks current file and line number. Each
1029 # element is a tuple (filename, lineno) that records the
1030 # *current* filename and the line number in the *previous*
1031 # file where it was included.
1032 self
.fileNameStack
= Stack()
1034 symbols
= ('makeList', 're', 'string')
1035 self
.exportContext
= dict([(s
, eval(s
)) for s
in symbols
])
1037 self
.maxInstSrcRegs
= 0
1038 self
.maxInstDestRegs
= 0
1040 #####################################################################
1044 # The PLY lexer module takes two things as input:
1045 # - A list of token names (the string list 'tokens')
1046 # - A regular expression describing a match for each token. The
1047 # regexp for token FOO can be provided in two ways:
1048 # - as a string variable named t_FOO
1049 # - as the doc string for a function named t_FOO. In this case,
1050 # the function is also executed, allowing an action to be
1051 # associated with each token match.
1053 #####################################################################
1055 # Reserved words. These are listed separately as they are matched
1056 # using the same regexp as generic IDs, but distinguished in the
1057 # t_ID() function. The PLY documentation suggests this approach.
1059 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
1060 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
1061 'OUTPUT', 'SIGNED', 'TEMPLATE'
1064 # List of tokens. The lex module requires this.
1065 tokens
= reserved
+ (
1078 # ( ) [ ] { } < > , ; . : :: *
1080 'LBRACKET', 'RBRACKET',
1082 'LESS', 'GREATER', 'EQUALS',
1083 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON',
1086 # C preprocessor directives
1089 # The following are matched but never returned. commented out to
1090 # suppress PLY warning
1098 # Regular expressions for token matching
1115 # Identifiers and reserved words
1118 reserved_map
[r
.lower()] = r
1122 t
.type = self
.reserved_map
.get(t
.value
, 'ID')
1126 def t_INTLIT(self
, t
):
1127 r
'-?(0x[\da-fA-F]+)|\d+'
1129 t
.value
= int(t
.value
,0)
1131 error(t
, 'Integer value "%s" too large' % t
.value
)
1135 # String literal. Note that these use only single quotes, and
1136 # can span multiple lines.
1137 def t_STRLIT(self
, t
):
1140 t
.value
= t
.value
[1:-1]
1141 t
.lexer
.lineno
+= t
.value
.count('\n')
1145 # "Code literal"... like a string literal, but delimiters are
1146 # '{{' and '}}' so they get formatted nicely under emacs c-mode
1147 def t_CODELIT(self
, t
):
1148 r
"(?m)\{\{([^\}]|}(?!\}))+\}\}"
1150 t
.value
= t
.value
[2:-2]
1151 t
.lexer
.lineno
+= t
.value
.count('\n')
1154 def t_CPPDIRECTIVE(self
, t
):
1156 t
.lexer
.lineno
+= t
.value
.count('\n')
1159 def t_NEWFILE(self
, t
):
1160 r
'^\#\#newfile\s+"[^"]*"'
1161 self
.fileNameStack
.push((t
.value
[11:-1], t
.lexer
.lineno
))
1164 def t_ENDFILE(self
, t
):
1166 (old_filename
, t
.lexer
.lineno
) = self
.fileNameStack
.pop()
1169 # The functions t_NEWLINE, t_ignore, and t_error are
1170 # special for the lex module.
1174 def t_NEWLINE(self
, t
):
1176 t
.lexer
.lineno
+= t
.value
.count('\n')
1179 def t_comment(self
, t
):
1182 # Completely ignored characters
1183 t_ignore
= ' \t\x0c'
1186 def t_error(self
, t
):
1187 error(t
, "illegal character '%s'" % t
.value
[0])
1190 #####################################################################
1194 # Every function whose name starts with 'p_' defines a grammar
1195 # rule. The rule is encoded in the function's doc string, while
1196 # the function body provides the action taken when the rule is
1197 # matched. The argument to each function is a list of the values
1198 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the
1199 # symbols on the RHS. For tokens, the value is copied from the
1200 # t.value attribute provided by the lexer. For non-terminals, the
1201 # value is assigned by the producing rule; i.e., the job of the
1202 # grammar rule function is to set the value for the non-terminal
1203 # on the LHS (by assigning to t[0]).
1204 #####################################################################
1206 # The LHS of the first grammar rule is used as the start symbol
1207 # (in this case, 'specification'). Note that this rule enforces
1208 # that there will be exactly one namespace declaration, with 0 or
1209 # more global defs/decls before and after it. The defs & decls
1210 # before the namespace decl will be outside the namespace; those
1211 # after will be inside. The decoder function is always inside the
1213 def p_specification(self
, t
):
1214 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
1217 namespace
= isa_name
+ "Inst"
1218 # wrap the decode block as a function definition
1219 t
[4].wrap_decode_block('''
1221 %(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst)
1223 using namespace %(namespace)s;
1225 # both the latter output blocks and the decode block are in
1227 namespace_code
= t
[3] + t
[4]
1228 # pass it all back to the caller of yacc.parse()
1229 t
[0] = (isa_name
, namespace
, global_code
, namespace_code
)
1231 # ISA name declaration looks like "namespace <foo>;"
1232 def p_name_decl(self
, t
):
1233 'name_decl : NAMESPACE ID SEMI'
1236 # 'opt_defs_and_outputs' is a possibly empty sequence of
1237 # def and/or output statements.
1238 def p_opt_defs_and_outputs_0(self
, t
):
1239 'opt_defs_and_outputs : empty'
1240 t
[0] = GenCode(self
)
1242 def p_opt_defs_and_outputs_1(self
, t
):
1243 'opt_defs_and_outputs : defs_and_outputs'
1246 def p_defs_and_outputs_0(self
, t
):
1247 'defs_and_outputs : def_or_output'
1250 def p_defs_and_outputs_1(self
, t
):
1251 'defs_and_outputs : defs_and_outputs def_or_output'
1254 # The list of possible definition/output statements.
1255 def p_def_or_output(self
, t
):
1256 '''def_or_output : def_format
1258 | def_bitfield_struct
1268 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1269 # directly to the appropriate output section.
1271 # Massage output block by substituting in template definitions and
1272 # bit operators. We handle '%'s embedded in the string that don't
1273 # indicate template substitutions (or CPU-specific symbols, which
1274 # get handled in GenCode) by doubling them first so that the
1275 # format operation will reduce them back to single '%'s.
1276 def process_output(self
, s
):
1277 s
= self
.protectNonSubstPercents(s
)
1278 # protects cpu-specific symbols too
1279 s
= self
.protectCpuSymbols(s
)
1280 return substBitOps(s
% self
.templateMap
)
1282 def p_output_header(self
, t
):
1283 'output_header : OUTPUT HEADER CODELIT SEMI'
1284 t
[0] = GenCode(self
, header_output
= self
.process_output(t
[3]))
1286 def p_output_decoder(self
, t
):
1287 'output_decoder : OUTPUT DECODER CODELIT SEMI'
1288 t
[0] = GenCode(self
, decoder_output
= self
.process_output(t
[3]))
1290 def p_output_exec(self
, t
):
1291 'output_exec : OUTPUT EXEC CODELIT SEMI'
1292 t
[0] = GenCode(self
, exec_output
= self
.process_output(t
[3]))
1294 # global let blocks 'let {{...}}' (Python code blocks) are
1295 # executed directly when seen. Note that these execute in a
1296 # special variable context 'exportContext' to prevent the code
1297 # from polluting this script's namespace.
1298 def p_global_let(self
, t
):
1299 'global_let : LET CODELIT SEMI'
1300 self
.updateExportContext()
1301 self
.exportContext
["header_output"] = ''
1302 self
.exportContext
["decoder_output"] = ''
1303 self
.exportContext
["exec_output"] = ''
1304 self
.exportContext
["decode_block"] = ''
1306 exec fixPythonIndentation(t
[2]) in self
.exportContext
1307 except Exception, exc
:
1310 error(t
, 'error: %s in global let block "%s".' % (exc
, t
[2]))
1311 t
[0] = GenCode(self
,
1312 header_output
=self
.exportContext
["header_output"],
1313 decoder_output
=self
.exportContext
["decoder_output"],
1314 exec_output
=self
.exportContext
["exec_output"],
1315 decode_block
=self
.exportContext
["decode_block"])
1317 # Define the mapping from operand type extensions to C++ types and
1318 # bit widths (stored in operandTypeMap).
1319 def p_def_operand_types(self
, t
):
1320 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1322 self
.operandTypeMap
= eval('{' + t
[3] + '}')
1323 except Exception, exc
:
1327 'error: %s in def operand_types block "%s".' % (exc
, t
[3]))
1328 t
[0] = GenCode(self
) # contributes nothing to the output C++ file
1330 # Define the mapping from operand names to operand classes and
1331 # other traits. Stored in operandNameMap.
1332 def p_def_operands(self
, t
):
1333 'def_operands : DEF OPERANDS CODELIT SEMI'
1334 if not hasattr(self
, 'operandTypeMap'):
1335 error(t
, 'error: operand types must be defined before operands')
1337 user_dict
= eval('{' + t
[3] + '}', self
.exportContext
)
1338 except Exception, exc
:
1341 error(t
, 'error: %s in def operands block "%s".' % (exc
, t
[3]))
1342 self
.buildOperandNameMap(user_dict
, t
.lexer
.lineno
)
1343 t
[0] = GenCode(self
) # contributes nothing to the output C++ file
1345 # A bitfield definition looks like:
1346 # 'def [signed] bitfield <ID> [<first>:<last>]'
1347 # This generates a preprocessor macro in the output file.
1348 def p_def_bitfield_0(self
, t
):
1349 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
1350 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[8])
1351 if (t
[2] == 'signed'):
1352 expr
= 'sext<%d>(%s)' % (t
[6] - t
[8] + 1, expr
)
1353 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1354 t
[0] = GenCode(self
, header_output
=hash_define
)
1356 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
1357 def p_def_bitfield_1(self
, t
):
1358 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
1359 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[6])
1360 if (t
[2] == 'signed'):
1361 expr
= 'sext<%d>(%s)' % (1, expr
)
1362 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1363 t
[0] = GenCode(self
, header_output
=hash_define
)
1365 # alternate form for structure member: 'def bitfield <ID> <ID>'
1366 def p_def_bitfield_struct(self
, t
):
1367 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI'
1369 error(t
, 'error: structure bitfields are always unsigned.')
1370 expr
= 'machInst.%s' % t
[5]
1371 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1372 t
[0] = GenCode(self
, header_output
=hash_define
)
1374 def p_id_with_dot_0(self
, t
):
1378 def p_id_with_dot_1(self
, t
):
1379 'id_with_dot : ID DOT id_with_dot'
1380 t
[0] = t
[1] + t
[2] + t
[3]
1382 def p_opt_signed_0(self
, t
):
1383 'opt_signed : SIGNED'
1386 def p_opt_signed_1(self
, t
):
1387 'opt_signed : empty'
1390 def p_def_template(self
, t
):
1391 'def_template : DEF TEMPLATE ID CODELIT SEMI'
1392 self
.templateMap
[t
[3]] = Template(self
, t
[4])
1393 t
[0] = GenCode(self
)
1395 # An instruction format definition looks like
1396 # "def format <fmt>(<params>) {{...}};"
1397 def p_def_format(self
, t
):
1398 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1399 (id, params
, code
) = (t
[3], t
[5], t
[7])
1400 self
.defFormat(id, params
, code
, t
.lexer
.lineno
)
1401 t
[0] = GenCode(self
)
1403 # The formal parameter list for an instruction format is a
1404 # possibly empty list of comma-separated parameters. Positional
1405 # (standard, non-keyword) parameters must come first, followed by
1406 # keyword parameters, followed by a '*foo' parameter that gets
1407 # excess positional arguments (as in Python). Each of these three
1408 # parameter categories is optional.
1410 # Note that we do not support the '**foo' parameter for collecting
1411 # otherwise undefined keyword args. Otherwise the parameter list
1412 # is (I believe) identical to what is supported in Python.
1414 # The param list generates a tuple, where the first element is a
1415 # list of the positional params and the second element is a dict
1416 # containing the keyword params.
1417 def p_param_list_0(self
, t
):
1418 'param_list : positional_param_list COMMA nonpositional_param_list'
1421 def p_param_list_1(self
, t
):
1422 '''param_list : positional_param_list
1423 | nonpositional_param_list'''
1426 def p_positional_param_list_0(self
, t
):
1427 'positional_param_list : empty'
1430 def p_positional_param_list_1(self
, t
):
1431 'positional_param_list : ID'
1434 def p_positional_param_list_2(self
, t
):
1435 'positional_param_list : positional_param_list COMMA ID'
1436 t
[0] = t
[1] + [t
[3]]
1438 def p_nonpositional_param_list_0(self
, t
):
1439 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
1442 def p_nonpositional_param_list_1(self
, t
):
1443 '''nonpositional_param_list : keyword_param_list
1444 | excess_args_param'''
1447 def p_keyword_param_list_0(self
, t
):
1448 'keyword_param_list : keyword_param'
1451 def p_keyword_param_list_1(self
, t
):
1452 'keyword_param_list : keyword_param_list COMMA keyword_param'
1453 t
[0] = t
[1] + [t
[3]]
1455 def p_keyword_param(self
, t
):
1456 'keyword_param : ID EQUALS expr'
1457 t
[0] = t
[1] + ' = ' + t
[3].__repr
__()
1459 def p_excess_args_param(self
, t
):
1460 'excess_args_param : ASTERISK ID'
1461 # Just concatenate them: '*ID'. Wrap in list to be consistent
1462 # with positional_param_list and keyword_param_list.
1463 t
[0] = [t
[1] + t
[2]]
1465 # End of format definition-related rules.
1469 # A decode block looks like:
1470 # decode <field1> [, <field2>]* [default <inst>] { ... }
1472 def p_decode_block(self
, t
):
1473 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
1474 default_defaults
= self
.defaultStack
.pop()
1476 # use the "default defaults" only if there was no explicit
1477 # default statement in decode_stmt_list
1478 if not codeObj
.has_decode_default
:
1479 codeObj
+= default_defaults
1480 codeObj
.wrap_decode_block('switch (%s) {\n' % t
[2], '}\n')
1483 # The opt_default statement serves only to push the "default
1484 # defaults" onto defaultStack. This value will be used by nested
1485 # decode blocks, and used and popped off when the current
1486 # decode_block is processed (in p_decode_block() above).
1487 def p_opt_default_0(self
, t
):
1488 'opt_default : empty'
1489 # no default specified: reuse the one currently at the top of
1491 self
.defaultStack
.push(self
.defaultStack
.top())
1492 # no meaningful value returned
1495 def p_opt_default_1(self
, t
):
1496 'opt_default : DEFAULT inst'
1497 # push the new default
1499 codeObj
.wrap_decode_block('\ndefault:\n', 'break;\n')
1500 self
.defaultStack
.push(codeObj
)
1501 # no meaningful value returned
1504 def p_decode_stmt_list_0(self
, t
):
1505 'decode_stmt_list : decode_stmt'
1508 def p_decode_stmt_list_1(self
, t
):
1509 'decode_stmt_list : decode_stmt decode_stmt_list'
1510 if (t
[1].has_decode_default
and t
[2].has_decode_default
):
1511 error(t
, 'Two default cases in decode block')
1515 # Decode statement rules
1517 # There are four types of statements allowed in a decode block:
1518 # 1. Format blocks 'format <foo> { ... }'
1519 # 2. Nested decode blocks
1520 # 3. Instruction definitions.
1521 # 4. C preprocessor directives.
1524 # Preprocessor directives found in a decode statement list are
1525 # passed through to the output, replicated to all of the output
1526 # code streams. This works well for ifdefs, so we can ifdef out
1527 # both the declarations and the decode cases generated by an
1528 # instruction definition. Handling them as part of the grammar
1529 # makes it easy to keep them in the right place with respect to
1530 # the code generated by the other statements.
1531 def p_decode_stmt_cpp(self
, t
):
1532 'decode_stmt : CPPDIRECTIVE'
1533 t
[0] = GenCode(self
, t
[1], t
[1], t
[1], t
[1])
1535 # A format block 'format <foo> { ... }' sets the default
1536 # instruction format used to handle instruction definitions inside
1537 # the block. This format can be overridden by using an explicit
1538 # format on the instruction definition or with a nested format
1540 def p_decode_stmt_format(self
, t
):
1541 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
1542 # The format will be pushed on the stack when 'push_format_id'
1543 # is processed (see below). Once the parser has recognized
1544 # the full production (though the right brace), we're done
1545 # with the format, so now we can pop it.
1546 self
.formatStack
.pop()
1549 # This rule exists so we can set the current format (& push the
1550 # stack) when we recognize the format name part of the format
1552 def p_push_format_id(self
, t
):
1553 'push_format_id : ID'
1555 self
.formatStack
.push(self
.formatMap
[t
[1]])
1556 t
[0] = ('', '// format %s' % t
[1])
1558 error(t
, 'instruction format "%s" not defined.' % t
[1])
1560 # Nested decode block: if the value of the current field matches
1561 # the specified constant, do a nested decode on some other field.
1562 def p_decode_stmt_decode(self
, t
):
1563 'decode_stmt : case_label COLON decode_block'
1566 # just wrap the decoding code from the block as a case in the
1567 # outer switch statement.
1568 codeObj
.wrap_decode_block('\n%s:\n' % label
)
1569 codeObj
.has_decode_default
= (label
== 'default')
1572 # Instruction definition (finally!).
1573 def p_decode_stmt_inst(self
, t
):
1574 'decode_stmt : case_label COLON inst SEMI'
1577 codeObj
.wrap_decode_block('\n%s:' % label
, 'break;\n')
1578 codeObj
.has_decode_default
= (label
== 'default')
1581 # The case label is either a list of one or more constants or
1583 def p_case_label_0(self
, t
):
1584 'case_label : intlit_list'
1585 def make_case(intlit
):
1587 return 'case ULL(%#x)' % intlit
1589 return 'case %#x' % intlit
1590 t
[0] = ': '.join(map(make_case
, t
[1]))
1592 def p_case_label_1(self
, t
):
1593 'case_label : DEFAULT'
1597 # The constant list for a decode case label must be non-empty, but
1598 # may have one or more comma-separated integer literals in it.
1600 def p_intlit_list_0(self
, t
):
1601 'intlit_list : INTLIT'
1604 def p_intlit_list_1(self
, t
):
1605 'intlit_list : intlit_list COMMA INTLIT'
1609 # Define an instruction using the current instruction format
1610 # (specified by an enclosing format block).
1611 # "<mnemonic>(<args>)"
1612 def p_inst_0(self
, t
):
1613 'inst : ID LPAREN arg_list RPAREN'
1614 # Pass the ID and arg list to the current format class to deal with.
1615 currentFormat
= self
.formatStack
.top()
1616 codeObj
= currentFormat
.defineInst(self
, t
[1], t
[3], t
.lexer
.lineno
)
1617 args
= ','.join(map(str, t
[3]))
1618 args
= re
.sub('(?m)^', '//', args
)
1619 args
= re
.sub('^//', '', args
)
1620 comment
= '\n// %s::%s(%s)\n' % (currentFormat
.id, t
[1], args
)
1621 codeObj
.prepend_all(comment
)
1624 # Define an instruction using an explicitly specified format:
1625 # "<fmt>::<mnemonic>(<args>)"
1626 def p_inst_1(self
, t
):
1627 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1629 format
= self
.formatMap
[t
[1]]
1631 error(t
, 'instruction format "%s" not defined.' % t
[1])
1633 codeObj
= format
.defineInst(self
, t
[3], t
[5], t
.lexer
.lineno
)
1634 comment
= '\n// %s::%s(%s)\n' % (t
[1], t
[3], t
[5])
1635 codeObj
.prepend_all(comment
)
1638 # The arg list generates a tuple, where the first element is a
1639 # list of the positional args and the second element is a dict
1640 # containing the keyword args.
1641 def p_arg_list_0(self
, t
):
1642 'arg_list : positional_arg_list COMMA keyword_arg_list'
1643 t
[0] = ( t
[1], t
[3] )
1645 def p_arg_list_1(self
, t
):
1646 'arg_list : positional_arg_list'
1649 def p_arg_list_2(self
, t
):
1650 'arg_list : keyword_arg_list'
1653 def p_positional_arg_list_0(self
, t
):
1654 'positional_arg_list : empty'
1657 def p_positional_arg_list_1(self
, t
):
1658 'positional_arg_list : expr'
1661 def p_positional_arg_list_2(self
, t
):
1662 'positional_arg_list : positional_arg_list COMMA expr'
1663 t
[0] = t
[1] + [t
[3]]
1665 def p_keyword_arg_list_0(self
, t
):
1666 'keyword_arg_list : keyword_arg'
1669 def p_keyword_arg_list_1(self
, t
):
1670 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
1674 def p_keyword_arg(self
, t
):
1675 'keyword_arg : ID EQUALS expr'
1676 t
[0] = { t
[1] : t
[3] }
1679 # Basic expressions. These constitute the argument values of
1680 # "function calls" (i.e. instruction definitions in the decode
1681 # block) and default values for formal parameters of format
1684 # Right now, these are either strings, integers, or (recursively)
1685 # lists of exprs (using Python square-bracket list syntax). Note
1686 # that bare identifiers are trated as string constants here (since
1687 # there isn't really a variable namespace to refer to).
1689 def p_expr_0(self
, t
):
1696 def p_expr_1(self
, t
):
1697 '''expr : LBRACKET list_expr RBRACKET'''
1700 def p_list_expr_0(self
, t
):
1704 def p_list_expr_1(self
, t
):
1705 'list_expr : list_expr COMMA expr'
1706 t
[0] = t
[1] + [t
[3]]
1708 def p_list_expr_2(self
, t
):
1713 # Empty production... use in other rules for readability.
1715 def p_empty(self
, t
):
1719 # Parse error handler. Note that the argument here is the
1720 # offending *token*, not a grammar symbol (hence the need to use
1722 def p_error(self
, t
):
1724 error(t
, "syntax error at '%s'" % t
.value
)
1726 error("unknown syntax error")
1728 # END OF GRAMMAR RULES
1730 def updateExportContext(self
):
1732 # create a continuation that allows us to grab the current parser
1733 def wrapInstObjParams(*args
):
1734 return InstObjParams(self
, *args
)
1735 self
.exportContext
['InstObjParams'] = wrapInstObjParams
1736 self
.exportContext
.update(self
.templateMap
)
1738 def defFormat(self
, id, params
, code
, lineno
):
1739 '''Define a new format'''
1741 # make sure we haven't already defined this one
1742 if id in self
.formatMap
:
1743 error(lineno
, 'format %s redefined.' % id)
1745 # create new object and store in global map
1746 self
.formatMap
[id] = Format(id, params
, code
)
1748 def expandCpuSymbolsToDict(self
, template
):
1749 '''Expand template with CPU-specific references into a
1750 dictionary with an entry for each CPU model name. The entry
1751 key is the model name and the corresponding value is the
1752 template with the CPU-specific refs substituted for that
1755 # Protect '%'s that don't go with CPU-specific terms
1756 t
= re
.sub(r
'%(?!\(CPU_)', '%%', template
)
1758 for cpu
in self
.cpuModels
:
1759 result
[cpu
.name
] = t
% cpu
.strings
1762 def expandCpuSymbolsToString(self
, template
):
1763 '''*If* the template has CPU-specific references, return a
1764 single string containing a copy of the template for each CPU
1765 model with the corresponding values substituted in. If the
1766 template has no CPU-specific references, it is returned
1769 if template
.find('%(CPU_') != -1:
1770 return reduce(lambda x
,y
: x
+y
,
1771 self
.expandCpuSymbolsToDict(template
).values())
1775 def protectCpuSymbols(self
, template
):
1776 '''Protect CPU-specific references by doubling the
1777 corresponding '%'s (in preparation for substituting a different
1778 set of references into the template).'''
1780 return re
.sub(r
'%(?=\(CPU_)', '%%', template
)
1782 def protectNonSubstPercents(self
, s
):
1783 '''Protect any non-dict-substitution '%'s in a format string
1784 (i.e. those not followed by '(')'''
1786 return re
.sub(r
'%(?!\()', '%%', s
)
1788 def buildOperandNameMap(self
, user_dict
, lineno
):
1790 for op_name
, val
in user_dict
.iteritems():
1791 base_cls_name
, dflt_ext
, reg_spec
, flags
, sort_pri
= val
[:5]
1802 'error: too many attributes for operand "%s"' %
1805 # Canonical flag structure is a triple of lists, where each list
1806 # indicates the set of flags implied by this operand always, when
1807 # used as a source, and when used as a dest, respectively.
1808 # For simplicity this can be initialized using a variety of fairly
1809 # obvious shortcuts; we convert these to canonical form here.
1811 # no flags specified (e.g., 'None')
1812 flags
= ( [], [], [] )
1813 elif isinstance(flags
, str):
1814 # a single flag: assumed to be unconditional
1815 flags
= ( [ flags
], [], [] )
1816 elif isinstance(flags
, list):
1817 # a list of flags: also assumed to be unconditional
1818 flags
= ( flags
, [], [] )
1819 elif isinstance(flags
, tuple):
1820 # it's a tuple: it should be a triple,
1821 # but each item could be a single string or a list
1822 (uncond_flags
, src_flags
, dest_flags
) = flags
1823 flags
= (makeList(uncond_flags
),
1824 makeList(src_flags
), makeList(dest_flags
))
1825 # Accumulate attributes of new operand class in tmp_dict
1827 attrList
= ['reg_spec', 'flags', 'sort_pri',
1828 'read_code', 'write_code']
1830 dflt_ctype
= self
.operandTypeMap
[dflt_ext
]
1831 attrList
.extend(['dflt_ctype', 'dflt_ext'])
1832 for attr
in attrList
:
1833 tmp_dict
[attr
] = eval(attr
)
1834 tmp_dict
['base_name'] = op_name
1835 # New class name will be e.g. "IntReg_Ra"
1836 cls_name
= base_cls_name
+ '_' + op_name
1837 # Evaluate string arg to get class object. Note that the
1838 # actual base class for "IntReg" is "IntRegOperand", i.e. we
1839 # have to append "Operand".
1841 base_cls
= eval(base_cls_name
+ 'Operand')
1844 'error: unknown operand base class "%s"' % base_cls_name
)
1845 # The following statement creates a new class called
1846 # <cls_name> as a subclass of <base_cls> with the attributes
1847 # in tmp_dict, just as if we evaluated a class declaration.
1848 operand_name
[op_name
] = type(cls_name
, (base_cls
,), tmp_dict
)
1850 self
.operandNameMap
= operand_name
1852 # Define operand variables.
1853 operands
= user_dict
.keys()
1855 operandsREString
= (r
'''
1856 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
1857 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
1858 (?![\w\.]) # neg. lookahead assertion: prevent partial matches
1860 % string
.join(operands
, '|'))
1862 self
.operandsRE
= re
.compile(operandsREString
, re
.MULTILINE|re
.VERBOSE
)
1864 # Same as operandsREString, but extension is mandatory, and only two
1865 # groups are returned (base and ext, not full name as above).
1866 # Used for subtituting '_' for '.' to make C++ identifiers.
1867 operandsWithExtREString
= (r
'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
1868 % string
.join(operands
, '|'))
1870 self
.operandsWithExtRE
= \
1871 re
.compile(operandsWithExtREString
, re
.MULTILINE
)
1873 def substMungedOpNames(self
, code
):
1874 '''Munge operand names in code string to make legal C++
1875 variable names. This means getting rid of the type extension
1876 if any. Will match base_name attribute of Operand object.)'''
1877 return self
.operandsWithExtRE
.sub(r
'\1', code
)
1879 def mungeSnippet(self
, s
):
1880 '''Fix up code snippets for final substitution in templates.'''
1881 if isinstance(s
, str):
1882 return self
.substMungedOpNames(substBitOps(s
))
1886 def update_if_needed(self
, file, contents
):
1887 '''Update the output file only if the new contents are
1888 different from the current contents. Minimizes the files that
1889 need to be rebuilt after minor changes.'''
1891 file = os
.path
.join(self
.output_dir
, file)
1893 if os
.access(file, os
.R_OK
):
1895 old_contents
= f
.read()
1897 if contents
!= old_contents
:
1898 os
.remove(file) # in case it's write-protected
1901 print 'File', file, 'is unchanged'
1909 # This regular expression matches '##include' directives
1910 includeRE
= re
.compile(r
'^\s*##include\s+"(?P<filename>[^"]*)".*$',
1913 def replace_include(self
, matchobj
, dirname
):
1914 """Function to replace a matched '##include' directive with the
1915 contents of the specified file (with nested ##includes
1916 replaced recursively). 'matchobj' is an re match object
1917 (from a match of includeRE) and 'dirname' is the directory
1918 relative to which the file path should be resolved."""
1920 fname
= matchobj
.group('filename')
1921 full_fname
= os
.path
.normpath(os
.path
.join(dirname
, fname
))
1922 contents
= '##newfile "%s"\n%s\n##endfile\n' % \
1923 (full_fname
, self
.read_and_flatten(full_fname
))
1926 def read_and_flatten(self
, filename
):
1927 """Read a file and recursively flatten nested '##include' files."""
1929 current_dir
= os
.path
.dirname(filename
)
1931 contents
= open(filename
).read()
1933 error('Error including file "%s"' % filename
)
1935 self
.fileNameStack
.push((filename
, 0))
1937 # Find any includes and include them
1938 def replace(matchobj
):
1939 return self
.replace_include(matchobj
, current_dir
)
1940 contents
= self
.includeRE
.sub(replace
, contents
)
1942 self
.fileNameStack
.pop()
1945 def _parse_isa_desc(self
, isa_desc_file
):
1946 '''Read in and parse the ISA description.'''
1948 # Read file and (recursively) all included files into a string.
1949 # PLY requires that the input be in a single string so we have to
1951 isa_desc
= self
.read_and_flatten(isa_desc_file
)
1953 # Initialize filename stack with outer file.
1954 self
.fileNameStack
.push((isa_desc_file
, 0))
1957 (isa_name
, namespace
, global_code
, namespace_code
) = \
1958 self
.parse_string(isa_desc
)
1960 # grab the last three path components of isa_desc_file to put in
1962 filename
= '/'.join(isa_desc_file
.split('/')[-3:])
1964 # generate decoder.hh
1965 includes
= '#include "base/bitfield.hh" // for bitfield support'
1966 global_output
= global_code
.header_output
1967 namespace_output
= namespace_code
.header_output
1968 decode_function
= ''
1969 self
.update_if_needed('decoder.hh', file_template
% vars())
1971 # generate decoder.cc
1972 includes
= '#include "decoder.hh"'
1973 global_output
= global_code
.decoder_output
1974 namespace_output
= namespace_code
.decoder_output
1975 # namespace_output += namespace_code.decode_block
1976 decode_function
= namespace_code
.decode_block
1977 self
.update_if_needed('decoder.cc', file_template
% vars())
1979 # generate per-cpu exec files
1980 for cpu
in self
.cpuModels
:
1981 includes
= '#include "decoder.hh"\n'
1982 includes
+= cpu
.includes
1983 global_output
= global_code
.exec_output
[cpu
.name
]
1984 namespace_output
= namespace_code
.exec_output
[cpu
.name
]
1985 decode_function
= ''
1986 self
.update_if_needed(cpu
.filename
, file_template
% vars())
1988 # The variable names here are hacky, but this will creat local
1989 # variables which will be referenced in vars() which have the
1990 # value of the globals.
1991 MaxInstSrcRegs
= self
.maxInstSrcRegs
1992 MaxInstDestRegs
= self
.maxInstDestRegs
1994 self
.update_if_needed('max_inst_regs.hh',
1995 max_inst_regs_template
% vars())
1997 def parse_isa_desc(self
, *args
, **kwargs
):
1999 self
._parse
_isa
_desc
(*args
, **kwargs
)
2000 except ISAParserError
, e
:
2001 e
.exit(self
.fileNameStack
)
2003 # Called as script: get args from command line.
2004 # Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2005 if __name__
== '__main__':
2006 execfile(sys
.argv
[1]) # read in CpuModel definitions
2007 cpu_models
= [CpuModel
.dict[cpu
] for cpu
in sys
.argv
[4:]]
2008 ISAParser(sys
.argv
[3], cpu_models
).parse_isa_desc(sys
.argv
[2])