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')
175 is_src
= lambda op
: op
.is_src
176 is_dest
= lambda op
: op
.is_dest
178 myDict
['op_src_decl'] = \
179 operands
.concatSomeAttrStrings(is_src
, 'op_src_decl')
180 myDict
['op_dest_decl'] = \
181 operands
.concatSomeAttrStrings(is_dest
, 'op_dest_decl')
183 myDict
['op_rd'] = operands
.concatAttrStrings('op_rd')
184 myDict
['op_wb'] = operands
.concatAttrStrings('op_wb')
186 if d
.operands
.memOperand
:
187 myDict
['mem_acc_size'] = d
.operands
.memOperand
.mem_acc_size
188 myDict
['mem_acc_type'] = d
.operands
.memOperand
.mem_acc_type
190 elif isinstance(d
, dict):
191 # if the argument is a dictionary, we just use it.
193 elif hasattr(d
, '__dict__'):
194 # if the argument is an object, we use its attribute map.
195 myDict
.update(d
.__dict
__)
197 raise TypeError, "Template.subst() arg must be or have dictionary"
198 return template
% myDict
200 # Convert to string. This handles the case when a template with a
201 # CPU-specific term gets interpolated into another template or into
204 return self
.parser
.expandCpuSymbolsToString(self
.template
)
209 # A format object encapsulates an instruction format. It must provide
210 # a defineInst() method that generates the code for an instruction
213 class Format(object):
214 def __init__(self
, id, params
, code
):
217 label
= 'def format ' + id
218 self
.user_code
= compile(fixPythonIndentation(code
), label
, 'exec')
219 param_list
= string
.join(params
, ", ")
220 f
= '''def defInst(_code, _context, %s):
221 my_locals = vars().copy()
222 exec _code in _context, my_locals
223 return my_locals\n''' % param_list
224 c
= compile(f
, label
+ ' wrapper', 'exec')
228 def defineInst(self
, parser
, name
, args
, lineno
):
229 parser
.updateExportContext()
230 context
= parser
.exportContext
.copy()
232 Name
= name
[0].upper()
235 context
.update({ 'name' : name
, 'Name' : Name
})
237 vars = self
.func(self
.user_code
, context
, *args
[0], **args
[1])
238 except Exception, exc
:
241 error(lineno
, 'error defining "%s": %s.' % (name
, exc
))
242 for k
in vars.keys():
243 if k
not in ('header_output', 'decoder_output',
244 'exec_output', 'decode_block'):
246 return GenCode(parser
, **vars)
248 # Special null format to catch an implicit-format instruction
249 # definition outside of any format block.
250 class NoFormat(object):
252 self
.defaultInst
= ''
254 def defineInst(self
, parser
, name
, args
, lineno
):
256 'instruction definition "%s" with no active format!' % name
)
261 # The GenCode class encapsulates generated code destined for various
262 # output files. The header_output and decoder_output attributes are
263 # strings containing code destined for decoder.hh and decoder.cc
264 # respectively. The decode_block attribute contains code to be
265 # incorporated in the decode function itself (that will also end up in
266 # decoder.cc). The exec_output attribute is a dictionary with a key
267 # for each CPU model name; the value associated with a particular key
268 # is the string of code for that CPU model's exec.cc file. The
269 # has_decode_default attribute is used in the decode block to allow
270 # explicit default clauses to override default default clauses.
272 class GenCode(object):
273 # Constructor. At this point we substitute out all CPU-specific
274 # symbols. For the exec output, these go into the per-model
275 # dictionary. For all other output types they get collapsed into
277 def __init__(self
, parser
,
278 header_output
= '', decoder_output
= '', exec_output
= '',
279 decode_block
= '', has_decode_default
= False):
281 self
.header_output
= parser
.expandCpuSymbolsToString(header_output
)
282 self
.decoder_output
= parser
.expandCpuSymbolsToString(decoder_output
)
283 if isinstance(exec_output
, dict):
284 self
.exec_output
= exec_output
285 elif isinstance(exec_output
, str):
286 # If the exec_output arg is a single string, we replicate
287 # it for each of the CPU models, substituting and
288 # %(CPU_foo)s params appropriately.
289 self
.exec_output
= parser
.expandCpuSymbolsToDict(exec_output
)
290 self
.decode_block
= parser
.expandCpuSymbolsToString(decode_block
)
291 self
.has_decode_default
= has_decode_default
293 # Override '+' operator: generate a new GenCode object that
294 # concatenates all the individual strings in the operands.
295 def __add__(self
, other
):
297 for cpu
in self
.parser
.cpuModels
:
299 exec_output
[n
] = self
.exec_output
[n
] + other
.exec_output
[n
]
300 return GenCode(self
.parser
,
301 self
.header_output
+ other
.header_output
,
302 self
.decoder_output
+ other
.decoder_output
,
304 self
.decode_block
+ other
.decode_block
,
305 self
.has_decode_default
or other
.has_decode_default
)
307 # Prepend a string (typically a comment) to all the strings.
308 def prepend_all(self
, pre
):
309 self
.header_output
= pre
+ self
.header_output
310 self
.decoder_output
= pre
+ self
.decoder_output
311 self
.decode_block
= pre
+ self
.decode_block
312 for cpu
in self
.parser
.cpuModels
:
313 self
.exec_output
[cpu
.name
] = pre
+ self
.exec_output
[cpu
.name
]
315 # Wrap the decode block in a pair of strings (e.g., 'case foo:'
316 # and 'break;'). Used to build the big nested switch statement.
317 def wrap_decode_block(self
, pre
, post
= ''):
318 self
.decode_block
= pre
+ indent(self
.decode_block
) + post
320 #####################################################################
322 # Bitfield Operator Support
324 #####################################################################
326 bitOp1ArgRE
= re
.compile(r
'<\s*(\w+)\s*:\s*>')
328 bitOpWordRE
= re
.compile(r
'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
329 bitOpExprRE
= re
.compile(r
'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
331 def substBitOps(code
):
332 # first convert single-bit selectors to two-index form
333 # i.e., <n> --> <n:n>
334 code
= bitOp1ArgRE
.sub(r
'<\1:\1>', code
)
335 # simple case: selector applied to ID (name)
336 # i.e., foo<a:b> --> bits(foo, a, b)
337 code
= bitOpWordRE
.sub(r
'bits(\1, \2, \3)', code
)
338 # if selector is applied to expression (ending in ')'),
339 # we need to search backward for matching '('
340 match
= bitOpExprRE
.search(code
)
342 exprEnd
= match
.start()
346 if code
[here
] == '(':
348 elif code
[here
] == ')':
352 sys
.exit("Didn't find '('!")
354 newExpr
= r
'bits(%s, %s, %s)' % (code
[exprStart
:exprEnd
+1],
355 match
.group(1), match
.group(2))
356 code
= code
[:exprStart
] + newExpr
+ code
[match
.end():]
357 match
= bitOpExprRE
.search(code
)
361 #####################################################################
365 # The remaining code is the support for automatically extracting
366 # instruction characteristics from pseudocode.
368 #####################################################################
370 # Force the argument to be a list. Useful for flags, where a caller
371 # can specify a singleton flag or a list of flags. Also usful for
372 # converting tuples to lists so they can be modified.
374 if isinstance(arg
, list):
376 elif isinstance(arg
, tuple):
383 class Operand(object):
384 '''Base class for operand descriptors. An instance of this class
385 (or actually a class derived from this one) represents a specific
386 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
387 derived classes encapsulates the traits of a particular operand
388 type (e.g., "32-bit integer register").'''
390 def buildReadCode(self
, func
= None):
391 subst_dict
= {"name": self
.base_name
,
393 "reg_idx": self
.reg_spec
,
396 if hasattr(self
, 'src_reg_idx'):
397 subst_dict
['op_idx'] = self
.src_reg_idx
398 code
= self
.read_code
% subst_dict
399 if self
.size
!= self
.dflt_size
:
400 return '%s = bits(%s, %d, 0);\n' % \
401 (self
.base_name
, code
, self
.size
-1)
403 return '%s = %s;\n' % \
404 (self
.base_name
, code
)
406 def buildWriteCode(self
, func
= None):
407 if (self
.size
!= self
.dflt_size
and self
.is_signed
):
408 final_val
= 'sext<%d>(%s)' % (self
.size
, self
.base_name
)
410 final_val
= self
.base_name
411 subst_dict
= {"name": self
.base_name
,
413 "reg_idx": self
.reg_spec
,
416 "final_val": final_val
}
417 if hasattr(self
, 'dest_reg_idx'):
418 subst_dict
['op_idx'] = self
.dest_reg_idx
419 code
= self
.write_code
% subst_dict
424 if (traceData) { traceData->setData(final_val); }
425 }''' % (self
.dflt_ctype
, final_val
, code
)
427 def __init__(self
, parser
, full_name
, ext
, is_src
, is_dest
):
428 self
.full_name
= full_name
431 self
.is_dest
= is_dest
432 # The 'effective extension' (eff_ext) is either the actual
433 # extension, if one was explicitly provided, or the default.
437 self
.eff_ext
= self
.dflt_ext
439 self
.size
, self
.ctype
, self
.is_signed
= \
440 parser
.operandTypeMap
[self
.eff_ext
]
442 # note that mem_acc_size is undefined for non-mem operands...
443 # template must be careful not to use it if it doesn't apply.
445 self
.mem_acc_size
= self
.makeAccSize()
446 if self
.ctype
in ['Twin32_t', 'Twin64_t']:
447 self
.mem_acc_type
= 'Twin'
449 self
.mem_acc_type
= 'uint'
451 # Finalize additional fields (primarily code fields). This step
452 # is done separately since some of these fields may depend on the
453 # register index enumeration that hasn't been performed yet at the
454 # time of __init__().
456 self
.flags
= self
.getFlags()
457 self
.constructor
= self
.makeConstructor()
458 self
.op_decl
= self
.makeDecl()
461 self
.op_rd
= self
.makeRead()
462 self
.op_src_decl
= self
.makeDecl()
465 self
.op_src_decl
= ''
468 self
.op_wb
= self
.makeWrite()
469 self
.op_dest_decl
= self
.makeDecl()
472 self
.op_dest_decl
= ''
480 def isFloatReg(self
):
486 def isControlReg(self
):
490 # note the empty slice '[:]' gives us a copy of self.flags[0]
491 # instead of a reference to it
492 my_flags
= self
.flags
[0][:]
494 my_flags
+= self
.flags
[1]
496 my_flags
+= self
.flags
[2]
500 # Note that initializations in the declarations are solely
501 # to avoid 'uninitialized variable' errors from the compiler.
502 return self
.ctype
+ ' ' + self
.base_name
+ ' = 0;\n';
504 class IntRegOperand(Operand
):
511 def makeConstructor(self
):
514 c
+= '\n\t_srcRegIdx[%d] = %s;' % \
515 (self
.src_reg_idx
, self
.reg_spec
)
517 c
+= '\n\t_destRegIdx[%d] = %s;' % \
518 (self
.dest_reg_idx
, self
.reg_spec
)
522 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
523 error('Attempt to read integer register as FP')
524 if self
.read_code
!= None:
525 return self
.buildReadCode('readIntRegOperand')
526 if (self
.size
== self
.dflt_size
):
527 return '%s = xc->readIntRegOperand(this, %d);\n' % \
528 (self
.base_name
, self
.src_reg_idx
)
529 elif (self
.size
> self
.dflt_size
):
530 int_reg_val
= 'xc->readIntRegOperand(this, %d)' % \
533 int_reg_val
= 'sext<%d>(%s)' % (self
.dflt_size
, int_reg_val
)
534 return '%s = %s;\n' % (self
.base_name
, int_reg_val
)
536 return '%s = bits(xc->readIntRegOperand(this, %d), %d, 0);\n' % \
537 (self
.base_name
, self
.src_reg_idx
, self
.size
-1)
540 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
541 error('Attempt to write integer register as FP')
542 if self
.write_code
!= None:
543 return self
.buildWriteCode('setIntRegOperand')
544 if (self
.size
!= self
.dflt_size
and self
.is_signed
):
545 final_val
= 'sext<%d>(%s)' % (self
.size
, self
.base_name
)
547 final_val
= self
.base_name
551 xc->setIntRegOperand(this, %d, final_val);\n
552 if (traceData) { traceData->setData(final_val); }
553 }''' % (self
.dflt_ctype
, final_val
, self
.dest_reg_idx
)
556 class FloatRegOperand(Operand
):
560 def isFloatReg(self
):
563 def makeConstructor(self
):
566 c
+= '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
567 (self
.src_reg_idx
, self
.reg_spec
)
569 c
+= '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
570 (self
.dest_reg_idx
, self
.reg_spec
)
575 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
576 func
= 'readFloatRegOperand'
578 func
= 'readFloatRegOperandBits'
579 if (self
.size
!= self
.dflt_size
):
581 base
= 'xc->%s(this, %d)' % (func
, self
.src_reg_idx
)
582 if self
.read_code
!= None:
583 return self
.buildReadCode(func
)
585 return '%s = bits(%s, %d, 0);\n' % \
586 (self
.base_name
, base
, self
.size
-1)
588 return '%s = %s;\n' % (self
.base_name
, base
)
591 final_val
= self
.base_name
592 final_ctype
= self
.ctype
593 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
594 func
= 'setFloatRegOperand'
595 elif (self
.ctype
== 'uint32_t' or self
.ctype
== 'uint64_t'):
596 func
= 'setFloatRegOperandBits'
598 func
= 'setFloatRegOperandBits'
599 final_ctype
= 'uint%d_t' % self
.dflt_size
600 if (self
.size
!= self
.dflt_size
and self
.is_signed
):
601 final_val
= 'sext<%d>(%s)' % (self
.size
, self
.base_name
)
602 if self
.write_code
!= None:
603 return self
.buildWriteCode(func
)
607 xc->%s(this, %d, final_val);\n
608 if (traceData) { traceData->setData(final_val); }
609 }''' % (final_ctype
, final_val
, func
, self
.dest_reg_idx
)
612 class ControlRegOperand(Operand
):
616 def isControlReg(self
):
619 def makeConstructor(self
):
622 c
+= '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
623 (self
.src_reg_idx
, self
.reg_spec
)
625 c
+= '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
626 (self
.dest_reg_idx
, self
.reg_spec
)
631 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
632 error('Attempt to read control register as FP')
633 if self
.read_code
!= None:
634 return self
.buildReadCode('readMiscRegOperand')
635 base
= 'xc->readMiscRegOperand(this, %s)' % self
.src_reg_idx
636 if self
.size
== self
.dflt_size
:
637 return '%s = %s;\n' % (self
.base_name
, base
)
639 return '%s = bits(%s, %d, 0);\n' % \
640 (self
.base_name
, base
, self
.size
-1)
643 if (self
.ctype
== 'float' or self
.ctype
== 'double'):
644 error('Attempt to write control register as FP')
645 if self
.write_code
!= None:
646 return self
.buildWriteCode('setMiscRegOperand')
647 wb
= 'xc->setMiscRegOperand(this, %s, %s);\n' % \
648 (self
.dest_reg_idx
, self
.base_name
)
649 wb
+= 'if (traceData) { traceData->setData(%s); }' % \
653 class MemOperand(Operand
):
657 def makeConstructor(self
):
661 # Note that initializations in the declarations are solely
662 # to avoid 'uninitialized variable' errors from the compiler.
663 # Declare memory data variable.
664 if self
.ctype
in ['Twin32_t','Twin64_t']:
665 return "%s %s; %s.a = 0; %s.b = 0;\n" % \
666 (self
.ctype
, self
.base_name
, self
.base_name
, self
.base_name
)
667 return '%s %s = 0;\n' % (self
.ctype
, self
.base_name
)
670 if self
.read_code
!= None:
671 return self
.buildReadCode()
675 if self
.write_code
!= None:
676 return self
.buildWriteCode()
679 # Return the memory access size *in bits*, suitable for
680 # forming a type via "uint%d_t". Divide by 8 if you want bytes.
681 def makeAccSize(self
):
684 class PCOperand(Operand
):
685 def makeConstructor(self
):
689 return '%s = xc->readPC();\n' % self
.base_name
692 return 'xc->setPC(%s);\n' % self
.base_name
694 class UPCOperand(Operand
):
695 def makeConstructor(self
):
699 if self
.read_code
!= None:
700 return self
.buildReadCode('readMicroPC')
701 return '%s = xc->readMicroPC();\n' % self
.base_name
704 if self
.write_code
!= None:
705 return self
.buildWriteCode('setMicroPC')
706 return 'xc->setMicroPC(%s);\n' % self
.base_name
708 class NUPCOperand(Operand
):
709 def makeConstructor(self
):
713 if self
.read_code
!= None:
714 return self
.buildReadCode('readNextMicroPC')
715 return '%s = xc->readNextMicroPC();\n' % self
.base_name
718 if self
.write_code
!= None:
719 return self
.buildWriteCode('setNextMicroPC')
720 return 'xc->setNextMicroPC(%s);\n' % self
.base_name
722 class NPCOperand(Operand
):
723 def makeConstructor(self
):
727 if self
.read_code
!= None:
728 return self
.buildReadCode('readNextPC')
729 return '%s = xc->readNextPC();\n' % self
.base_name
732 if self
.write_code
!= None:
733 return self
.buildWriteCode('setNextPC')
734 return 'xc->setNextPC(%s);\n' % self
.base_name
736 class NNPCOperand(Operand
):
737 def makeConstructor(self
):
741 if self
.read_code
!= None:
742 return self
.buildReadCode('readNextNPC')
743 return '%s = xc->readNextNPC();\n' % self
.base_name
746 if self
.write_code
!= None:
747 return self
.buildWriteCode('setNextNPC')
748 return 'xc->setNextNPC(%s);\n' % self
.base_name
750 class OperandList(object):
751 '''Find all the operands in the given code block. Returns an operand
752 descriptor list (instance of class OperandList).'''
753 def __init__(self
, parser
, code
):
756 # delete comments so we don't match on reg specifiers inside
757 code
= commentRE
.sub('', code
)
758 # search for operands
761 match
= parser
.operandsRE
.search(code
, next_pos
)
763 # no more matches: we're done
766 # regexp groups are operand full name, base, and extension
767 (op_full
, op_base
, op_ext
) = op
768 # if the token following the operand is an assignment, this is
769 # a destination (LHS), else it's a source (RHS)
770 is_dest
= (assignRE
.match(code
, match
.end()) != None)
772 # see if we've already seen this one
773 op_desc
= self
.find_base(op_base
)
775 if op_desc
.ext
!= op_ext
:
776 error('Inconsistent extensions for operand %s' % \
778 op_desc
.is_src
= op_desc
.is_src
or is_src
779 op_desc
.is_dest
= op_desc
.is_dest
or is_dest
781 # new operand: create new descriptor
782 op_desc
= parser
.operandNameMap
[op_base
](parser
,
783 op_full
, op_ext
, is_src
, is_dest
)
785 # start next search after end of current match
786 next_pos
= match
.end()
788 # enumerate source & dest register operands... used in building
792 self
.numFPDestRegs
= 0
793 self
.numIntDestRegs
= 0
794 self
.memOperand
= None
795 for op_desc
in self
.items
:
798 op_desc
.src_reg_idx
= self
.numSrcRegs
801 op_desc
.dest_reg_idx
= self
.numDestRegs
802 self
.numDestRegs
+= 1
803 if op_desc
.isFloatReg():
804 self
.numFPDestRegs
+= 1
805 elif op_desc
.isIntReg():
806 self
.numIntDestRegs
+= 1
807 elif op_desc
.isMem():
809 error("Code block has more than one memory operand.")
810 self
.memOperand
= op_desc
811 if parser
.maxInstSrcRegs
< self
.numSrcRegs
:
812 parser
.maxInstSrcRegs
= self
.numSrcRegs
813 if parser
.maxInstDestRegs
< self
.numDestRegs
:
814 parser
.maxInstDestRegs
= self
.numDestRegs
815 # now make a final pass to finalize op_desc fields that may depend
816 # on the register enumeration
817 for op_desc
in self
.items
:
821 return len(self
.items
)
823 def __getitem__(self
, index
):
824 return self
.items
[index
]
826 def append(self
, op_desc
):
827 self
.items
.append(op_desc
)
828 self
.bases
[op_desc
.base_name
] = op_desc
830 def find_base(self
, base_name
):
831 # like self.bases[base_name], but returns None if not found
832 # (rather than raising exception)
833 return self
.bases
.get(base_name
)
835 # internal helper function for concat[Some]Attr{Strings|Lists}
836 def __internalConcatAttrs(self
, attr_name
, filter, result
):
837 for op_desc
in self
.items
:
839 result
+= getattr(op_desc
, attr_name
)
842 # return a single string that is the concatenation of the (string)
843 # values of the specified attribute for all operands
844 def concatAttrStrings(self
, attr_name
):
845 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, '')
847 # like concatAttrStrings, but only include the values for the operands
848 # for which the provided filter function returns true
849 def concatSomeAttrStrings(self
, filter, attr_name
):
850 return self
.__internalConcatAttrs
(attr_name
, filter, '')
852 # return a single list that is the concatenation of the (list)
853 # values of the specified attribute for all operands
854 def concatAttrLists(self
, attr_name
):
855 return self
.__internalConcatAttrs
(attr_name
, lambda x
: 1, [])
857 # like concatAttrLists, but only include the values for the operands
858 # for which the provided filter function returns true
859 def concatSomeAttrLists(self
, filter, attr_name
):
860 return self
.__internalConcatAttrs
(attr_name
, filter, [])
863 self
.items
.sort(lambda a
, b
: a
.sort_pri
- b
.sort_pri
)
865 class SubOperandList(OperandList
):
866 '''Find all the operands in the given code block. Returns an operand
867 descriptor list (instance of class OperandList).'''
868 def __init__(self
, parser
, code
, master_list
):
871 # delete comments so we don't match on reg specifiers inside
872 code
= commentRE
.sub('', code
)
873 # search for operands
876 match
= parser
.operandsRE
.search(code
, next_pos
)
878 # no more matches: we're done
881 # regexp groups are operand full name, base, and extension
882 (op_full
, op_base
, op_ext
) = op
883 # find this op in the master list
884 op_desc
= master_list
.find_base(op_base
)
886 error('Found operand %s which is not in the master list!' \
887 ' This is an internal error' % op_base
)
889 # See if we've already found this operand
890 op_desc
= self
.find_base(op_base
)
892 # if not, add a reference to it to this sub list
893 self
.append(master_list
.bases
[op_base
])
895 # start next search after end of current match
896 next_pos
= match
.end()
898 self
.memOperand
= None
899 for op_desc
in self
.items
:
902 error("Code block has more than one memory operand.")
903 self
.memOperand
= op_desc
905 # Regular expression object to match C++ comments
906 # (used in findOperands())
907 commentRE
= re
.compile(r
'//.*\n')
909 # Regular expression object to match assignment statements
910 # (used in findOperands())
911 assignRE
= re
.compile(r
'\s*=(?!=)', re
.MULTILINE
)
913 def makeFlagConstructor(flag_list
):
914 if len(flag_list
) == 0:
916 # filter out repeated flags
919 while i
< len(flag_list
):
920 if flag_list
[i
] == flag_list
[i
-1]:
926 code
= pre
+ string
.join(flag_list
, post
+ pre
) + post
929 # Assume all instruction flags are of the form 'IsFoo'
930 instFlagRE
= re
.compile(r
'Is.*')
932 # OpClass constants end in 'Op' except No_OpClass
933 opClassRE
= re
.compile(r
'.*Op|No_OpClass')
935 class InstObjParams(object):
936 def __init__(self
, parser
, mnem
, class_name
, base_class
= '',
937 snippets
= {}, opt_args
= []):
939 self
.class_name
= class_name
940 self
.base_class
= base_class
941 if not isinstance(snippets
, dict):
942 snippets
= {'code' : snippets
}
943 compositeCode
= ' '.join(map(str, snippets
.values()))
944 self
.snippets
= snippets
946 self
.operands
= OperandList(parser
, compositeCode
)
947 self
.constructor
= self
.operands
.concatAttrStrings('constructor')
948 self
.constructor
+= \
949 '\n\t_numSrcRegs = %d;' % self
.operands
.numSrcRegs
950 self
.constructor
+= \
951 '\n\t_numDestRegs = %d;' % self
.operands
.numDestRegs
952 self
.constructor
+= \
953 '\n\t_numFPDestRegs = %d;' % self
.operands
.numFPDestRegs
954 self
.constructor
+= \
955 '\n\t_numIntDestRegs = %d;' % self
.operands
.numIntDestRegs
956 self
.flags
= self
.operands
.concatAttrLists('flags')
958 # Make a basic guess on the operand class (function unit type).
959 # These are good enough for most cases, and can be overridden
961 if 'IsStore' in self
.flags
:
962 self
.op_class
= 'MemWriteOp'
963 elif 'IsLoad' in self
.flags
or 'IsPrefetch' in self
.flags
:
964 self
.op_class
= 'MemReadOp'
965 elif 'IsFloating' in self
.flags
:
966 self
.op_class
= 'FloatAddOp'
968 self
.op_class
= 'IntAluOp'
970 # Optional arguments are assumed to be either StaticInst flags
971 # or an OpClass value. To avoid having to import a complete
972 # list of these values to match against, we do it ad-hoc
975 if instFlagRE
.match(oa
):
976 self
.flags
.append(oa
)
977 elif opClassRE
.match(oa
):
980 error('InstObjParams: optional arg "%s" not recognized '
981 'as StaticInst::Flag or OpClass.' % oa
)
983 # add flag initialization to contructor here to include
984 # any flags added via opt_args
985 self
.constructor
+= makeFlagConstructor(self
.flags
)
987 # if 'IsFloating' is set, add call to the FP enable check
988 # function (which should be provided by isa_desc via a declare)
989 if 'IsFloating' in self
.flags
:
990 self
.fp_enable_check
= 'fault = checkFpEnableFault(xc);'
992 self
.fp_enable_check
= ''
995 # Stack: a simple stack object. Used for both formats (formatStack)
996 # and default cases (defaultStack). Simply wraps a list to give more
997 # stack-like syntax and enable initialization with an argument list
998 # (as opposed to an argument that's a list).
1001 def __init__(self
, *items
):
1002 list.__init
__(self
, items
)
1004 def push(self
, item
):
1010 #######################
1012 # Output file template
1017 * DO NOT EDIT THIS FILE!!!
1019 * It was automatically generated from the ISA description in %(filename)s
1026 namespace %(namespace)s {
1028 %(namespace_output)s
1030 } // namespace %(namespace)s
1035 max_inst_regs_template
= '''
1037 * DO NOT EDIT THIS FILE!!!
1039 * It was automatically generated from the ISA description in %(filename)s
1042 namespace %(namespace)s {
1044 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
1045 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
1047 } // namespace %(namespace)s
1051 class ISAParser(Grammar
):
1052 def __init__(self
, output_dir
, cpu_models
):
1053 super(ISAParser
, self
).__init
__()
1054 self
.output_dir
= output_dir
1056 self
.cpuModels
= cpu_models
1058 # variable to hold templates
1059 self
.templateMap
= {}
1061 # This dictionary maps format name strings to Format objects.
1065 self
.formatStack
= Stack(NoFormat())
1067 # The default case stack.
1068 self
.defaultStack
= Stack(None)
1070 # Stack that tracks current file and line number. Each
1071 # element is a tuple (filename, lineno) that records the
1072 # *current* filename and the line number in the *previous*
1073 # file where it was included.
1074 self
.fileNameStack
= Stack()
1076 symbols
= ('makeList', 're', 'string')
1077 self
.exportContext
= dict([(s
, eval(s
)) for s
in symbols
])
1079 self
.maxInstSrcRegs
= 0
1080 self
.maxInstDestRegs
= 0
1082 #####################################################################
1086 # The PLY lexer module takes two things as input:
1087 # - A list of token names (the string list 'tokens')
1088 # - A regular expression describing a match for each token. The
1089 # regexp for token FOO can be provided in two ways:
1090 # - as a string variable named t_FOO
1091 # - as the doc string for a function named t_FOO. In this case,
1092 # the function is also executed, allowing an action to be
1093 # associated with each token match.
1095 #####################################################################
1097 # Reserved words. These are listed separately as they are matched
1098 # using the same regexp as generic IDs, but distinguished in the
1099 # t_ID() function. The PLY documentation suggests this approach.
1101 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
1102 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
1103 'OUTPUT', 'SIGNED', 'TEMPLATE'
1106 # List of tokens. The lex module requires this.
1107 tokens
= reserved
+ (
1120 # ( ) [ ] { } < > , ; . : :: *
1122 'LBRACKET', 'RBRACKET',
1124 'LESS', 'GREATER', 'EQUALS',
1125 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON',
1128 # C preprocessor directives
1131 # The following are matched but never returned. commented out to
1132 # suppress PLY warning
1140 # Regular expressions for token matching
1157 # Identifiers and reserved words
1160 reserved_map
[r
.lower()] = r
1164 t
.type = self
.reserved_map
.get(t
.value
, 'ID')
1168 def t_INTLIT(self
, t
):
1169 r
'-?(0x[\da-fA-F]+)|\d+'
1171 t
.value
= int(t
.value
,0)
1173 error(t
, 'Integer value "%s" too large' % t
.value
)
1177 # String literal. Note that these use only single quotes, and
1178 # can span multiple lines.
1179 def t_STRLIT(self
, t
):
1182 t
.value
= t
.value
[1:-1]
1183 t
.lexer
.lineno
+= t
.value
.count('\n')
1187 # "Code literal"... like a string literal, but delimiters are
1188 # '{{' and '}}' so they get formatted nicely under emacs c-mode
1189 def t_CODELIT(self
, t
):
1190 r
"(?m)\{\{([^\}]|}(?!\}))+\}\}"
1192 t
.value
= t
.value
[2:-2]
1193 t
.lexer
.lineno
+= t
.value
.count('\n')
1196 def t_CPPDIRECTIVE(self
, t
):
1198 t
.lexer
.lineno
+= t
.value
.count('\n')
1201 def t_NEWFILE(self
, t
):
1202 r
'^\#\#newfile\s+"[\w/.-]*"'
1203 self
.fileNameStack
.push((t
.value
[11:-1], t
.lexer
.lineno
))
1206 def t_ENDFILE(self
, t
):
1208 (old_filename
, t
.lexer
.lineno
) = self
.fileNameStack
.pop()
1211 # The functions t_NEWLINE, t_ignore, and t_error are
1212 # special for the lex module.
1216 def t_NEWLINE(self
, t
):
1218 t
.lexer
.lineno
+= t
.value
.count('\n')
1221 def t_comment(self
, t
):
1224 # Completely ignored characters
1225 t_ignore
= ' \t\x0c'
1228 def t_error(self
, t
):
1229 error(t
, "illegal character '%s'" % t
.value
[0])
1232 #####################################################################
1236 # Every function whose name starts with 'p_' defines a grammar
1237 # rule. The rule is encoded in the function's doc string, while
1238 # the function body provides the action taken when the rule is
1239 # matched. The argument to each function is a list of the values
1240 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the
1241 # symbols on the RHS. For tokens, the value is copied from the
1242 # t.value attribute provided by the lexer. For non-terminals, the
1243 # value is assigned by the producing rule; i.e., the job of the
1244 # grammar rule function is to set the value for the non-terminal
1245 # on the LHS (by assigning to t[0]).
1246 #####################################################################
1248 # The LHS of the first grammar rule is used as the start symbol
1249 # (in this case, 'specification'). Note that this rule enforces
1250 # that there will be exactly one namespace declaration, with 0 or
1251 # more global defs/decls before and after it. The defs & decls
1252 # before the namespace decl will be outside the namespace; those
1253 # after will be inside. The decoder function is always inside the
1255 def p_specification(self
, t
):
1256 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
1259 namespace
= isa_name
+ "Inst"
1260 # wrap the decode block as a function definition
1261 t
[4].wrap_decode_block('''
1263 %(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst)
1265 using namespace %(namespace)s;
1267 # both the latter output blocks and the decode block are in
1269 namespace_code
= t
[3] + t
[4]
1270 # pass it all back to the caller of yacc.parse()
1271 t
[0] = (isa_name
, namespace
, global_code
, namespace_code
)
1273 # ISA name declaration looks like "namespace <foo>;"
1274 def p_name_decl(self
, t
):
1275 'name_decl : NAMESPACE ID SEMI'
1278 # 'opt_defs_and_outputs' is a possibly empty sequence of
1279 # def and/or output statements.
1280 def p_opt_defs_and_outputs_0(self
, t
):
1281 'opt_defs_and_outputs : empty'
1282 t
[0] = GenCode(self
)
1284 def p_opt_defs_and_outputs_1(self
, t
):
1285 'opt_defs_and_outputs : defs_and_outputs'
1288 def p_defs_and_outputs_0(self
, t
):
1289 'defs_and_outputs : def_or_output'
1292 def p_defs_and_outputs_1(self
, t
):
1293 'defs_and_outputs : defs_and_outputs def_or_output'
1296 # The list of possible definition/output statements.
1297 def p_def_or_output(self
, t
):
1298 '''def_or_output : def_format
1300 | def_bitfield_struct
1310 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1311 # directly to the appropriate output section.
1313 # Massage output block by substituting in template definitions and
1314 # bit operators. We handle '%'s embedded in the string that don't
1315 # indicate template substitutions (or CPU-specific symbols, which
1316 # get handled in GenCode) by doubling them first so that the
1317 # format operation will reduce them back to single '%'s.
1318 def process_output(self
, s
):
1319 s
= self
.protectNonSubstPercents(s
)
1320 # protects cpu-specific symbols too
1321 s
= self
.protectCpuSymbols(s
)
1322 return substBitOps(s
% self
.templateMap
)
1324 def p_output_header(self
, t
):
1325 'output_header : OUTPUT HEADER CODELIT SEMI'
1326 t
[0] = GenCode(self
, header_output
= self
.process_output(t
[3]))
1328 def p_output_decoder(self
, t
):
1329 'output_decoder : OUTPUT DECODER CODELIT SEMI'
1330 t
[0] = GenCode(self
, decoder_output
= self
.process_output(t
[3]))
1332 def p_output_exec(self
, t
):
1333 'output_exec : OUTPUT EXEC CODELIT SEMI'
1334 t
[0] = GenCode(self
, exec_output
= self
.process_output(t
[3]))
1336 # global let blocks 'let {{...}}' (Python code blocks) are
1337 # executed directly when seen. Note that these execute in a
1338 # special variable context 'exportContext' to prevent the code
1339 # from polluting this script's namespace.
1340 def p_global_let(self
, t
):
1341 'global_let : LET CODELIT SEMI'
1342 self
.updateExportContext()
1343 self
.exportContext
["header_output"] = ''
1344 self
.exportContext
["decoder_output"] = ''
1345 self
.exportContext
["exec_output"] = ''
1346 self
.exportContext
["decode_block"] = ''
1348 exec fixPythonIndentation(t
[2]) in self
.exportContext
1349 except Exception, exc
:
1352 error(t
, 'error: %s in global let block "%s".' % (exc
, t
[2]))
1353 t
[0] = GenCode(self
,
1354 header_output
=self
.exportContext
["header_output"],
1355 decoder_output
=self
.exportContext
["decoder_output"],
1356 exec_output
=self
.exportContext
["exec_output"],
1357 decode_block
=self
.exportContext
["decode_block"])
1359 # Define the mapping from operand type extensions to C++ types and
1360 # bit widths (stored in operandTypeMap).
1361 def p_def_operand_types(self
, t
):
1362 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1364 user_dict
= eval('{' + t
[3] + '}')
1365 except Exception, exc
:
1369 'error: %s in def operand_types block "%s".' % (exc
, t
[3]))
1370 self
.buildOperandTypeMap(user_dict
, t
.lexer
.lineno
)
1371 t
[0] = GenCode(self
) # contributes nothing to the output C++ file
1373 # Define the mapping from operand names to operand classes and
1374 # other traits. Stored in operandNameMap.
1375 def p_def_operands(self
, t
):
1376 'def_operands : DEF OPERANDS CODELIT SEMI'
1377 if not hasattr(self
, 'operandTypeMap'):
1378 error(t
, 'error: operand types must be defined before operands')
1380 user_dict
= eval('{' + t
[3] + '}', self
.exportContext
)
1381 except Exception, exc
:
1384 error(t
, 'error: %s in def operands block "%s".' % (exc
, t
[3]))
1385 self
.buildOperandNameMap(user_dict
, t
.lexer
.lineno
)
1386 t
[0] = GenCode(self
) # contributes nothing to the output C++ file
1388 # A bitfield definition looks like:
1389 # 'def [signed] bitfield <ID> [<first>:<last>]'
1390 # This generates a preprocessor macro in the output file.
1391 def p_def_bitfield_0(self
, t
):
1392 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
1393 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[8])
1394 if (t
[2] == 'signed'):
1395 expr
= 'sext<%d>(%s)' % (t
[6] - t
[8] + 1, expr
)
1396 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1397 t
[0] = GenCode(self
, header_output
=hash_define
)
1399 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
1400 def p_def_bitfield_1(self
, t
):
1401 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
1402 expr
= 'bits(machInst, %2d, %2d)' % (t
[6], t
[6])
1403 if (t
[2] == 'signed'):
1404 expr
= 'sext<%d>(%s)' % (1, expr
)
1405 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1406 t
[0] = GenCode(self
, header_output
=hash_define
)
1408 # alternate form for structure member: 'def bitfield <ID> <ID>'
1409 def p_def_bitfield_struct(self
, t
):
1410 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI'
1412 error(t
, 'error: structure bitfields are always unsigned.')
1413 expr
= 'machInst.%s' % t
[5]
1414 hash_define
= '#undef %s\n#define %s\t%s\n' % (t
[4], t
[4], expr
)
1415 t
[0] = GenCode(self
, header_output
=hash_define
)
1417 def p_id_with_dot_0(self
, t
):
1421 def p_id_with_dot_1(self
, t
):
1422 'id_with_dot : ID DOT id_with_dot'
1423 t
[0] = t
[1] + t
[2] + t
[3]
1425 def p_opt_signed_0(self
, t
):
1426 'opt_signed : SIGNED'
1429 def p_opt_signed_1(self
, t
):
1430 'opt_signed : empty'
1433 def p_def_template(self
, t
):
1434 'def_template : DEF TEMPLATE ID CODELIT SEMI'
1435 self
.templateMap
[t
[3]] = Template(self
, t
[4])
1436 t
[0] = GenCode(self
)
1438 # An instruction format definition looks like
1439 # "def format <fmt>(<params>) {{...}};"
1440 def p_def_format(self
, t
):
1441 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1442 (id, params
, code
) = (t
[3], t
[5], t
[7])
1443 self
.defFormat(id, params
, code
, t
.lexer
.lineno
)
1444 t
[0] = GenCode(self
)
1446 # The formal parameter list for an instruction format is a
1447 # possibly empty list of comma-separated parameters. Positional
1448 # (standard, non-keyword) parameters must come first, followed by
1449 # keyword parameters, followed by a '*foo' parameter that gets
1450 # excess positional arguments (as in Python). Each of these three
1451 # parameter categories is optional.
1453 # Note that we do not support the '**foo' parameter for collecting
1454 # otherwise undefined keyword args. Otherwise the parameter list
1455 # is (I believe) identical to what is supported in Python.
1457 # The param list generates a tuple, where the first element is a
1458 # list of the positional params and the second element is a dict
1459 # containing the keyword params.
1460 def p_param_list_0(self
, t
):
1461 'param_list : positional_param_list COMMA nonpositional_param_list'
1464 def p_param_list_1(self
, t
):
1465 '''param_list : positional_param_list
1466 | nonpositional_param_list'''
1469 def p_positional_param_list_0(self
, t
):
1470 'positional_param_list : empty'
1473 def p_positional_param_list_1(self
, t
):
1474 'positional_param_list : ID'
1477 def p_positional_param_list_2(self
, t
):
1478 'positional_param_list : positional_param_list COMMA ID'
1479 t
[0] = t
[1] + [t
[3]]
1481 def p_nonpositional_param_list_0(self
, t
):
1482 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
1485 def p_nonpositional_param_list_1(self
, t
):
1486 '''nonpositional_param_list : keyword_param_list
1487 | excess_args_param'''
1490 def p_keyword_param_list_0(self
, t
):
1491 'keyword_param_list : keyword_param'
1494 def p_keyword_param_list_1(self
, t
):
1495 'keyword_param_list : keyword_param_list COMMA keyword_param'
1496 t
[0] = t
[1] + [t
[3]]
1498 def p_keyword_param(self
, t
):
1499 'keyword_param : ID EQUALS expr'
1500 t
[0] = t
[1] + ' = ' + t
[3].__repr
__()
1502 def p_excess_args_param(self
, t
):
1503 'excess_args_param : ASTERISK ID'
1504 # Just concatenate them: '*ID'. Wrap in list to be consistent
1505 # with positional_param_list and keyword_param_list.
1506 t
[0] = [t
[1] + t
[2]]
1508 # End of format definition-related rules.
1512 # A decode block looks like:
1513 # decode <field1> [, <field2>]* [default <inst>] { ... }
1515 def p_decode_block(self
, t
):
1516 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
1517 default_defaults
= self
.defaultStack
.pop()
1519 # use the "default defaults" only if there was no explicit
1520 # default statement in decode_stmt_list
1521 if not codeObj
.has_decode_default
:
1522 codeObj
+= default_defaults
1523 codeObj
.wrap_decode_block('switch (%s) {\n' % t
[2], '}\n')
1526 # The opt_default statement serves only to push the "default
1527 # defaults" onto defaultStack. This value will be used by nested
1528 # decode blocks, and used and popped off when the current
1529 # decode_block is processed (in p_decode_block() above).
1530 def p_opt_default_0(self
, t
):
1531 'opt_default : empty'
1532 # no default specified: reuse the one currently at the top of
1534 self
.defaultStack
.push(self
.defaultStack
.top())
1535 # no meaningful value returned
1538 def p_opt_default_1(self
, t
):
1539 'opt_default : DEFAULT inst'
1540 # push the new default
1542 codeObj
.wrap_decode_block('\ndefault:\n', 'break;\n')
1543 self
.defaultStack
.push(codeObj
)
1544 # no meaningful value returned
1547 def p_decode_stmt_list_0(self
, t
):
1548 'decode_stmt_list : decode_stmt'
1551 def p_decode_stmt_list_1(self
, t
):
1552 'decode_stmt_list : decode_stmt decode_stmt_list'
1553 if (t
[1].has_decode_default
and t
[2].has_decode_default
):
1554 error(t
, 'Two default cases in decode block')
1558 # Decode statement rules
1560 # There are four types of statements allowed in a decode block:
1561 # 1. Format blocks 'format <foo> { ... }'
1562 # 2. Nested decode blocks
1563 # 3. Instruction definitions.
1564 # 4. C preprocessor directives.
1567 # Preprocessor directives found in a decode statement list are
1568 # passed through to the output, replicated to all of the output
1569 # code streams. This works well for ifdefs, so we can ifdef out
1570 # both the declarations and the decode cases generated by an
1571 # instruction definition. Handling them as part of the grammar
1572 # makes it easy to keep them in the right place with respect to
1573 # the code generated by the other statements.
1574 def p_decode_stmt_cpp(self
, t
):
1575 'decode_stmt : CPPDIRECTIVE'
1576 t
[0] = GenCode(self
, t
[1], t
[1], t
[1], t
[1])
1578 # A format block 'format <foo> { ... }' sets the default
1579 # instruction format used to handle instruction definitions inside
1580 # the block. This format can be overridden by using an explicit
1581 # format on the instruction definition or with a nested format
1583 def p_decode_stmt_format(self
, t
):
1584 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
1585 # The format will be pushed on the stack when 'push_format_id'
1586 # is processed (see below). Once the parser has recognized
1587 # the full production (though the right brace), we're done
1588 # with the format, so now we can pop it.
1589 self
.formatStack
.pop()
1592 # This rule exists so we can set the current format (& push the
1593 # stack) when we recognize the format name part of the format
1595 def p_push_format_id(self
, t
):
1596 'push_format_id : ID'
1598 self
.formatStack
.push(self
.formatMap
[t
[1]])
1599 t
[0] = ('', '// format %s' % t
[1])
1601 error(t
, 'instruction format "%s" not defined.' % t
[1])
1603 # Nested decode block: if the value of the current field matches
1604 # the specified constant, do a nested decode on some other field.
1605 def p_decode_stmt_decode(self
, t
):
1606 'decode_stmt : case_label COLON decode_block'
1609 # just wrap the decoding code from the block as a case in the
1610 # outer switch statement.
1611 codeObj
.wrap_decode_block('\n%s:\n' % label
)
1612 codeObj
.has_decode_default
= (label
== 'default')
1615 # Instruction definition (finally!).
1616 def p_decode_stmt_inst(self
, t
):
1617 'decode_stmt : case_label COLON inst SEMI'
1620 codeObj
.wrap_decode_block('\n%s:' % label
, 'break;\n')
1621 codeObj
.has_decode_default
= (label
== 'default')
1624 # The case label is either a list of one or more constants or
1626 def p_case_label_0(self
, t
):
1627 'case_label : intlit_list'
1628 def make_case(intlit
):
1630 return 'case ULL(%#x)' % intlit
1632 return 'case %#x' % intlit
1633 t
[0] = ': '.join(map(make_case
, t
[1]))
1635 def p_case_label_1(self
, t
):
1636 'case_label : DEFAULT'
1640 # The constant list for a decode case label must be non-empty, but
1641 # may have one or more comma-separated integer literals in it.
1643 def p_intlit_list_0(self
, t
):
1644 'intlit_list : INTLIT'
1647 def p_intlit_list_1(self
, t
):
1648 'intlit_list : intlit_list COMMA INTLIT'
1652 # Define an instruction using the current instruction format
1653 # (specified by an enclosing format block).
1654 # "<mnemonic>(<args>)"
1655 def p_inst_0(self
, t
):
1656 'inst : ID LPAREN arg_list RPAREN'
1657 # Pass the ID and arg list to the current format class to deal with.
1658 currentFormat
= self
.formatStack
.top()
1659 codeObj
= currentFormat
.defineInst(self
, t
[1], t
[3], t
.lexer
.lineno
)
1660 args
= ','.join(map(str, t
[3]))
1661 args
= re
.sub('(?m)^', '//', args
)
1662 args
= re
.sub('^//', '', args
)
1663 comment
= '\n// %s::%s(%s)\n' % (currentFormat
.id, t
[1], args
)
1664 codeObj
.prepend_all(comment
)
1667 # Define an instruction using an explicitly specified format:
1668 # "<fmt>::<mnemonic>(<args>)"
1669 def p_inst_1(self
, t
):
1670 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1672 format
= self
.formatMap
[t
[1]]
1674 error(t
, 'instruction format "%s" not defined.' % t
[1])
1676 codeObj
= format
.defineInst(self
, t
[3], t
[5], t
.lexer
.lineno
)
1677 comment
= '\n// %s::%s(%s)\n' % (t
[1], t
[3], t
[5])
1678 codeObj
.prepend_all(comment
)
1681 # The arg list generates a tuple, where the first element is a
1682 # list of the positional args and the second element is a dict
1683 # containing the keyword args.
1684 def p_arg_list_0(self
, t
):
1685 'arg_list : positional_arg_list COMMA keyword_arg_list'
1686 t
[0] = ( t
[1], t
[3] )
1688 def p_arg_list_1(self
, t
):
1689 'arg_list : positional_arg_list'
1692 def p_arg_list_2(self
, t
):
1693 'arg_list : keyword_arg_list'
1696 def p_positional_arg_list_0(self
, t
):
1697 'positional_arg_list : empty'
1700 def p_positional_arg_list_1(self
, t
):
1701 'positional_arg_list : expr'
1704 def p_positional_arg_list_2(self
, t
):
1705 'positional_arg_list : positional_arg_list COMMA expr'
1706 t
[0] = t
[1] + [t
[3]]
1708 def p_keyword_arg_list_0(self
, t
):
1709 'keyword_arg_list : keyword_arg'
1712 def p_keyword_arg_list_1(self
, t
):
1713 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
1717 def p_keyword_arg(self
, t
):
1718 'keyword_arg : ID EQUALS expr'
1719 t
[0] = { t
[1] : t
[3] }
1722 # Basic expressions. These constitute the argument values of
1723 # "function calls" (i.e. instruction definitions in the decode
1724 # block) and default values for formal parameters of format
1727 # Right now, these are either strings, integers, or (recursively)
1728 # lists of exprs (using Python square-bracket list syntax). Note
1729 # that bare identifiers are trated as string constants here (since
1730 # there isn't really a variable namespace to refer to).
1732 def p_expr_0(self
, t
):
1739 def p_expr_1(self
, t
):
1740 '''expr : LBRACKET list_expr RBRACKET'''
1743 def p_list_expr_0(self
, t
):
1747 def p_list_expr_1(self
, t
):
1748 'list_expr : list_expr COMMA expr'
1749 t
[0] = t
[1] + [t
[3]]
1751 def p_list_expr_2(self
, t
):
1756 # Empty production... use in other rules for readability.
1758 def p_empty(self
, t
):
1762 # Parse error handler. Note that the argument here is the
1763 # offending *token*, not a grammar symbol (hence the need to use
1765 def p_error(self
, t
):
1767 error(t
, "syntax error at '%s'" % t
.value
)
1769 error("unknown syntax error")
1771 # END OF GRAMMAR RULES
1773 def updateExportContext(self
):
1775 # create a continuation that allows us to grab the current parser
1776 def wrapInstObjParams(*args
):
1777 return InstObjParams(self
, *args
)
1778 self
.exportContext
['InstObjParams'] = wrapInstObjParams
1779 self
.exportContext
.update(self
.templateMap
)
1781 def defFormat(self
, id, params
, code
, lineno
):
1782 '''Define a new format'''
1784 # make sure we haven't already defined this one
1785 if id in self
.formatMap
:
1786 error(lineno
, 'format %s redefined.' % id)
1788 # create new object and store in global map
1789 self
.formatMap
[id] = Format(id, params
, code
)
1791 def expandCpuSymbolsToDict(self
, template
):
1792 '''Expand template with CPU-specific references into a
1793 dictionary with an entry for each CPU model name. The entry
1794 key is the model name and the corresponding value is the
1795 template with the CPU-specific refs substituted for that
1798 # Protect '%'s that don't go with CPU-specific terms
1799 t
= re
.sub(r
'%(?!\(CPU_)', '%%', template
)
1801 for cpu
in self
.cpuModels
:
1802 result
[cpu
.name
] = t
% cpu
.strings
1805 def expandCpuSymbolsToString(self
, template
):
1806 '''*If* the template has CPU-specific references, return a
1807 single string containing a copy of the template for each CPU
1808 model with the corresponding values substituted in. If the
1809 template has no CPU-specific references, it is returned
1812 if template
.find('%(CPU_') != -1:
1813 return reduce(lambda x
,y
: x
+y
,
1814 self
.expandCpuSymbolsToDict(template
).values())
1818 def protectCpuSymbols(self
, template
):
1819 '''Protect CPU-specific references by doubling the
1820 corresponding '%'s (in preparation for substituting a different
1821 set of references into the template).'''
1823 return re
.sub(r
'%(?=\(CPU_)', '%%', template
)
1825 def protectNonSubstPercents(self
, s
):
1826 '''Protect any non-dict-substitution '%'s in a format string
1827 (i.e. those not followed by '(')'''
1829 return re
.sub(r
'%(?!\()', '%%', s
)
1831 def buildOperandTypeMap(self
, user_dict
, lineno
):
1832 """Generate operandTypeMap from the user's 'def operand_types'
1835 for (ext
, (desc
, size
)) in user_dict
.iteritems():
1836 if desc
== 'signed int':
1837 ctype
= 'int%d_t' % size
1839 elif desc
== 'unsigned int':
1840 ctype
= 'uint%d_t' % size
1842 elif desc
== 'float':
1843 is_signed
= 1 # shouldn't really matter
1848 elif desc
== 'twin64 int':
1851 elif desc
== 'twin32 int':
1855 error(parser
, lineno
,
1856 'Unrecognized type description "%s" in user_dict')
1857 operand_type
[ext
] = (size
, ctype
, is_signed
)
1859 self
.operandTypeMap
= operand_type
1861 def buildOperandNameMap(self
, user_dict
, lineno
):
1863 for op_name
, val
in user_dict
.iteritems():
1864 base_cls_name
, dflt_ext
, reg_spec
, flags
, sort_pri
= val
[:5]
1875 'error: too many attributes for operand "%s"' %
1878 (dflt_size
, dflt_ctype
, dflt_is_signed
) = \
1879 self
.operandTypeMap
[dflt_ext
]
1880 # Canonical flag structure is a triple of lists, where each list
1881 # indicates the set of flags implied by this operand always, when
1882 # used as a source, and when used as a dest, respectively.
1883 # For simplicity this can be initialized using a variety of fairly
1884 # obvious shortcuts; we convert these to canonical form here.
1886 # no flags specified (e.g., 'None')
1887 flags
= ( [], [], [] )
1888 elif isinstance(flags
, str):
1889 # a single flag: assumed to be unconditional
1890 flags
= ( [ flags
], [], [] )
1891 elif isinstance(flags
, list):
1892 # a list of flags: also assumed to be unconditional
1893 flags
= ( flags
, [], [] )
1894 elif isinstance(flags
, tuple):
1895 # it's a tuple: it should be a triple,
1896 # but each item could be a single string or a list
1897 (uncond_flags
, src_flags
, dest_flags
) = flags
1898 flags
= (makeList(uncond_flags
),
1899 makeList(src_flags
), makeList(dest_flags
))
1900 # Accumulate attributes of new operand class in tmp_dict
1902 for attr
in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
1903 'dflt_size', 'dflt_ctype', 'dflt_is_signed',
1904 'read_code', 'write_code'):
1905 tmp_dict
[attr
] = eval(attr
)
1906 tmp_dict
['base_name'] = op_name
1907 # New class name will be e.g. "IntReg_Ra"
1908 cls_name
= base_cls_name
+ '_' + op_name
1909 # Evaluate string arg to get class object. Note that the
1910 # actual base class for "IntReg" is "IntRegOperand", i.e. we
1911 # have to append "Operand".
1913 base_cls
= eval(base_cls_name
+ 'Operand')
1916 'error: unknown operand base class "%s"' % base_cls_name
)
1917 # The following statement creates a new class called
1918 # <cls_name> as a subclass of <base_cls> with the attributes
1919 # in tmp_dict, just as if we evaluated a class declaration.
1920 operand_name
[op_name
] = type(cls_name
, (base_cls
,), tmp_dict
)
1922 self
.operandNameMap
= operand_name
1924 # Define operand variables.
1925 operands
= user_dict
.keys()
1927 operandsREString
= (r
'''
1928 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
1929 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
1930 (?![\w\.]) # neg. lookahead assertion: prevent partial matches
1932 % string
.join(operands
, '|'))
1934 self
.operandsRE
= re
.compile(operandsREString
, re
.MULTILINE|re
.VERBOSE
)
1936 # Same as operandsREString, but extension is mandatory, and only two
1937 # groups are returned (base and ext, not full name as above).
1938 # Used for subtituting '_' for '.' to make C++ identifiers.
1939 operandsWithExtREString
= (r
'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
1940 % string
.join(operands
, '|'))
1942 self
.operandsWithExtRE
= \
1943 re
.compile(operandsWithExtREString
, re
.MULTILINE
)
1945 def substMungedOpNames(self
, code
):
1946 '''Munge operand names in code string to make legal C++
1947 variable names. This means getting rid of the type extension
1948 if any. Will match base_name attribute of Operand object.)'''
1949 return self
.operandsWithExtRE
.sub(r
'\1', code
)
1951 def mungeSnippet(self
, s
):
1952 '''Fix up code snippets for final substitution in templates.'''
1953 if isinstance(s
, str):
1954 return self
.substMungedOpNames(substBitOps(s
))
1958 def update_if_needed(self
, file, contents
):
1959 '''Update the output file only if the new contents are
1960 different from the current contents. Minimizes the files that
1961 need to be rebuilt after minor changes.'''
1963 file = os
.path
.join(self
.output_dir
, file)
1965 if os
.access(file, os
.R_OK
):
1967 old_contents
= f
.read()
1969 if contents
!= old_contents
:
1970 print 'Updating', file
1971 os
.remove(file) # in case it's write-protected
1974 print 'File', file, 'is unchanged'
1976 print 'Generating', file
1983 # This regular expression matches '##include' directives
1984 includeRE
= re
.compile(r
'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
1987 def replace_include(self
, matchobj
, dirname
):
1988 """Function to replace a matched '##include' directive with the
1989 contents of the specified file (with nested ##includes
1990 replaced recursively). 'matchobj' is an re match object
1991 (from a match of includeRE) and 'dirname' is the directory
1992 relative to which the file path should be resolved."""
1994 fname
= matchobj
.group('filename')
1995 full_fname
= os
.path
.normpath(os
.path
.join(dirname
, fname
))
1996 contents
= '##newfile "%s"\n%s\n##endfile\n' % \
1997 (full_fname
, self
.read_and_flatten(full_fname
))
2000 def read_and_flatten(self
, filename
):
2001 """Read a file and recursively flatten nested '##include' files."""
2003 current_dir
= os
.path
.dirname(filename
)
2005 contents
= open(filename
).read()
2007 error('Error including file "%s"' % filename
)
2009 self
.fileNameStack
.push((filename
, 0))
2011 # Find any includes and include them
2012 def replace(matchobj
):
2013 return self
.replace_include(matchobj
, current_dir
)
2014 contents
= self
.includeRE
.sub(replace
, contents
)
2016 self
.fileNameStack
.pop()
2019 def _parse_isa_desc(self
, isa_desc_file
):
2020 '''Read in and parse the ISA description.'''
2022 # Read file and (recursively) all included files into a string.
2023 # PLY requires that the input be in a single string so we have to
2025 isa_desc
= self
.read_and_flatten(isa_desc_file
)
2027 # Initialize filename stack with outer file.
2028 self
.fileNameStack
.push((isa_desc_file
, 0))
2031 (isa_name
, namespace
, global_code
, namespace_code
) = \
2032 self
.parse(isa_desc
)
2034 # grab the last three path components of isa_desc_file to put in
2036 filename
= '/'.join(isa_desc_file
.split('/')[-3:])
2038 # generate decoder.hh
2039 includes
= '#include "base/bitfield.hh" // for bitfield support'
2040 global_output
= global_code
.header_output
2041 namespace_output
= namespace_code
.header_output
2042 decode_function
= ''
2043 self
.update_if_needed('decoder.hh', file_template
% vars())
2045 # generate decoder.cc
2046 includes
= '#include "decoder.hh"'
2047 global_output
= global_code
.decoder_output
2048 namespace_output
= namespace_code
.decoder_output
2049 # namespace_output += namespace_code.decode_block
2050 decode_function
= namespace_code
.decode_block
2051 self
.update_if_needed('decoder.cc', file_template
% vars())
2053 # generate per-cpu exec files
2054 for cpu
in self
.cpuModels
:
2055 includes
= '#include "decoder.hh"\n'
2056 includes
+= cpu
.includes
2057 global_output
= global_code
.exec_output
[cpu
.name
]
2058 namespace_output
= namespace_code
.exec_output
[cpu
.name
]
2059 decode_function
= ''
2060 self
.update_if_needed(cpu
.filename
, file_template
% vars())
2062 # The variable names here are hacky, but this will creat local
2063 # variables which will be referenced in vars() which have the
2064 # value of the globals.
2065 MaxInstSrcRegs
= self
.maxInstSrcRegs
2066 MaxInstDestRegs
= self
.maxInstDestRegs
2068 self
.update_if_needed('max_inst_regs.hh',
2069 max_inst_regs_template
% vars())
2071 def parse_isa_desc(self
, *args
, **kwargs
):
2073 self
._parse
_isa
_desc
(*args
, **kwargs
)
2074 except ISAParserError
, e
:
2075 e
.exit(self
.fileNameStack
)
2077 # Called as script: get args from command line.
2078 # Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2079 if __name__
== '__main__':
2080 execfile(sys
.argv
[1]) # read in CpuModel definitions
2081 cpu_models
= [CpuModel
.dict[cpu
] for cpu
in sys
.argv
[4:]]
2082 ISAParser(sys
.argv
[3], cpu_models
).parse_isa_desc(sys
.argv
[2])