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 if d
.operands
.memOperand
:
213 myDict
['mem_acc_size'] = d
.operands
.memOperand
.mem_acc_size
214 myDict
['mem_acc_type'] = d
.operands
.memOperand
.mem_acc_type
216 elif isinstance(d
, dict):
217 # if the argument is a dictionary, we just use it.
219 elif hasattr(d
, '__dict__'):
220 # if the argument is an object, we use its attribute map.
221 myDict
.update(d
.__dict
__)
223 raise TypeError, "Template.subst() arg must be or have dictionary"
224 return template
% myDict
226 # Convert to string. This handles the case when a template with a
227 # CPU-specific term gets interpolated into another template or into
230 return self
.parser
.expandCpuSymbolsToString(self
.template
)
235 # A format object encapsulates an instruction format. It must provide
236 # a defineInst() method that generates the code for an instruction
239 class Format(object):
240 def __init__(self
, id, params
, code
):
243 label
= 'def format ' + id
244 self
.user_code
= compile(fixPythonIndentation(code
), label
, 'exec')
245 param_list
= string
.join(params
, ", ")
246 f
= '''def defInst(_code, _context, %s):
247 my_locals = vars().copy()
248 exec _code in _context, my_locals
249 return my_locals\n''' % param_list
250 c
= compile(f
, label
+ ' wrapper', 'exec')
254 def defineInst(self
, parser
, name
, args
, lineno
):
255 parser
.updateExportContext()
256 context
= parser
.exportContext
.copy()
258 Name
= name
[0].upper()
261 context
.update({ 'name' : name
, 'Name' : Name
})
263 vars = self
.func(self
.user_code
, context
, *args
[0], **args
[1])
264 except Exception, exc
:
267 error(lineno
, 'error defining "%s": %s.' % (name
, exc
))
268 for k
in vars.keys():
269 if k
not in ('header_output', 'decoder_output',
270 'exec_output', 'decode_block'):
272 return GenCode(parser
, **vars)
274 # Special null format to catch an implicit-format instruction
275 # definition outside of any format block.
276 class NoFormat(object):
278 self
.defaultInst
= ''
280 def defineInst(self
, parser
, name
, args
, lineno
):
282 'instruction definition "%s" with no active format!' % name
)
287 # The GenCode class encapsulates generated code destined for various
288 # output files. The header_output and decoder_output attributes are
289 # strings containing code destined for decoder.hh and decoder.cc
290 # respectively. The decode_block attribute contains code to be
291 # incorporated in the decode function itself (that will also end up in
292 # decoder.cc). The exec_output attribute is a dictionary with a key
293 # for each CPU model name; the value associated with a particular key
294 # is the string of code for that CPU model's exec.cc file. The
295 # has_decode_default attribute is used in the decode block to allow
296 # explicit default clauses to override default default clauses.
298 class GenCode(object):
299 # Constructor. At this point we substitute out all CPU-specific
300 # symbols. For the exec output, these go into the per-model
301 # dictionary. For all other output types they get collapsed into
303 def __init__(self
, parser
,
304 header_output
= '', decoder_output
= '', exec_output
= '',
305 decode_block
= '', has_decode_default
= False):
307 self
.header_output
= parser
.expandCpuSymbolsToString(header_output
)
308 self
.decoder_output
= parser
.expandCpuSymbolsToString(decoder_output
)
309 if isinstance(exec_output
, dict):
310 self
.exec_output
= exec_output
311 elif isinstance(exec_output
, str):
312 # If the exec_output arg is a single string, we replicate
313 # it for each of the CPU models, substituting and
314 # %(CPU_foo)s params appropriately.
315 self
.exec_output
= parser
.expandCpuSymbolsToDict(exec_output
)
316 self
.decode_block
= parser
.expandCpuSymbolsToString(decode_block
)
317 self
.has_decode_default
= has_decode_default
319 # Override '+' operator: generate a new GenCode object that
320 # concatenates all the individual strings in the operands.
321 def __add__(self
, other
):
323 for cpu
in self
.parser
.cpuModels
:
325 exec_output
[n
] = self
.exec_output
[n
] + other
.exec_output
[n
]
326 return GenCode(self
.parser
,
327 self
.header_output
+ other
.header_output
,
328 self
.decoder_output
+ other
.decoder_output
,
330 self
.decode_block
+ other
.decode_block
,
331 self
.has_decode_default
or other
.has_decode_default
)
333 # Prepend a string (typically a comment) to all the strings.
334 def prepend_all(self
, pre
):
335 self
.header_output
= pre
+ self
.header_output
336 self
.decoder_output
= pre
+ self
.decoder_output
337 self
.decode_block
= pre
+ self
.decode_block
338 for cpu
in self
.parser
.cpuModels
:
339 self
.exec_output
[cpu
.name
] = pre
+ self
.exec_output
[cpu
.name
]
341 # Wrap the decode block in a pair of strings (e.g., 'case foo:'
342 # and 'break;'). Used to build the big nested switch statement.
343 def wrap_decode_block(self
, pre
, post
= ''):
344 self
.decode_block
= pre
+ indent(self
.decode_block
) + post
346 #####################################################################
348 # Bitfield Operator Support
350 #####################################################################
352 bitOp1ArgRE
= re
.compile(r
'<\s*(\w+)\s*:\s*>')
354 bitOpWordRE
= re
.compile(r
'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
355 bitOpExprRE
= re
.compile(r
'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
357 def substBitOps(code
):
358 # first convert single-bit selectors to two-index form
359 # i.e., <n> --> <n:n>
360 code
= bitOp1ArgRE
.sub(r
'<\1:\1>', code
)
361 # simple case: selector applied to ID (name)
362 # i.e., foo<a:b> --> bits(foo, a, b)
363 code
= bitOpWordRE
.sub(r
'bits(\1, \2, \3)', code
)
364 # if selector is applied to expression (ending in ')'),
365 # we need to search backward for matching '('
366 match
= bitOpExprRE
.search(code
)
368 exprEnd
= match
.start()
372 if code
[here
] == '(':
374 elif code
[here
] == ')':
378 sys
.exit("Didn't find '('!")
380 newExpr
= r
'bits(%s, %s, %s)' % (code
[exprStart
:exprEnd
+1],
381 match
.group(1), match
.group(2))
382 code
= code
[:exprStart
] + newExpr
+ code
[match
.end():]
383 match
= bitOpExprRE
.search(code
)
387 #####################################################################
391 # The remaining code is the support for automatically extracting
392 # instruction characteristics from pseudocode.
394 #####################################################################
396 # Force the argument to be a list. Useful for flags, where a caller
397 # can specify a singleton flag or a list of flags. Also usful for
398 # converting tuples to lists so they can be modified.
400 if isinstance(arg
, list):
402 elif isinstance(arg
, tuple):
409 class Operand(object):
410 '''Base class for operand descriptors. An instance of this class
411 (or actually a class derived from this one) represents a specific
412 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
413 derived classes encapsulates the traits of a particular operand
414 type (e.g., "32-bit integer register").'''
416 def buildReadCode(self
, func
= None):
417 subst_dict
= {"name": self
.base_name
,
419 "reg_idx": self
.reg_spec
,
422 if hasattr(self
, 'src_reg_idx'):
423 subst_dict
['op_idx'] = self
.src_reg_idx
424 code
= self
.read_code
% subst_dict
425 if self
.size
!= self
.dflt_size
:
426 return '%s = bits(%s, %d, 0);\n' % \
427 (self
.base_name
, code
, self
.size
-1)
429 return '%s = %s;\n' % \
430 (self
.base_name
, code
)
432 def buildWriteCode(self
, func
= None):
433 if (self
.size
!= self
.dflt_size
and self
.is_signed
):
434 final_val
= 'sext<%d>(%s)' % (self
.size
, self
.base_name
)
436 final_val
= self
.base_name
437 subst_dict
= {"name": self
.base_name
,
439 "reg_idx": self
.reg_spec
,
442 "final_val": final_val
}
443 if hasattr(self
, 'dest_reg_idx'):
444 subst_dict
['op_idx'] = self
.dest_reg_idx
445 code
= self
.write_code
% subst_dict
450 if (traceData) { traceData->setData(final_val); }
451 }''' % (self
.dflt_ctype
, final_val
, code
)
453 def __init__(self
, parser
, full_name
, ext
, is_src
, is_dest
):
454 self
.full_name
= full_name
457 self
.is_dest
= is_dest
458 # The 'effective extension' (eff_ext) is either the actual
459 # extension, if one was explicitly provided, or the default.
462 elif hasattr(self
, 'dflt_ext'):
463 self
.eff_ext
= self
.dflt_ext
465 if hasattr(self
, 'eff_ext'):
466 self
.size
, self
.ctype
, self
.is_signed
= \
467 parser
.operandTypeMap
[self
.eff_ext
]
469 # note that mem_acc_size is undefined for non-mem operands...
470 # template must be careful not to use it if it doesn't apply.
472 self
.mem_acc_size
= self
.makeAccSize()
473 if self
.ctype
in ['Twin32_t', 'Twin64_t']:
474 self
.mem_acc_type
= 'Twin'
476 self
.mem_acc_type
= 'uint'
478 # Finalize additional fields (primarily code fields). This step
479 # is done separately since some of these fields may depend on the
480 # register index enumeration that hasn't been performed yet at the
481 # time of __init__().
483 self
.flags
= self
.getFlags()
484 self
.constructor
= self
.makeConstructor()
485 self
.op_decl
= self
.makeDecl()
488 self
.op_rd
= self
.makeRead()
489 self
.op_src_decl
= self
.makeDecl()
492 self
.op_src_decl
= ''
495 self
.op_wb
= self
.makeWrite()
496 self
.op_dest_decl
= self
.makeDecl()
499 self
.op_dest_decl
= ''
507 def isFloatReg(self
):
513 def isControlReg(self
):
520 return self
.isPCState() and self
.reg_spec
523 # note the empty slice '[:]' gives us a copy of self.flags[0]
524 # instead of a reference to it
525 my_flags
= self
.flags
[0][:]
527 my_flags
+= self
.flags
[1]
529 my_flags
+= self
.flags
[2]
533 # Note that initializations in the declarations are solely
534 # to avoid 'uninitialized variable' errors from the compiler.
535 return self
.ctype
+ ' ' + self
.base_name
+ ' = 0;\n';
537 class IntRegOperand(Operand
):
544 def makeConstructor(self
):
547 c
+= '\n\t_srcRegIdx[%d] = %s;' % \
548 (self
.src_reg_idx
, self
.reg_spec
)
550 c
+= '\n\t_destRegIdx[%d] = %s;' % \
551 (self
.dest_reg_idx
, self
.reg_spec
)
555 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
556 error('Attempt to read integer register as FP')
557 if self
.read_code
!= None:
558 return self
.buildReadCode('readIntRegOperand')
559 if (self
.size
== self
.dflt_size
):
560 return '%s = xc->readIntRegOperand(this, %d);\n' % \
561 (self
.base_name
, self
.src_reg_idx
)
562 elif (self
.size
> self
.dflt_size
):
563 int_reg_val
= 'xc->readIntRegOperand(this, %d)' % \
566 int_reg_val
= 'sext<%d>(%s)' % (self
.dflt_size
, int_reg_val
)
567 return '%s = %s;\n' % (self
.base_name
, int_reg_val
)
569 return '%s = bits(xc->readIntRegOperand(this, %d), %d, 0);\n' % \
570 (self
.base_name
, self
.src_reg_idx
, self
.size
-1)
573 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
574 error('Attempt to write integer register as FP')
575 if self
.write_code
!= None:
576 return self
.buildWriteCode('setIntRegOperand')
577 if (self
.size
!= self
.dflt_size
and self
.is_signed
):
578 final_val
= 'sext<%d>(%s)' % (self
.size
, self
.base_name
)
580 final_val
= self
.base_name
584 xc->setIntRegOperand(this, %d, final_val);\n
585 if (traceData) { traceData->setData(final_val); }
586 }''' % (self
.dflt_ctype
, final_val
, self
.dest_reg_idx
)
589 class FloatRegOperand(Operand
):
593 def isFloatReg(self
):
596 def makeConstructor(self
):
599 c
+= '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
600 (self
.src_reg_idx
, self
.reg_spec
)
602 c
+= '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
603 (self
.dest_reg_idx
, self
.reg_spec
)
608 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
609 func
= 'readFloatRegOperand'
611 func
= 'readFloatRegOperandBits'
612 if (self
.size
!= self
.dflt_size
):
614 base
= 'xc->%s(this, %d)' % (func
, self
.src_reg_idx
)
615 if self
.read_code
!= None:
616 return self
.buildReadCode(func
)
618 return '%s = bits(%s, %d, 0);\n' % \
619 (self
.base_name
, base
, self
.size
-1)
621 return '%s = %s;\n' % (self
.base_name
, base
)
624 final_val
= self
.base_name
625 final_ctype
= self
.ctype
626 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
627 func
= 'setFloatRegOperand'
628 elif (self
.ctype
== 'uint32_t' or self
.ctype
== 'uint64_t'):
629 func
= 'setFloatRegOperandBits'
631 func
= 'setFloatRegOperandBits'
632 final_ctype
= 'uint%d_t' % self
.dflt_size
633 if (self
.size
!= self
.dflt_size
and self
.is_signed
):
634 final_val
= 'sext<%d>(%s)' % (self
.size
, self
.base_name
)
635 if self
.write_code
!= None:
636 return self
.buildWriteCode(func
)
640 xc->%s(this, %d, final_val);\n
641 if (traceData) { traceData->setData(final_val); }
642 }''' % (final_ctype
, final_val
, func
, self
.dest_reg_idx
)
645 class ControlRegOperand(Operand
):
649 def isControlReg(self
):
652 def makeConstructor(self
):
655 c
+= '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
656 (self
.src_reg_idx
, self
.reg_spec
)
658 c
+= '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
659 (self
.dest_reg_idx
, self
.reg_spec
)
664 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
665 error('Attempt to read control register as FP')
666 if self
.read_code
!= None:
667 return self
.buildReadCode('readMiscRegOperand')
668 base
= 'xc->readMiscRegOperand(this, %s)' % self
.src_reg_idx
669 if self
.size
== self
.dflt_size
:
670 return '%s = %s;\n' % (self
.base_name
, base
)
672 return '%s = bits(%s, %d, 0);\n' % \
673 (self
.base_name
, base
, self
.size
-1)
676 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
677 error('Attempt to write control register as FP')
678 if self
.write_code
!= None:
679 return self
.buildWriteCode('setMiscRegOperand')
680 wb
= 'xc->setMiscRegOperand(this, %s, %s);\n' % \
681 (self
.dest_reg_idx
, self
.base_name
)
682 wb
+= 'if (traceData) { traceData->setData(%s); }' % \
686 class MemOperand(Operand
):
690 def makeConstructor(self
):
694 # Note that initializations in the declarations are solely
695 # to avoid 'uninitialized variable' errors from the compiler.
696 # Declare memory data variable.
697 if self
.ctype
in ['Twin32_t','Twin64_t']:
698 return "%s %s; %s.a = 0; %s.b = 0;\n" % \
699 (self
.ctype
, self
.base_name
, self
.base_name
, self
.base_name
)
700 return '%s %s = 0;\n' % (self
.ctype
, self
.base_name
)
703 if self
.read_code
!= None:
704 return self
.buildReadCode()
708 if self
.write_code
!= None:
709 return self
.buildWriteCode()
712 # Return the memory access size *in bits*, suitable for
713 # forming a type via "uint%d_t". Divide by 8 if you want bytes.
714 def makeAccSize(self
):
717 class PCStateOperand(Operand
):
718 def makeConstructor(self
):
723 # A component of the PC state.
724 return '%s = __parserAutoPCState.%s();\n' % \
725 (self
.base_name
, self
.reg_spec
)
727 # The whole PC state itself.
728 return '%s = xc->pcState();\n' % self
.base_name
732 # A component of the PC state.
733 return '__parserAutoPCState.%s(%s);\n' % \
734 (self
.reg_spec
, self
.base_name
)
736 # The whole PC state itself.
737 return 'xc->pcState(%s);\n' % self
.base_name
740 ctype
= 'TheISA::PCState'
743 return "%s %s;\n" % (ctype
, self
.base_name
)
748 class OperandList(object):
749 '''Find all the operands in the given code block. Returns an operand
750 descriptor list (instance of class OperandList).'''
751 def __init__(self
, parser
, code
):
754 # delete comments so we don't match on reg specifiers inside
755 code
= commentRE
.sub('', code
)
756 # search for operands
759 match
= parser
.operandsRE
.search(code
, next_pos
)
761 # no more matches: we're done
764 # regexp groups are operand full name, base, and extension
765 (op_full
, op_base
, op_ext
) = op
766 # if the token following the operand is an assignment, this is
767 # a destination (LHS), else it's a source (RHS)
768 is_dest
= (assignRE
.match(code
, match
.end()) != None)
770 # see if we've already seen this one
771 op_desc
= self
.find_base(op_base
)
773 if op_desc
.ext
!= op_ext
:
774 error('Inconsistent extensions for operand %s' % \
776 op_desc
.is_src
= op_desc
.is_src
or is_src
777 op_desc
.is_dest
= op_desc
.is_dest
or is_dest
779 # new operand: create new descriptor
780 op_desc
= parser
.operandNameMap
[op_base
](parser
,
781 op_full
, op_ext
, is_src
, is_dest
)
783 # start next search after end of current match
784 next_pos
= match
.end()
786 # enumerate source & dest register operands... used in building
790 self
.numFPDestRegs
= 0
791 self
.numIntDestRegs
= 0
792 self
.memOperand
= None
793 for op_desc
in self
.items
:
796 op_desc
.src_reg_idx
= self
.numSrcRegs
799 op_desc
.dest_reg_idx
= self
.numDestRegs
800 self
.numDestRegs
+= 1
801 if op_desc
.isFloatReg():
802 self
.numFPDestRegs
+= 1
803 elif op_desc
.isIntReg():
804 self
.numIntDestRegs
+= 1
805 elif op_desc
.isMem():
807 error("Code block has more than one memory operand.")
808 self
.memOperand
= op_desc
809 if parser
.maxInstSrcRegs
< self
.numSrcRegs
:
810 parser
.maxInstSrcRegs
= self
.numSrcRegs
811 if parser
.maxInstDestRegs
< self
.numDestRegs
:
812 parser
.maxInstDestRegs
= self
.numDestRegs
813 # now make a final pass to finalize op_desc fields that may depend
814 # on the register enumeration
815 for op_desc
in self
.items
:
819 return len(self
.items
)
821 def __getitem__(self
, index
):
822 return self
.items
[index
]
824 def append(self
, op_desc
):
825 self
.items
.append(op_desc
)
826 self
.bases
[op_desc
.base_name
] = op_desc
828 def find_base(self
, base_name
):
829 # like self.bases[base_name], but returns None if not found
830 # (rather than raising exception)
831 return self
.bases
.get(base_name
)
833 # internal helper function for concat[Some]Attr{Strings|Lists}
834 def __internalConcatAttrs(self
, attr_name
, filter, result
):
835 for op_desc
in self
.items
:
837 result
+= getattr(op_desc
, attr_name
)
840 # return a single string that is the concatenation of the (string)
841 # values of the specified attribute for all operands
842 def concatAttrStrings(self
, attr_name
):
843 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, '')
845 # like concatAttrStrings, but only include the values for the operands
846 # for which the provided filter function returns true
847 def concatSomeAttrStrings(self
, filter, attr_name
):
848 return self
.__internalConcatAttrs
(attr_name
, filter, '')
850 # return a single list that is the concatenation of the (list)
851 # values of the specified attribute for all operands
852 def concatAttrLists(self
, attr_name
):
853 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, [])
855 # like concatAttrLists, but only include the values for the operands
856 # for which the provided filter function returns true
857 def concatSomeAttrLists(self
, filter, attr_name
):
858 return self
.__internalConcatAttrs
(attr_name
, filter, [])
861 self
.items
.sort(lambda a
, b
: a
.sort_pri
- b
.sort_pri
)
863 class SubOperandList(OperandList
):
864 '''Find all the operands in the given code block. Returns an operand
865 descriptor list (instance of class OperandList).'''
866 def __init__(self
, parser
, code
, master_list
):
869 # delete comments so we don't match on reg specifiers inside
870 code
= commentRE
.sub('', code
)
871 # search for operands
874 match
= parser
.operandsRE
.search(code
, next_pos
)
876 # no more matches: we're done
879 # regexp groups are operand full name, base, and extension
880 (op_full
, op_base
, op_ext
) = op
881 # find this op in the master list
882 op_desc
= master_list
.find_base(op_base
)
884 error('Found operand %s which is not in the master list!' \
885 ' This is an internal error' % op_base
)
887 # See if we've already found this operand
888 op_desc
= self
.find_base(op_base
)
890 # if not, add a reference to it to this sub list
891 self
.append(master_list
.bases
[op_base
])
893 # start next search after end of current match
894 next_pos
= match
.end()
896 self
.memOperand
= None
897 # Whether the whole PC needs to be read so parts of it can be accessed
899 # Whether the whole PC needs to be written after parts of it were
902 # Whether this instruction manipulates the whole PC or parts of it.
903 # Mixing the two is a bad idea and flagged as an error.
905 for op_desc
in self
.items
:
906 if op_desc
.isPCPart():
910 if op_desc
.isPCState():
911 if self
.pcPart
is not None:
912 if self
.pcPart
and not op_desc
.isPCPart() or \
913 not self
.pcPart
and op_desc
.isPCPart():
914 error("Mixed whole and partial PC state operands.")
915 self
.pcPart
= op_desc
.isPCPart()
918 error("Code block has more than one memory operand.")
919 self
.memOperand
= op_desc
921 # Regular expression object to match C++ comments
922 # (used in findOperands())
923 commentRE
= re
.compile(r
'//.*\n')
925 # Regular expression object to match assignment statements
926 # (used in findOperands())
927 assignRE
= re
.compile(r
'\s*=(?!=)', re
.MULTILINE
)
929 def makeFlagConstructor(flag_list
):
930 if len(flag_list
) == 0:
932 # filter out repeated flags
935 while i
< len(flag_list
):
936 if flag_list
[i
] == flag_list
[i
-1]:
942 code
= pre
+ string
.join(flag_list
, post
+ pre
) + post
945 # Assume all instruction flags are of the form 'IsFoo'
946 instFlagRE
= re
.compile(r
'Is.*')
948 # OpClass constants end in 'Op' except No_OpClass
949 opClassRE
= re
.compile(r
'.*Op|No_OpClass')
951 class InstObjParams(object):
952 def __init__(self
, parser
, mnem
, class_name
, base_class
= '',
953 snippets
= {}, opt_args
= []):
955 self
.class_name
= class_name
956 self
.base_class
= base_class
957 if not isinstance(snippets
, dict):
958 snippets
= {'code' : snippets
}
959 compositeCode
= ' '.join(map(str, snippets
.values()))
960 self
.snippets
= snippets
962 self
.operands
= OperandList(parser
, compositeCode
)
963 self
.constructor
= self
.operands
.concatAttrStrings('constructor')
964 self
.constructor
+= \
965 '\n\t_numSrcRegs = %d;' % self
.operands
.numSrcRegs
966 self
.constructor
+= \
967 '\n\t_numDestRegs = %d;' % self
.operands
.numDestRegs
968 self
.constructor
+= \
969 '\n\t_numFPDestRegs = %d;' % self
.operands
.numFPDestRegs
970 self
.constructor
+= \
971 '\n\t_numIntDestRegs = %d;' % self
.operands
.numIntDestRegs
972 self
.flags
= self
.operands
.concatAttrLists('flags')
974 # Make a basic guess on the operand class (function unit type).
975 # These are good enough for most cases, and can be overridden
977 if 'IsStore' in self
.flags
:
978 self
.op_class
= 'MemWriteOp'
979 elif 'IsLoad' in self
.flags
or 'IsPrefetch' in self
.flags
:
980 self
.op_class
= 'MemReadOp'
981 elif 'IsFloating' in self
.flags
:
982 self
.op_class
= 'FloatAddOp'
984 self
.op_class
= 'IntAluOp'
986 # Optional arguments are assumed to be either StaticInst flags
987 # or an OpClass value. To avoid having to import a complete
988 # list of these values to match against, we do it ad-hoc
991 if instFlagRE
.match(oa
):
992 self
.flags
.append(oa
)
993 elif opClassRE
.match(oa
):
996 error('InstObjParams: optional arg "%s" not recognized '
997 'as StaticInst::Flag or OpClass.' % oa
)
999 # add flag initialization to contructor here to include
1000 # any flags added via opt_args
1001 self
.constructor
+= makeFlagConstructor(self
.flags
)
1003 # if 'IsFloating' is set, add call to the FP enable check
1004 # function (which should be provided by isa_desc via a declare)
1005 if 'IsFloating' in self
.flags
:
1006 self
.fp_enable_check
= 'fault = checkFpEnableFault(xc);'
1008 self
.fp_enable_check
= ''
1011 # Stack: a simple stack object. Used for both formats (formatStack)
1012 # and default cases (defaultStack). Simply wraps a list to give more
1013 # stack-like syntax and enable initialization with an argument list
1014 # (as opposed to an argument that's a list).
1017 def __init__(self
, *items
):
1018 list.__init
__(self
, items
)
1020 def push(self
, item
):
1026 #######################
1028 # Output file template
1033 * DO NOT EDIT THIS FILE!!!
1035 * It was automatically generated from the ISA description in %(filename)s
1042 namespace %(namespace)s {
1044 %(namespace_output)s
1046 } // namespace %(namespace)s
1051 max_inst_regs_template
= '''
1053 * DO NOT EDIT THIS FILE!!!
1055 * It was automatically generated from the ISA description in %(filename)s
1058 namespace %(namespace)s {
1060 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
1061 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
1063 } // namespace %(namespace)s
1067 class ISAParser(Grammar
):
1068 def __init__(self
, output_dir
, cpu_models
):
1069 super(ISAParser
, self
).__init
__()
1070 self
.output_dir
= output_dir
1072 self
.cpuModels
= cpu_models
1074 # variable to hold templates
1075 self
.templateMap
= {}
1077 # This dictionary maps format name strings to Format objects.
1081 self
.formatStack
= Stack(NoFormat())
1083 # The default case stack.
1084 self
.defaultStack
= Stack(None)
1086 # Stack that tracks current file and line number. Each
1087 # element is a tuple (filename, lineno) that records the
1088 # *current* filename and the line number in the *previous*
1089 # file where it was included.
1090 self
.fileNameStack
= Stack()
1092 symbols
= ('makeList', 're', 'string')
1093 self
.exportContext
= dict([(s
, eval(s
)) for s
in symbols
])
1095 self
.maxInstSrcRegs
= 0
1096 self
.maxInstDestRegs
= 0
1098 #####################################################################
1102 # The PLY lexer module takes two things as input:
1103 # - A list of token names (the string list 'tokens')
1104 # - A regular expression describing a match for each token. The
1105 # regexp for token FOO can be provided in two ways:
1106 # - as a string variable named t_FOO
1107 # - as the doc string for a function named t_FOO. In this case,
1108 # the function is also executed, allowing an action to be
1109 # associated with each token match.
1111 #####################################################################
1113 # Reserved words. These are listed separately as they are matched
1114 # using the same regexp as generic IDs, but distinguished in the
1115 # t_ID() function. The PLY documentation suggests this approach.
1117 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
1118 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
1119 'OUTPUT', 'SIGNED', 'TEMPLATE'
1122 # List of tokens. The lex module requires this.
1123 tokens
= reserved
+ (
1136 # ( ) [ ] { } < > , ; . : :: *
1138 'LBRACKET', 'RBRACKET',
1140 'LESS', 'GREATER', 'EQUALS',
1141 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON',
1144 # C preprocessor directives
1147 # The following are matched but never returned. commented out to
1148 # suppress PLY warning
1156 # Regular expressions for token matching
1173 # Identifiers and reserved words
1176 reserved_map
[r
.lower()] = r
1180 t
.type = self
.reserved_map
.get(t
.value
, 'ID')
1184 def t_INTLIT(self
, t
):
1185 r
'-?(0x[\da-fA-F]+)|\d+'
1187 t
.value
= int(t
.value
,0)
1189 error(t
, 'Integer value "%s" too large' % t
.value
)
1193 # String literal. Note that these use only single quotes, and
1194 # can span multiple lines.
1195 def t_STRLIT(self
, t
):
1198 t
.value
= t
.value
[1:-1]
1199 t
.lexer
.lineno
+= t
.value
.count('\n')
1203 # "Code literal"... like a string literal, but delimiters are
1204 # '{{' and '}}' so they get formatted nicely under emacs c-mode
1205 def t_CODELIT(self
, t
):
1206 r
"(?m)\{\{([^\}]|}(?!\}))+\}\}"
1208 t
.value
= t
.value
[2:-2]
1209 t
.lexer
.lineno
+= t
.value
.count('\n')
1212 def t_CPPDIRECTIVE(self
, t
):
1214 t
.lexer
.lineno
+= t
.value
.count('\n')
1217 def t_NEWFILE(self
, t
):
1218 r
'^\#\#newfile\s+"[^"]*"'
1219 self
.fileNameStack
.push((t
.value
[11:-1], t
.lexer
.lineno
))
1222 def t_ENDFILE(self
, t
):
1224 (old_filename
, t
.lexer
.lineno
) = self
.fileNameStack
.pop()
1227 # The functions t_NEWLINE, t_ignore, and t_error are
1228 # special for the lex module.
1232 def t_NEWLINE(self
, t
):
1234 t
.lexer
.lineno
+= t
.value
.count('\n')
1237 def t_comment(self
, t
):
1240 # Completely ignored characters
1241 t_ignore
= ' \t\x0c'
1244 def t_error(self
, t
):
1245 error(t
, "illegal character '%s'" % t
.value
[0])
1248 #####################################################################
1252 # Every function whose name starts with 'p_' defines a grammar
1253 # rule. The rule is encoded in the function's doc string, while
1254 # the function body provides the action taken when the rule is
1255 # matched. The argument to each function is a list of the values
1256 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the
1257 # symbols on the RHS. For tokens, the value is copied from the
1258 # t.value attribute provided by the lexer. For non-terminals, the
1259 # value is assigned by the producing rule; i.e., the job of the
1260 # grammar rule function is to set the value for the non-terminal
1261 # on the LHS (by assigning to t[0]).
1262 #####################################################################
1264 # The LHS of the first grammar rule is used as the start symbol
1265 # (in this case, 'specification'). Note that this rule enforces
1266 # that there will be exactly one namespace declaration, with 0 or
1267 # more global defs/decls before and after it. The defs & decls
1268 # before the namespace decl will be outside the namespace; those
1269 # after will be inside. The decoder function is always inside the
1271 def p_specification(self
, t
):
1272 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
1275 namespace
= isa_name
+ "Inst"
1276 # wrap the decode block as a function definition
1277 t
[4].wrap_decode_block('''
1279 %(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst)
1281 using namespace %(namespace)s;
1283 # both the latter output blocks and the decode block are in
1285 namespace_code
= t
[3] + t
[4]
1286 # pass it all back to the caller of yacc.parse()
1287 t
[0] = (isa_name
, namespace
, global_code
, namespace_code
)
1289 # ISA name declaration looks like "namespace <foo>;"
1290 def p_name_decl(self
, t
):
1291 'name_decl : NAMESPACE ID SEMI'
1294 # 'opt_defs_and_outputs' is a possibly empty sequence of
1295 # def and/or output statements.
1296 def p_opt_defs_and_outputs_0(self
, t
):
1297 'opt_defs_and_outputs : empty'
1298 t
[0] = GenCode(self
)
1300 def p_opt_defs_and_outputs_1(self
, t
):
1301 'opt_defs_and_outputs : defs_and_outputs'
1304 def p_defs_and_outputs_0(self
, t
):
1305 'defs_and_outputs : def_or_output'
1308 def p_defs_and_outputs_1(self
, t
):
1309 'defs_and_outputs : defs_and_outputs def_or_output'
1312 # The list of possible definition/output statements.
1313 def p_def_or_output(self
, t
):
1314 '''def_or_output : def_format
1316 | def_bitfield_struct
1326 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1327 # directly to the appropriate output section.
1329 # Massage output block by substituting in template definitions and
1330 # bit operators. We handle '%'s embedded in the string that don't
1331 # indicate template substitutions (or CPU-specific symbols, which
1332 # get handled in GenCode) by doubling them first so that the
1333 # format operation will reduce them back to single '%'s.
1334 def process_output(self
, s
):
1335 s
= self
.protectNonSubstPercents(s
)
1336 # protects cpu-specific symbols too
1337 s
= self
.protectCpuSymbols(s
)
1338 return substBitOps(s
% self
.templateMap
)
1340 def p_output_header(self
, t
):
1341 'output_header : OUTPUT HEADER CODELIT SEMI'
1342 t
[0] = GenCode(self
, header_output
= self
.process_output(t
[3]))
1344 def p_output_decoder(self
, t
):
1345 'output_decoder : OUTPUT DECODER CODELIT SEMI'
1346 t
[0] = GenCode(self
, decoder_output
= self
.process_output(t
[3]))
1348 def p_output_exec(self
, t
):
1349 'output_exec : OUTPUT EXEC CODELIT SEMI'
1350 t
[0] = GenCode(self
, exec_output
= self
.process_output(t
[3]))
1352 # global let blocks 'let {{...}}' (Python code blocks) are
1353 # executed directly when seen. Note that these execute in a
1354 # special variable context 'exportContext' to prevent the code
1355 # from polluting this script's namespace.
1356 def p_global_let(self
, t
):
1357 'global_let : LET CODELIT SEMI'
1358 self
.updateExportContext()
1359 self
.exportContext
["header_output"] = ''
1360 self
.exportContext
["decoder_output"] = ''
1361 self
.exportContext
["exec_output"] = ''
1362 self
.exportContext
["decode_block"] = ''
1364 exec fixPythonIndentation(t
[2]) in self
.exportContext
1365 except Exception, exc
:
1368 error(t
, 'error: %s in global let block "%s".' % (exc
, t
[2]))
1369 t
[0] = GenCode(self
,
1370 header_output
=self
.exportContext
["header_output"],
1371 decoder_output
=self
.exportContext
["decoder_output"],
1372 exec_output
=self
.exportContext
["exec_output"],
1373 decode_block
=self
.exportContext
["decode_block"])
1375 # Define the mapping from operand type extensions to C++ types and
1376 # bit widths (stored in operandTypeMap).
1377 def p_def_operand_types(self
, t
):
1378 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1380 user_dict
= eval('{' + t
[3] + '}')
1381 except Exception, exc
:
1385 'error: %s in def operand_types block "%s".' % (exc
, t
[3]))
1386 self
.buildOperandTypeMap(user_dict
, t
.lexer
.lineno
)
1387 t
[0] = GenCode(self
) # contributes nothing to the output C++ file
1389 # Define the mapping from operand names to operand classes and
1390 # other traits. Stored in operandNameMap.
1391 def p_def_operands(self
, t
):
1392 'def_operands : DEF OPERANDS CODELIT SEMI'
1393 if not hasattr(self
, 'operandTypeMap'):
1394 error(t
, 'error: operand types must be defined before operands')
1396 user_dict
= eval('{' + t
[3] + '}', self
.exportContext
)
1397 except Exception, exc
:
1400 error(t
, 'error: %s in def operands block "%s".' % (exc
, t
[3]))
1401 self
.buildOperandNameMap(user_dict
, t
.lexer
.lineno
)
1402 t
[0] = GenCode(self
) # contributes nothing to the output C++ file
1404 # A bitfield definition looks like:
1405 # 'def [signed] bitfield <ID> [<first>:<last>]'
1406 # This generates a preprocessor macro in the output file.
1407 def p_def_bitfield_0(self
, t
):
1408 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
1409 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[8])
1410 if (t
[2] == 'signed'):
1411 expr
= 'sext<%d>(%s)' % (t
[6] - t
[8] + 1, expr
)
1412 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1413 t
[0] = GenCode(self
, header_output
=hash_define
)
1415 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
1416 def p_def_bitfield_1(self
, t
):
1417 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
1418 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[6])
1419 if (t
[2] == 'signed'):
1420 expr
= 'sext<%d>(%s)' % (1, expr
)
1421 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1422 t
[0] = GenCode(self
, header_output
=hash_define
)
1424 # alternate form for structure member: 'def bitfield <ID> <ID>'
1425 def p_def_bitfield_struct(self
, t
):
1426 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI'
1428 error(t
, 'error: structure bitfields are always unsigned.')
1429 expr
= 'machInst.%s' % t
[5]
1430 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1431 t
[0] = GenCode(self
, header_output
=hash_define
)
1433 def p_id_with_dot_0(self
, t
):
1437 def p_id_with_dot_1(self
, t
):
1438 'id_with_dot : ID DOT id_with_dot'
1439 t
[0] = t
[1] + t
[2] + t
[3]
1441 def p_opt_signed_0(self
, t
):
1442 'opt_signed : SIGNED'
1445 def p_opt_signed_1(self
, t
):
1446 'opt_signed : empty'
1449 def p_def_template(self
, t
):
1450 'def_template : DEF TEMPLATE ID CODELIT SEMI'
1451 self
.templateMap
[t
[3]] = Template(self
, t
[4])
1452 t
[0] = GenCode(self
)
1454 # An instruction format definition looks like
1455 # "def format <fmt>(<params>) {{...}};"
1456 def p_def_format(self
, t
):
1457 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1458 (id, params
, code
) = (t
[3], t
[5], t
[7])
1459 self
.defFormat(id, params
, code
, t
.lexer
.lineno
)
1460 t
[0] = GenCode(self
)
1462 # The formal parameter list for an instruction format is a
1463 # possibly empty list of comma-separated parameters. Positional
1464 # (standard, non-keyword) parameters must come first, followed by
1465 # keyword parameters, followed by a '*foo' parameter that gets
1466 # excess positional arguments (as in Python). Each of these three
1467 # parameter categories is optional.
1469 # Note that we do not support the '**foo' parameter for collecting
1470 # otherwise undefined keyword args. Otherwise the parameter list
1471 # is (I believe) identical to what is supported in Python.
1473 # The param list generates a tuple, where the first element is a
1474 # list of the positional params and the second element is a dict
1475 # containing the keyword params.
1476 def p_param_list_0(self
, t
):
1477 'param_list : positional_param_list COMMA nonpositional_param_list'
1480 def p_param_list_1(self
, t
):
1481 '''param_list : positional_param_list
1482 | nonpositional_param_list'''
1485 def p_positional_param_list_0(self
, t
):
1486 'positional_param_list : empty'
1489 def p_positional_param_list_1(self
, t
):
1490 'positional_param_list : ID'
1493 def p_positional_param_list_2(self
, t
):
1494 'positional_param_list : positional_param_list COMMA ID'
1495 t
[0] = t
[1] + [t
[3]]
1497 def p_nonpositional_param_list_0(self
, t
):
1498 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
1501 def p_nonpositional_param_list_1(self
, t
):
1502 '''nonpositional_param_list : keyword_param_list
1503 | excess_args_param'''
1506 def p_keyword_param_list_0(self
, t
):
1507 'keyword_param_list : keyword_param'
1510 def p_keyword_param_list_1(self
, t
):
1511 'keyword_param_list : keyword_param_list COMMA keyword_param'
1512 t
[0] = t
[1] + [t
[3]]
1514 def p_keyword_param(self
, t
):
1515 'keyword_param : ID EQUALS expr'
1516 t
[0] = t
[1] + ' = ' + t
[3].__repr
__()
1518 def p_excess_args_param(self
, t
):
1519 'excess_args_param : ASTERISK ID'
1520 # Just concatenate them: '*ID'. Wrap in list to be consistent
1521 # with positional_param_list and keyword_param_list.
1522 t
[0] = [t
[1] + t
[2]]
1524 # End of format definition-related rules.
1528 # A decode block looks like:
1529 # decode <field1> [, <field2>]* [default <inst>] { ... }
1531 def p_decode_block(self
, t
):
1532 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
1533 default_defaults
= self
.defaultStack
.pop()
1535 # use the "default defaults" only if there was no explicit
1536 # default statement in decode_stmt_list
1537 if not codeObj
.has_decode_default
:
1538 codeObj
+= default_defaults
1539 codeObj
.wrap_decode_block('switch (%s) {\n' % t
[2], '}\n')
1542 # The opt_default statement serves only to push the "default
1543 # defaults" onto defaultStack. This value will be used by nested
1544 # decode blocks, and used and popped off when the current
1545 # decode_block is processed (in p_decode_block() above).
1546 def p_opt_default_0(self
, t
):
1547 'opt_default : empty'
1548 # no default specified: reuse the one currently at the top of
1550 self
.defaultStack
.push(self
.defaultStack
.top())
1551 # no meaningful value returned
1554 def p_opt_default_1(self
, t
):
1555 'opt_default : DEFAULT inst'
1556 # push the new default
1558 codeObj
.wrap_decode_block('\ndefault:\n', 'break;\n')
1559 self
.defaultStack
.push(codeObj
)
1560 # no meaningful value returned
1563 def p_decode_stmt_list_0(self
, t
):
1564 'decode_stmt_list : decode_stmt'
1567 def p_decode_stmt_list_1(self
, t
):
1568 'decode_stmt_list : decode_stmt decode_stmt_list'
1569 if (t
[1].has_decode_default
and t
[2].has_decode_default
):
1570 error(t
, 'Two default cases in decode block')
1574 # Decode statement rules
1576 # There are four types of statements allowed in a decode block:
1577 # 1. Format blocks 'format <foo> { ... }'
1578 # 2. Nested decode blocks
1579 # 3. Instruction definitions.
1580 # 4. C preprocessor directives.
1583 # Preprocessor directives found in a decode statement list are
1584 # passed through to the output, replicated to all of the output
1585 # code streams. This works well for ifdefs, so we can ifdef out
1586 # both the declarations and the decode cases generated by an
1587 # instruction definition. Handling them as part of the grammar
1588 # makes it easy to keep them in the right place with respect to
1589 # the code generated by the other statements.
1590 def p_decode_stmt_cpp(self
, t
):
1591 'decode_stmt : CPPDIRECTIVE'
1592 t
[0] = GenCode(self
, t
[1], t
[1], t
[1], t
[1])
1594 # A format block 'format <foo> { ... }' sets the default
1595 # instruction format used to handle instruction definitions inside
1596 # the block. This format can be overridden by using an explicit
1597 # format on the instruction definition or with a nested format
1599 def p_decode_stmt_format(self
, t
):
1600 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
1601 # The format will be pushed on the stack when 'push_format_id'
1602 # is processed (see below). Once the parser has recognized
1603 # the full production (though the right brace), we're done
1604 # with the format, so now we can pop it.
1605 self
.formatStack
.pop()
1608 # This rule exists so we can set the current format (& push the
1609 # stack) when we recognize the format name part of the format
1611 def p_push_format_id(self
, t
):
1612 'push_format_id : ID'
1614 self
.formatStack
.push(self
.formatMap
[t
[1]])
1615 t
[0] = ('', '// format %s' % t
[1])
1617 error(t
, 'instruction format "%s" not defined.' % t
[1])
1619 # Nested decode block: if the value of the current field matches
1620 # the specified constant, do a nested decode on some other field.
1621 def p_decode_stmt_decode(self
, t
):
1622 'decode_stmt : case_label COLON decode_block'
1625 # just wrap the decoding code from the block as a case in the
1626 # outer switch statement.
1627 codeObj
.wrap_decode_block('\n%s:\n' % label
)
1628 codeObj
.has_decode_default
= (label
== 'default')
1631 # Instruction definition (finally!).
1632 def p_decode_stmt_inst(self
, t
):
1633 'decode_stmt : case_label COLON inst SEMI'
1636 codeObj
.wrap_decode_block('\n%s:' % label
, 'break;\n')
1637 codeObj
.has_decode_default
= (label
== 'default')
1640 # The case label is either a list of one or more constants or
1642 def p_case_label_0(self
, t
):
1643 'case_label : intlit_list'
1644 def make_case(intlit
):
1646 return 'case ULL(%#x)' % intlit
1648 return 'case %#x' % intlit
1649 t
[0] = ': '.join(map(make_case
, t
[1]))
1651 def p_case_label_1(self
, t
):
1652 'case_label : DEFAULT'
1656 # The constant list for a decode case label must be non-empty, but
1657 # may have one or more comma-separated integer literals in it.
1659 def p_intlit_list_0(self
, t
):
1660 'intlit_list : INTLIT'
1663 def p_intlit_list_1(self
, t
):
1664 'intlit_list : intlit_list COMMA INTLIT'
1668 # Define an instruction using the current instruction format
1669 # (specified by an enclosing format block).
1670 # "<mnemonic>(<args>)"
1671 def p_inst_0(self
, t
):
1672 'inst : ID LPAREN arg_list RPAREN'
1673 # Pass the ID and arg list to the current format class to deal with.
1674 currentFormat
= self
.formatStack
.top()
1675 codeObj
= currentFormat
.defineInst(self
, t
[1], t
[3], t
.lexer
.lineno
)
1676 args
= ','.join(map(str, t
[3]))
1677 args
= re
.sub('(?m)^', '//', args
)
1678 args
= re
.sub('^//', '', args
)
1679 comment
= '\n// %s::%s(%s)\n' % (currentFormat
.id, t
[1], args
)
1680 codeObj
.prepend_all(comment
)
1683 # Define an instruction using an explicitly specified format:
1684 # "<fmt>::<mnemonic>(<args>)"
1685 def p_inst_1(self
, t
):
1686 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1688 format
= self
.formatMap
[t
[1]]
1690 error(t
, 'instruction format "%s" not defined.' % t
[1])
1692 codeObj
= format
.defineInst(self
, t
[3], t
[5], t
.lexer
.lineno
)
1693 comment
= '\n// %s::%s(%s)\n' % (t
[1], t
[3], t
[5])
1694 codeObj
.prepend_all(comment
)
1697 # The arg list generates a tuple, where the first element is a
1698 # list of the positional args and the second element is a dict
1699 # containing the keyword args.
1700 def p_arg_list_0(self
, t
):
1701 'arg_list : positional_arg_list COMMA keyword_arg_list'
1702 t
[0] = ( t
[1], t
[3] )
1704 def p_arg_list_1(self
, t
):
1705 'arg_list : positional_arg_list'
1708 def p_arg_list_2(self
, t
):
1709 'arg_list : keyword_arg_list'
1712 def p_positional_arg_list_0(self
, t
):
1713 'positional_arg_list : empty'
1716 def p_positional_arg_list_1(self
, t
):
1717 'positional_arg_list : expr'
1720 def p_positional_arg_list_2(self
, t
):
1721 'positional_arg_list : positional_arg_list COMMA expr'
1722 t
[0] = t
[1] + [t
[3]]
1724 def p_keyword_arg_list_0(self
, t
):
1725 'keyword_arg_list : keyword_arg'
1728 def p_keyword_arg_list_1(self
, t
):
1729 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
1733 def p_keyword_arg(self
, t
):
1734 'keyword_arg : ID EQUALS expr'
1735 t
[0] = { t
[1] : t
[3] }
1738 # Basic expressions. These constitute the argument values of
1739 # "function calls" (i.e. instruction definitions in the decode
1740 # block) and default values for formal parameters of format
1743 # Right now, these are either strings, integers, or (recursively)
1744 # lists of exprs (using Python square-bracket list syntax). Note
1745 # that bare identifiers are trated as string constants here (since
1746 # there isn't really a variable namespace to refer to).
1748 def p_expr_0(self
, t
):
1755 def p_expr_1(self
, t
):
1756 '''expr : LBRACKET list_expr RBRACKET'''
1759 def p_list_expr_0(self
, t
):
1763 def p_list_expr_1(self
, t
):
1764 'list_expr : list_expr COMMA expr'
1765 t
[0] = t
[1] + [t
[3]]
1767 def p_list_expr_2(self
, t
):
1772 # Empty production... use in other rules for readability.
1774 def p_empty(self
, t
):
1778 # Parse error handler. Note that the argument here is the
1779 # offending *token*, not a grammar symbol (hence the need to use
1781 def p_error(self
, t
):
1783 error(t
, "syntax error at '%s'" % t
.value
)
1785 error("unknown syntax error")
1787 # END OF GRAMMAR RULES
1789 def updateExportContext(self
):
1791 # create a continuation that allows us to grab the current parser
1792 def wrapInstObjParams(*args
):
1793 return InstObjParams(self
, *args
)
1794 self
.exportContext
['InstObjParams'] = wrapInstObjParams
1795 self
.exportContext
.update(self
.templateMap
)
1797 def defFormat(self
, id, params
, code
, lineno
):
1798 '''Define a new format'''
1800 # make sure we haven't already defined this one
1801 if id in self
.formatMap
:
1802 error(lineno
, 'format %s redefined.' % id)
1804 # create new object and store in global map
1805 self
.formatMap
[id] = Format(id, params
, code
)
1807 def expandCpuSymbolsToDict(self
, template
):
1808 '''Expand template with CPU-specific references into a
1809 dictionary with an entry for each CPU model name. The entry
1810 key is the model name and the corresponding value is the
1811 template with the CPU-specific refs substituted for that
1814 # Protect '%'s that don't go with CPU-specific terms
1815 t
= re
.sub(r
'%(?!\(CPU_)', '%%', template
)
1817 for cpu
in self
.cpuModels
:
1818 result
[cpu
.name
] = t
% cpu
.strings
1821 def expandCpuSymbolsToString(self
, template
):
1822 '''*If* the template has CPU-specific references, return a
1823 single string containing a copy of the template for each CPU
1824 model with the corresponding values substituted in. If the
1825 template has no CPU-specific references, it is returned
1828 if template
.find('%(CPU_') != -1:
1829 return reduce(lambda x
,y
: x
+y
,
1830 self
.expandCpuSymbolsToDict(template
).values())
1834 def protectCpuSymbols(self
, template
):
1835 '''Protect CPU-specific references by doubling the
1836 corresponding '%'s (in preparation for substituting a different
1837 set of references into the template).'''
1839 return re
.sub(r
'%(?=\(CPU_)', '%%', template
)
1841 def protectNonSubstPercents(self
, s
):
1842 '''Protect any non-dict-substitution '%'s in a format string
1843 (i.e. those not followed by '(')'''
1845 return re
.sub(r
'%(?!\()', '%%', s
)
1847 def buildOperandTypeMap(self
, user_dict
, lineno
):
1848 """Generate operandTypeMap from the user's 'def operand_types'
1851 for (ext
, (desc
, size
)) in user_dict
.iteritems():
1852 if desc
== 'signed int':
1853 ctype
= 'int%d_t' % size
1855 elif desc
== 'unsigned int':
1856 ctype
= 'uint%d_t' % size
1858 elif desc
== 'float':
1859 is_signed
= 1 # shouldn't really matter
1864 elif desc
== 'twin64 int':
1867 elif desc
== 'twin32 int':
1871 error(parser
, lineno
,
1872 'Unrecognized type description "%s" in user_dict')
1873 operand_type
[ext
] = (size
, ctype
, is_signed
)
1875 self
.operandTypeMap
= operand_type
1877 def buildOperandNameMap(self
, user_dict
, lineno
):
1879 for op_name
, val
in user_dict
.iteritems():
1880 base_cls_name
, dflt_ext
, reg_spec
, flags
, sort_pri
= val
[:5]
1891 'error: too many attributes for operand "%s"' %
1894 # Canonical flag structure is a triple of lists, where each list
1895 # indicates the set of flags implied by this operand always, when
1896 # used as a source, and when used as a dest, respectively.
1897 # For simplicity this can be initialized using a variety of fairly
1898 # obvious shortcuts; we convert these to canonical form here.
1900 # no flags specified (e.g., 'None')
1901 flags
= ( [], [], [] )
1902 elif isinstance(flags
, str):
1903 # a single flag: assumed to be unconditional
1904 flags
= ( [ flags
], [], [] )
1905 elif isinstance(flags
, list):
1906 # a list of flags: also assumed to be unconditional
1907 flags
= ( flags
, [], [] )
1908 elif isinstance(flags
, tuple):
1909 # it's a tuple: it should be a triple,
1910 # but each item could be a single string or a list
1911 (uncond_flags
, src_flags
, dest_flags
) = flags
1912 flags
= (makeList(uncond_flags
),
1913 makeList(src_flags
), makeList(dest_flags
))
1914 # Accumulate attributes of new operand class in tmp_dict
1916 attrList
= ['reg_spec', 'flags', 'sort_pri',
1917 'read_code', 'write_code']
1919 (dflt_size
, dflt_ctype
, dflt_is_signed
) = \
1920 self
.operandTypeMap
[dflt_ext
]
1921 attrList
.extend(['dflt_size', 'dflt_ctype',
1922 'dflt_is_signed', 'dflt_ext'])
1923 for attr
in attrList
:
1924 tmp_dict
[attr
] = eval(attr
)
1925 tmp_dict
['base_name'] = op_name
1926 # New class name will be e.g. "IntReg_Ra"
1927 cls_name
= base_cls_name
+ '_' + op_name
1928 # Evaluate string arg to get class object. Note that the
1929 # actual base class for "IntReg" is "IntRegOperand", i.e. we
1930 # have to append "Operand".
1932 base_cls
= eval(base_cls_name
+ 'Operand')
1935 'error: unknown operand base class "%s"' % base_cls_name
)
1936 # The following statement creates a new class called
1937 # <cls_name> as a subclass of <base_cls> with the attributes
1938 # in tmp_dict, just as if we evaluated a class declaration.
1939 operand_name
[op_name
] = type(cls_name
, (base_cls
,), tmp_dict
)
1941 self
.operandNameMap
= operand_name
1943 # Define operand variables.
1944 operands
= user_dict
.keys()
1946 operandsREString
= (r
'''
1947 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
1948 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
1949 (?![\w\.]) # neg. lookahead assertion: prevent partial matches
1951 % string
.join(operands
, '|'))
1953 self
.operandsRE
= re
.compile(operandsREString
, re
.MULTILINE|re
.VERBOSE
)
1955 # Same as operandsREString, but extension is mandatory, and only two
1956 # groups are returned (base and ext, not full name as above).
1957 # Used for subtituting '_' for '.' to make C++ identifiers.
1958 operandsWithExtREString
= (r
'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
1959 % string
.join(operands
, '|'))
1961 self
.operandsWithExtRE
= \
1962 re
.compile(operandsWithExtREString
, re
.MULTILINE
)
1964 def substMungedOpNames(self
, code
):
1965 '''Munge operand names in code string to make legal C++
1966 variable names. This means getting rid of the type extension
1967 if any. Will match base_name attribute of Operand object.)'''
1968 return self
.operandsWithExtRE
.sub(r
'\1', code
)
1970 def mungeSnippet(self
, s
):
1971 '''Fix up code snippets for final substitution in templates.'''
1972 if isinstance(s
, str):
1973 return self
.substMungedOpNames(substBitOps(s
))
1977 def update_if_needed(self
, file, contents
):
1978 '''Update the output file only if the new contents are
1979 different from the current contents. Minimizes the files that
1980 need to be rebuilt after minor changes.'''
1982 file = os
.path
.join(self
.output_dir
, file)
1984 if os
.access(file, os
.R_OK
):
1986 old_contents
= f
.read()
1988 if contents
!= old_contents
:
1989 os
.remove(file) # in case it's write-protected
1992 print 'File', file, 'is unchanged'
2000 # This regular expression matches '##include' directives
2001 includeRE
= re
.compile(r
'^\s*##include\s+"(?P<filename>[^"]*)".*$',
2004 def replace_include(self
, matchobj
, dirname
):
2005 """Function to replace a matched '##include' directive with the
2006 contents of the specified file (with nested ##includes
2007 replaced recursively). 'matchobj' is an re match object
2008 (from a match of includeRE) and 'dirname' is the directory
2009 relative to which the file path should be resolved."""
2011 fname
= matchobj
.group('filename')
2012 full_fname
= os
.path
.normpath(os
.path
.join(dirname
, fname
))
2013 contents
= '##newfile "%s"\n%s\n##endfile\n' % \
2014 (full_fname
, self
.read_and_flatten(full_fname
))
2017 def read_and_flatten(self
, filename
):
2018 """Read a file and recursively flatten nested '##include' files."""
2020 current_dir
= os
.path
.dirname(filename
)
2022 contents
= open(filename
).read()
2024 error('Error including file "%s"' % filename
)
2026 self
.fileNameStack
.push((filename
, 0))
2028 # Find any includes and include them
2029 def replace(matchobj
):
2030 return self
.replace_include(matchobj
, current_dir
)
2031 contents
= self
.includeRE
.sub(replace
, contents
)
2033 self
.fileNameStack
.pop()
2036 def _parse_isa_desc(self
, isa_desc_file
):
2037 '''Read in and parse the ISA description.'''
2039 # Read file and (recursively) all included files into a string.
2040 # PLY requires that the input be in a single string so we have to
2042 isa_desc
= self
.read_and_flatten(isa_desc_file
)
2044 # Initialize filename stack with outer file.
2045 self
.fileNameStack
.push((isa_desc_file
, 0))
2048 (isa_name
, namespace
, global_code
, namespace_code
) = \
2049 self
.parse(isa_desc
)
2051 # grab the last three path components of isa_desc_file to put in
2053 filename
= '/'.join(isa_desc_file
.split('/')[-3:])
2055 # generate decoder.hh
2056 includes
= '#include "base/bitfield.hh" // for bitfield support'
2057 global_output
= global_code
.header_output
2058 namespace_output
= namespace_code
.header_output
2059 decode_function
= ''
2060 self
.update_if_needed('decoder.hh', file_template
% vars())
2062 # generate decoder.cc
2063 includes
= '#include "decoder.hh"'
2064 global_output
= global_code
.decoder_output
2065 namespace_output
= namespace_code
.decoder_output
2066 # namespace_output += namespace_code.decode_block
2067 decode_function
= namespace_code
.decode_block
2068 self
.update_if_needed('decoder.cc', file_template
% vars())
2070 # generate per-cpu exec files
2071 for cpu
in self
.cpuModels
:
2072 includes
= '#include "decoder.hh"\n'
2073 includes
+= cpu
.includes
2074 global_output
= global_code
.exec_output
[cpu
.name
]
2075 namespace_output
= namespace_code
.exec_output
[cpu
.name
]
2076 decode_function
= ''
2077 self
.update_if_needed(cpu
.filename
, file_template
% vars())
2079 # The variable names here are hacky, but this will creat local
2080 # variables which will be referenced in vars() which have the
2081 # value of the globals.
2082 MaxInstSrcRegs
= self
.maxInstSrcRegs
2083 MaxInstDestRegs
= self
.maxInstDestRegs
2085 self
.update_if_needed('max_inst_regs.hh',
2086 max_inst_regs_template
% vars())
2088 def parse_isa_desc(self
, *args
, **kwargs
):
2090 self
._parse
_isa
_desc
(*args
, **kwargs
)
2091 except ISAParserError
, e
:
2092 e
.exit(self
.fileNameStack
)
2094 # Called as script: get args from command line.
2095 # Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2096 if __name__
== '__main__':
2097 execfile(sys
.argv
[1]) # read in CpuModel definitions
2098 cpu_models
= [CpuModel
.dict[cpu
] for cpu
in sys
.argv
[4:]]
2099 ISAParser(sys
.argv
[3], cpu_models
).parse_isa_desc(sys
.argv
[2])