ISA parser: Match /* */ and // style comments.
[gem5.git] / src / arch / isa_parser.py
1 # Copyright (c) 2003-2005 The Regents of The University of Michigan
2 # All rights reserved.
3 #
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.
14 #
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.
26 #
27 # Authors: Steve Reinhardt
28
29 import os
30 import sys
31 import re
32 import string
33 import inspect, traceback
34 # get type names
35 from types import *
36
37 from m5.util.grammar import Grammar
38
39 debug=False
40
41 ###################
42 # Utility functions
43
44 #
45 # Indent every line in string 's' by two spaces
46 # (except preprocessor directives).
47 # Used to make nested code blocks look pretty.
48 #
49 def indent(s):
50 return re.sub(r'(?m)^(?!#)', ' ', s)
51
52 #
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.
56 #
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).
65 #
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.
68
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])):
73 s = 'if 1:\n' + s
74 return s
75
76 class ISAParserError(Exception):
77 """Error handler for parser errors"""
78 def __init__(self, first, second=None):
79 if second is None:
80 self.lineno = 0
81 self.string = first
82 else:
83 if hasattr(first, 'lexer'):
84 first = first.lexer.lineno
85 self.lineno = first
86 self.string = second
87
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
92 # itself).
93
94 spaces = ""
95 for (filename, line) in filename_stack[:-1]:
96 print "%sIn file included from %s:" % (spaces, filename)
97 spaces += " "
98
99 # Print a Python stack backtrace if requested.
100 if print_traceback or not self.lineno:
101 traceback.print_exc()
102
103 line_str = "%s:" % (filename_stack[-1][0], )
104 if self.lineno:
105 line_str += "%d:" % (self.lineno, )
106
107 return "%s%s %s" % (spaces, line_str, self.string)
108
109 def exit(self, filename_stack, print_traceback=debug):
110 # Just call exit.
111
112 sys.exit(self.display(filename_stack, print_traceback))
113
114 def error(*args):
115 raise ISAParserError(*args)
116
117 ####################
118 # Template objects.
119 #
120 # Template objects are format strings that allow substitution from
121 # the attribute spaces of other objects (e.g. InstObjParams instances).
122
123 labelRE = re.compile(r'(?<!%)%\(([^\)]+)\)[sd]')
124
125 class Template(object):
126 def __init__(self, parser, t):
127 self.parser = parser
128 self.template = t
129
130 def subst(self, d):
131 myDict = None
132
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)
138
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()
143
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.
149 compositeCode = ''
150
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']
156
157 snippetLabels = [l for l in labelRE.findall(template)
158 if d.snippets.has_key(l)]
159
160 snippets = dict([(s, self.parser.mungeSnippet(d.snippets[s]))
161 for s in snippetLabels])
162
163 myDict.update(snippets)
164
165 compositeCode = ' '.join(map(str, snippets.values()))
166
167 # Add in template itself in case it references any
168 # operands explicitly (like Mem)
169 compositeCode += ' ' + template
170
171 operands = SubOperandList(self.parser, compositeCode, d.operands)
172
173 myDict['op_decl'] = operands.concatAttrStrings('op_decl')
174 if operands.readPC or operands.setPC:
175 myDict['op_decl'] += 'TheISA::PCState __parserAutoPCState;\n'
176
177 is_src = lambda op: op.is_src
178 is_dest = lambda op: op.is_dest
179
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')
184 if operands.readPC:
185 myDict['op_src_decl'] += \
186 'TheISA::PCState __parserAutoPCState;\n'
187 if operands.setPC:
188 myDict['op_dest_decl'] += \
189 'TheISA::PCState __parserAutoPCState;\n'
190
191 myDict['op_rd'] = operands.concatAttrStrings('op_rd')
192 if operands.readPC:
193 myDict['op_rd'] = '__parserAutoPCState = xc->pcState();\n' + \
194 myDict['op_rd']
195
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)
201 reordered.reverse()
202 op_wb_str = ''
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
207 pcWbStr = ''
208 else:
209 op_wb_str = op_desc.op_wb + op_wb_str
210 myDict['op_wb'] = op_wb_str
211
212 elif isinstance(d, dict):
213 # if the argument is a dictionary, we just use it.
214 myDict.update(d)
215 elif hasattr(d, '__dict__'):
216 # if the argument is an object, we use its attribute map.
217 myDict.update(d.__dict__)
218 else:
219 raise TypeError, "Template.subst() arg must be or have dictionary"
220 return template % myDict
221
222 # Convert to string. This handles the case when a template with a
223 # CPU-specific term gets interpolated into another template or into
224 # an output block.
225 def __str__(self):
226 return self.parser.expandCpuSymbolsToString(self.template)
227
228 ################
229 # Format object.
230 #
231 # A format object encapsulates an instruction format. It must provide
232 # a defineInst() method that generates the code for an instruction
233 # definition.
234
235 class Format(object):
236 def __init__(self, id, params, code):
237 self.id = id
238 self.params = params
239 label = 'def format ' + id
240 self.user_code = compile(fixPythonIndentation(code), label, 'exec')
241 param_list = string.join(params, ", ")
242 f = '''def defInst(_code, _context, %s):
243 my_locals = vars().copy()
244 exec _code in _context, my_locals
245 return my_locals\n''' % param_list
246 c = compile(f, label + ' wrapper', 'exec')
247 exec c
248 self.func = defInst
249
250 def defineInst(self, parser, name, args, lineno):
251 parser.updateExportContext()
252 context = parser.exportContext.copy()
253 if len(name):
254 Name = name[0].upper()
255 if len(name) > 1:
256 Name += name[1:]
257 context.update({ 'name' : name, 'Name' : Name })
258 try:
259 vars = self.func(self.user_code, context, *args[0], **args[1])
260 except Exception, exc:
261 if debug:
262 raise
263 error(lineno, 'error defining "%s": %s.' % (name, exc))
264 for k in vars.keys():
265 if k not in ('header_output', 'decoder_output',
266 'exec_output', 'decode_block'):
267 del vars[k]
268 return GenCode(parser, **vars)
269
270 # Special null format to catch an implicit-format instruction
271 # definition outside of any format block.
272 class NoFormat(object):
273 def __init__(self):
274 self.defaultInst = ''
275
276 def defineInst(self, parser, name, args, lineno):
277 error(lineno,
278 'instruction definition "%s" with no active format!' % name)
279
280 ###############
281 # GenCode class
282 #
283 # The GenCode class encapsulates generated code destined for various
284 # output files. The header_output and decoder_output attributes are
285 # strings containing code destined for decoder.hh and decoder.cc
286 # respectively. The decode_block attribute contains code to be
287 # incorporated in the decode function itself (that will also end up in
288 # decoder.cc). The exec_output attribute is a dictionary with a key
289 # for each CPU model name; the value associated with a particular key
290 # is the string of code for that CPU model's exec.cc file. The
291 # has_decode_default attribute is used in the decode block to allow
292 # explicit default clauses to override default default clauses.
293
294 class GenCode(object):
295 # Constructor. At this point we substitute out all CPU-specific
296 # symbols. For the exec output, these go into the per-model
297 # dictionary. For all other output types they get collapsed into
298 # a single string.
299 def __init__(self, parser,
300 header_output = '', decoder_output = '', exec_output = '',
301 decode_block = '', has_decode_default = False):
302 self.parser = parser
303 self.header_output = parser.expandCpuSymbolsToString(header_output)
304 self.decoder_output = parser.expandCpuSymbolsToString(decoder_output)
305 if isinstance(exec_output, dict):
306 self.exec_output = exec_output
307 elif isinstance(exec_output, str):
308 # If the exec_output arg is a single string, we replicate
309 # it for each of the CPU models, substituting and
310 # %(CPU_foo)s params appropriately.
311 self.exec_output = parser.expandCpuSymbolsToDict(exec_output)
312 self.decode_block = parser.expandCpuSymbolsToString(decode_block)
313 self.has_decode_default = has_decode_default
314
315 # Override '+' operator: generate a new GenCode object that
316 # concatenates all the individual strings in the operands.
317 def __add__(self, other):
318 exec_output = {}
319 for cpu in self.parser.cpuModels:
320 n = cpu.name
321 exec_output[n] = self.exec_output[n] + other.exec_output[n]
322 return GenCode(self.parser,
323 self.header_output + other.header_output,
324 self.decoder_output + other.decoder_output,
325 exec_output,
326 self.decode_block + other.decode_block,
327 self.has_decode_default or other.has_decode_default)
328
329 # Prepend a string (typically a comment) to all the strings.
330 def prepend_all(self, pre):
331 self.header_output = pre + self.header_output
332 self.decoder_output = pre + self.decoder_output
333 self.decode_block = pre + self.decode_block
334 for cpu in self.parser.cpuModels:
335 self.exec_output[cpu.name] = pre + self.exec_output[cpu.name]
336
337 # Wrap the decode block in a pair of strings (e.g., 'case foo:'
338 # and 'break;'). Used to build the big nested switch statement.
339 def wrap_decode_block(self, pre, post = ''):
340 self.decode_block = pre + indent(self.decode_block) + post
341
342 #####################################################################
343 #
344 # Bitfield Operator Support
345 #
346 #####################################################################
347
348 bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>')
349
350 bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
351 bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
352
353 def substBitOps(code):
354 # first convert single-bit selectors to two-index form
355 # i.e., <n> --> <n:n>
356 code = bitOp1ArgRE.sub(r'<\1:\1>', code)
357 # simple case: selector applied to ID (name)
358 # i.e., foo<a:b> --> bits(foo, a, b)
359 code = bitOpWordRE.sub(r'bits(\1, \2, \3)', code)
360 # if selector is applied to expression (ending in ')'),
361 # we need to search backward for matching '('
362 match = bitOpExprRE.search(code)
363 while match:
364 exprEnd = match.start()
365 here = exprEnd - 1
366 nestLevel = 1
367 while nestLevel > 0:
368 if code[here] == '(':
369 nestLevel -= 1
370 elif code[here] == ')':
371 nestLevel += 1
372 here -= 1
373 if here < 0:
374 sys.exit("Didn't find '('!")
375 exprStart = here+1
376 newExpr = r'bits(%s, %s, %s)' % (code[exprStart:exprEnd+1],
377 match.group(1), match.group(2))
378 code = code[:exprStart] + newExpr + code[match.end():]
379 match = bitOpExprRE.search(code)
380 return code
381
382
383 #####################################################################
384 #
385 # Code Parser
386 #
387 # The remaining code is the support for automatically extracting
388 # instruction characteristics from pseudocode.
389 #
390 #####################################################################
391
392 # Force the argument to be a list. Useful for flags, where a caller
393 # can specify a singleton flag or a list of flags. Also usful for
394 # converting tuples to lists so they can be modified.
395 def makeList(arg):
396 if isinstance(arg, list):
397 return arg
398 elif isinstance(arg, tuple):
399 return list(arg)
400 elif not arg:
401 return []
402 else:
403 return [ arg ]
404
405 class Operand(object):
406 '''Base class for operand descriptors. An instance of this class
407 (or actually a class derived from this one) represents a specific
408 operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
409 derived classes encapsulates the traits of a particular operand
410 type (e.g., "32-bit integer register").'''
411
412 def buildReadCode(self, func = None):
413 subst_dict = {"name": self.base_name,
414 "func": func,
415 "reg_idx": self.reg_spec,
416 "ctype": self.ctype}
417 if hasattr(self, 'src_reg_idx'):
418 subst_dict['op_idx'] = self.src_reg_idx
419 code = self.read_code % subst_dict
420 return '%s = %s;\n' % (self.base_name, code)
421
422 def buildWriteCode(self, func = None):
423 subst_dict = {"name": self.base_name,
424 "func": func,
425 "reg_idx": self.reg_spec,
426 "ctype": self.ctype,
427 "final_val": self.base_name}
428 if hasattr(self, 'dest_reg_idx'):
429 subst_dict['op_idx'] = self.dest_reg_idx
430 code = self.write_code % subst_dict
431 return '''
432 {
433 %s final_val = %s;
434 %s;
435 if (traceData) { traceData->setData(final_val); }
436 }''' % (self.dflt_ctype, self.base_name, code)
437
438 def __init__(self, parser, full_name, ext, is_src, is_dest):
439 self.full_name = full_name
440 self.ext = ext
441 self.is_src = is_src
442 self.is_dest = is_dest
443 # The 'effective extension' (eff_ext) is either the actual
444 # extension, if one was explicitly provided, or the default.
445 if ext:
446 self.eff_ext = ext
447 elif hasattr(self, 'dflt_ext'):
448 self.eff_ext = self.dflt_ext
449
450 if hasattr(self, 'eff_ext'):
451 self.ctype = parser.operandTypeMap[self.eff_ext]
452
453 # Finalize additional fields (primarily code fields). This step
454 # is done separately since some of these fields may depend on the
455 # register index enumeration that hasn't been performed yet at the
456 # time of __init__().
457 def finalize(self):
458 self.flags = self.getFlags()
459 self.constructor = self.makeConstructor()
460 self.op_decl = self.makeDecl()
461
462 if self.is_src:
463 self.op_rd = self.makeRead()
464 self.op_src_decl = self.makeDecl()
465 else:
466 self.op_rd = ''
467 self.op_src_decl = ''
468
469 if self.is_dest:
470 self.op_wb = self.makeWrite()
471 self.op_dest_decl = self.makeDecl()
472 else:
473 self.op_wb = ''
474 self.op_dest_decl = ''
475
476 def isMem(self):
477 return 0
478
479 def isReg(self):
480 return 0
481
482 def isFloatReg(self):
483 return 0
484
485 def isIntReg(self):
486 return 0
487
488 def isControlReg(self):
489 return 0
490
491 def isPCState(self):
492 return 0
493
494 def isPCPart(self):
495 return self.isPCState() and self.reg_spec
496
497 def getFlags(self):
498 # note the empty slice '[:]' gives us a copy of self.flags[0]
499 # instead of a reference to it
500 my_flags = self.flags[0][:]
501 if self.is_src:
502 my_flags += self.flags[1]
503 if self.is_dest:
504 my_flags += self.flags[2]
505 return my_flags
506
507 def makeDecl(self):
508 # Note that initializations in the declarations are solely
509 # to avoid 'uninitialized variable' errors from the compiler.
510 return self.ctype + ' ' + self.base_name + ' = 0;\n';
511
512 class IntRegOperand(Operand):
513 def isReg(self):
514 return 1
515
516 def isIntReg(self):
517 return 1
518
519 def makeConstructor(self):
520 c = ''
521 if self.is_src:
522 c += '\n\t_srcRegIdx[%d] = %s;' % \
523 (self.src_reg_idx, self.reg_spec)
524 if self.is_dest:
525 c += '\n\t_destRegIdx[%d] = %s;' % \
526 (self.dest_reg_idx, self.reg_spec)
527 return c
528
529 def makeRead(self):
530 if (self.ctype == 'float' or self.ctype == 'double'):
531 error('Attempt to read integer register as FP')
532 if self.read_code != None:
533 return self.buildReadCode('readIntRegOperand')
534 int_reg_val = 'xc->readIntRegOperand(this, %d)' % self.src_reg_idx
535 return '%s = %s;\n' % (self.base_name, int_reg_val)
536
537 def makeWrite(self):
538 if (self.ctype == 'float' or self.ctype == 'double'):
539 error('Attempt to write integer register as FP')
540 if self.write_code != None:
541 return self.buildWriteCode('setIntRegOperand')
542 wb = '''
543 {
544 %s final_val = %s;
545 xc->setIntRegOperand(this, %d, final_val);\n
546 if (traceData) { traceData->setData(final_val); }
547 }''' % (self.ctype, self.base_name, self.dest_reg_idx)
548 return wb
549
550 class FloatRegOperand(Operand):
551 def isReg(self):
552 return 1
553
554 def isFloatReg(self):
555 return 1
556
557 def makeConstructor(self):
558 c = ''
559 if self.is_src:
560 c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
561 (self.src_reg_idx, self.reg_spec)
562 if self.is_dest:
563 c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
564 (self.dest_reg_idx, self.reg_spec)
565 return c
566
567 def makeRead(self):
568 bit_select = 0
569 if (self.ctype == 'float' or self.ctype == 'double'):
570 func = 'readFloatRegOperand'
571 else:
572 func = 'readFloatRegOperandBits'
573 if self.read_code != None:
574 return self.buildReadCode(func)
575 return '%s = xc->%s(this, %d);\n' % \
576 (self.base_name, func, self.src_reg_idx)
577
578 def makeWrite(self):
579 if (self.ctype == 'float' or self.ctype == 'double'):
580 func = 'setFloatRegOperand'
581 else:
582 func = 'setFloatRegOperandBits'
583 if self.write_code != None:
584 return self.buildWriteCode(func)
585 wb = '''
586 {
587 %s final_val = %s;
588 xc->%s(this, %d, final_val);\n
589 if (traceData) { traceData->setData(final_val); }
590 }''' % (self.ctype, self.base_name, func, self.dest_reg_idx)
591 return wb
592
593 class ControlRegOperand(Operand):
594 def isReg(self):
595 return 1
596
597 def isControlReg(self):
598 return 1
599
600 def makeConstructor(self):
601 c = ''
602 if self.is_src:
603 c += '\n\t_srcRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
604 (self.src_reg_idx, self.reg_spec)
605 if self.is_dest:
606 c += '\n\t_destRegIdx[%d] = %s + Ctrl_Base_DepTag;' % \
607 (self.dest_reg_idx, self.reg_spec)
608 return c
609
610 def makeRead(self):
611 bit_select = 0
612 if (self.ctype == 'float' or self.ctype == 'double'):
613 error('Attempt to read control register as FP')
614 if self.read_code != None:
615 return self.buildReadCode('readMiscRegOperand')
616 return '%s = xc->readMiscRegOperand(this, %s);\n' % \
617 (self.base_name, self.src_reg_idx)
618
619 def makeWrite(self):
620 if (self.ctype == 'float' or self.ctype == 'double'):
621 error('Attempt to write control register as FP')
622 if self.write_code != None:
623 return self.buildWriteCode('setMiscRegOperand')
624 wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \
625 (self.dest_reg_idx, self.base_name)
626 wb += 'if (traceData) { traceData->setData(%s); }' % \
627 self.base_name
628 return wb
629
630 class MemOperand(Operand):
631 def isMem(self):
632 return 1
633
634 def makeConstructor(self):
635 return ''
636
637 def makeDecl(self):
638 # Note that initializations in the declarations are solely
639 # to avoid 'uninitialized variable' errors from the compiler.
640 # Declare memory data variable.
641 return '%s %s = 0;\n' % (self.ctype, self.base_name)
642
643 def makeRead(self):
644 if self.read_code != None:
645 return self.buildReadCode()
646 return ''
647
648 def makeWrite(self):
649 if self.write_code != None:
650 return self.buildWriteCode()
651 return ''
652
653 class PCStateOperand(Operand):
654 def makeConstructor(self):
655 return ''
656
657 def makeRead(self):
658 if self.reg_spec:
659 # A component of the PC state.
660 return '%s = __parserAutoPCState.%s();\n' % \
661 (self.base_name, self.reg_spec)
662 else:
663 # The whole PC state itself.
664 return '%s = xc->pcState();\n' % self.base_name
665
666 def makeWrite(self):
667 if self.reg_spec:
668 # A component of the PC state.
669 return '__parserAutoPCState.%s(%s);\n' % \
670 (self.reg_spec, self.base_name)
671 else:
672 # The whole PC state itself.
673 return 'xc->pcState(%s);\n' % self.base_name
674
675 def makeDecl(self):
676 ctype = 'TheISA::PCState'
677 if self.isPCPart():
678 ctype = self.ctype
679 return "%s %s;\n" % (ctype, self.base_name)
680
681 def isPCState(self):
682 return 1
683
684 class OperandList(object):
685 '''Find all the operands in the given code block. Returns an operand
686 descriptor list (instance of class OperandList).'''
687 def __init__(self, parser, code):
688 self.items = []
689 self.bases = {}
690 # delete comments so we don't match on reg specifiers inside
691 code = commentRE.sub('', code)
692 # search for operands
693 next_pos = 0
694 while 1:
695 match = parser.operandsRE.search(code, next_pos)
696 if not match:
697 # no more matches: we're done
698 break
699 op = match.groups()
700 # regexp groups are operand full name, base, and extension
701 (op_full, op_base, op_ext) = op
702 # if the token following the operand is an assignment, this is
703 # a destination (LHS), else it's a source (RHS)
704 is_dest = (assignRE.match(code, match.end()) != None)
705 is_src = not is_dest
706 # see if we've already seen this one
707 op_desc = self.find_base(op_base)
708 if op_desc:
709 if op_desc.ext != op_ext:
710 error('Inconsistent extensions for operand %s' % \
711 op_base)
712 op_desc.is_src = op_desc.is_src or is_src
713 op_desc.is_dest = op_desc.is_dest or is_dest
714 else:
715 # new operand: create new descriptor
716 op_desc = parser.operandNameMap[op_base](parser,
717 op_full, op_ext, is_src, is_dest)
718 self.append(op_desc)
719 # start next search after end of current match
720 next_pos = match.end()
721 self.sort()
722 # enumerate source & dest register operands... used in building
723 # constructor later
724 self.numSrcRegs = 0
725 self.numDestRegs = 0
726 self.numFPDestRegs = 0
727 self.numIntDestRegs = 0
728 self.memOperand = None
729 for op_desc in self.items:
730 if op_desc.isReg():
731 if op_desc.is_src:
732 op_desc.src_reg_idx = self.numSrcRegs
733 self.numSrcRegs += 1
734 if op_desc.is_dest:
735 op_desc.dest_reg_idx = self.numDestRegs
736 self.numDestRegs += 1
737 if op_desc.isFloatReg():
738 self.numFPDestRegs += 1
739 elif op_desc.isIntReg():
740 self.numIntDestRegs += 1
741 elif op_desc.isMem():
742 if self.memOperand:
743 error("Code block has more than one memory operand.")
744 self.memOperand = op_desc
745 if parser.maxInstSrcRegs < self.numSrcRegs:
746 parser.maxInstSrcRegs = self.numSrcRegs
747 if parser.maxInstDestRegs < self.numDestRegs:
748 parser.maxInstDestRegs = self.numDestRegs
749 # now make a final pass to finalize op_desc fields that may depend
750 # on the register enumeration
751 for op_desc in self.items:
752 op_desc.finalize()
753
754 def __len__(self):
755 return len(self.items)
756
757 def __getitem__(self, index):
758 return self.items[index]
759
760 def append(self, op_desc):
761 self.items.append(op_desc)
762 self.bases[op_desc.base_name] = op_desc
763
764 def find_base(self, base_name):
765 # like self.bases[base_name], but returns None if not found
766 # (rather than raising exception)
767 return self.bases.get(base_name)
768
769 # internal helper function for concat[Some]Attr{Strings|Lists}
770 def __internalConcatAttrs(self, attr_name, filter, result):
771 for op_desc in self.items:
772 if filter(op_desc):
773 result += getattr(op_desc, attr_name)
774 return result
775
776 # return a single string that is the concatenation of the (string)
777 # values of the specified attribute for all operands
778 def concatAttrStrings(self, attr_name):
779 return self.__internalConcatAttrs(attr_name, lambda x: 1, '')
780
781 # like concatAttrStrings, but only include the values for the operands
782 # for which the provided filter function returns true
783 def concatSomeAttrStrings(self, filter, attr_name):
784 return self.__internalConcatAttrs(attr_name, filter, '')
785
786 # return a single list that is the concatenation of the (list)
787 # values of the specified attribute for all operands
788 def concatAttrLists(self, attr_name):
789 return self.__internalConcatAttrs(attr_name, lambda x: 1, [])
790
791 # like concatAttrLists, but only include the values for the operands
792 # for which the provided filter function returns true
793 def concatSomeAttrLists(self, filter, attr_name):
794 return self.__internalConcatAttrs(attr_name, filter, [])
795
796 def sort(self):
797 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
798
799 class SubOperandList(OperandList):
800 '''Find all the operands in the given code block. Returns an operand
801 descriptor list (instance of class OperandList).'''
802 def __init__(self, parser, code, master_list):
803 self.items = []
804 self.bases = {}
805 # delete comments so we don't match on reg specifiers inside
806 code = commentRE.sub('', code)
807 # search for operands
808 next_pos = 0
809 while 1:
810 match = parser.operandsRE.search(code, next_pos)
811 if not match:
812 # no more matches: we're done
813 break
814 op = match.groups()
815 # regexp groups are operand full name, base, and extension
816 (op_full, op_base, op_ext) = op
817 # find this op in the master list
818 op_desc = master_list.find_base(op_base)
819 if not op_desc:
820 error('Found operand %s which is not in the master list!' \
821 ' This is an internal error' % op_base)
822 else:
823 # See if we've already found this operand
824 op_desc = self.find_base(op_base)
825 if not op_desc:
826 # if not, add a reference to it to this sub list
827 self.append(master_list.bases[op_base])
828
829 # start next search after end of current match
830 next_pos = match.end()
831 self.sort()
832 self.memOperand = None
833 # Whether the whole PC needs to be read so parts of it can be accessed
834 self.readPC = False
835 # Whether the whole PC needs to be written after parts of it were
836 # changed
837 self.setPC = False
838 # Whether this instruction manipulates the whole PC or parts of it.
839 # Mixing the two is a bad idea and flagged as an error.
840 self.pcPart = None
841 for op_desc in self.items:
842 if op_desc.isPCPart():
843 self.readPC = True
844 if op_desc.is_dest:
845 self.setPC = True
846 if op_desc.isPCState():
847 if self.pcPart is not None:
848 if self.pcPart and not op_desc.isPCPart() or \
849 not self.pcPart and op_desc.isPCPart():
850 error("Mixed whole and partial PC state operands.")
851 self.pcPart = op_desc.isPCPart()
852 if op_desc.isMem():
853 if self.memOperand:
854 error("Code block has more than one memory operand.")
855 self.memOperand = op_desc
856
857 # Regular expression object to match C++ comments
858 # (used in findOperands())
859 commentRE = re.compile(r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
860 re.DOTALL | re.MULTILINE)
861
862 # Regular expression object to match assignment statements
863 # (used in findOperands())
864 assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
865
866 def makeFlagConstructor(flag_list):
867 if len(flag_list) == 0:
868 return ''
869 # filter out repeated flags
870 flag_list.sort()
871 i = 1
872 while i < len(flag_list):
873 if flag_list[i] == flag_list[i-1]:
874 del flag_list[i]
875 else:
876 i += 1
877 pre = '\n\tflags['
878 post = '] = true;'
879 code = pre + string.join(flag_list, post + pre) + post
880 return code
881
882 # Assume all instruction flags are of the form 'IsFoo'
883 instFlagRE = re.compile(r'Is.*')
884
885 # OpClass constants end in 'Op' except No_OpClass
886 opClassRE = re.compile(r'.*Op|No_OpClass')
887
888 class InstObjParams(object):
889 def __init__(self, parser, mnem, class_name, base_class = '',
890 snippets = {}, opt_args = []):
891 self.mnemonic = mnem
892 self.class_name = class_name
893 self.base_class = base_class
894 if not isinstance(snippets, dict):
895 snippets = {'code' : snippets}
896 compositeCode = ' '.join(map(str, snippets.values()))
897 self.snippets = snippets
898
899 self.operands = OperandList(parser, compositeCode)
900 self.constructor = self.operands.concatAttrStrings('constructor')
901 self.constructor += \
902 '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
903 self.constructor += \
904 '\n\t_numDestRegs = %d;' % self.operands.numDestRegs
905 self.constructor += \
906 '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs
907 self.constructor += \
908 '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
909 self.flags = self.operands.concatAttrLists('flags')
910
911 # Make a basic guess on the operand class (function unit type).
912 # These are good enough for most cases, and can be overridden
913 # later otherwise.
914 if 'IsStore' in self.flags:
915 self.op_class = 'MemWriteOp'
916 elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags:
917 self.op_class = 'MemReadOp'
918 elif 'IsFloating' in self.flags:
919 self.op_class = 'FloatAddOp'
920 else:
921 self.op_class = 'IntAluOp'
922
923 # Optional arguments are assumed to be either StaticInst flags
924 # or an OpClass value. To avoid having to import a complete
925 # list of these values to match against, we do it ad-hoc
926 # with regexps.
927 for oa in opt_args:
928 if instFlagRE.match(oa):
929 self.flags.append(oa)
930 elif opClassRE.match(oa):
931 self.op_class = oa
932 else:
933 error('InstObjParams: optional arg "%s" not recognized '
934 'as StaticInst::Flag or OpClass.' % oa)
935
936 # add flag initialization to contructor here to include
937 # any flags added via opt_args
938 self.constructor += makeFlagConstructor(self.flags)
939
940 # if 'IsFloating' is set, add call to the FP enable check
941 # function (which should be provided by isa_desc via a declare)
942 if 'IsFloating' in self.flags:
943 self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
944 else:
945 self.fp_enable_check = ''
946
947 ##############
948 # Stack: a simple stack object. Used for both formats (formatStack)
949 # and default cases (defaultStack). Simply wraps a list to give more
950 # stack-like syntax and enable initialization with an argument list
951 # (as opposed to an argument that's a list).
952
953 class Stack(list):
954 def __init__(self, *items):
955 list.__init__(self, items)
956
957 def push(self, item):
958 self.append(item);
959
960 def top(self):
961 return self[-1]
962
963 #######################
964 #
965 # Output file template
966 #
967
968 file_template = '''
969 /*
970 * DO NOT EDIT THIS FILE!!!
971 *
972 * It was automatically generated from the ISA description in %(filename)s
973 */
974
975 %(includes)s
976
977 %(global_output)s
978
979 namespace %(namespace)s {
980
981 %(namespace_output)s
982
983 } // namespace %(namespace)s
984
985 %(decode_function)s
986 '''
987
988 max_inst_regs_template = '''
989 /*
990 * DO NOT EDIT THIS FILE!!!
991 *
992 * It was automatically generated from the ISA description in %(filename)s
993 */
994
995 namespace %(namespace)s {
996
997 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
998 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
999
1000 } // namespace %(namespace)s
1001
1002 '''
1003
1004 class ISAParser(Grammar):
1005 def __init__(self, output_dir, cpu_models):
1006 super(ISAParser, self).__init__()
1007 self.output_dir = output_dir
1008
1009 self.cpuModels = cpu_models
1010
1011 # variable to hold templates
1012 self.templateMap = {}
1013
1014 # This dictionary maps format name strings to Format objects.
1015 self.formatMap = {}
1016
1017 # The format stack.
1018 self.formatStack = Stack(NoFormat())
1019
1020 # The default case stack.
1021 self.defaultStack = Stack(None)
1022
1023 # Stack that tracks current file and line number. Each
1024 # element is a tuple (filename, lineno) that records the
1025 # *current* filename and the line number in the *previous*
1026 # file where it was included.
1027 self.fileNameStack = Stack()
1028
1029 symbols = ('makeList', 're', 'string')
1030 self.exportContext = dict([(s, eval(s)) for s in symbols])
1031
1032 self.maxInstSrcRegs = 0
1033 self.maxInstDestRegs = 0
1034
1035 #####################################################################
1036 #
1037 # Lexer
1038 #
1039 # The PLY lexer module takes two things as input:
1040 # - A list of token names (the string list 'tokens')
1041 # - A regular expression describing a match for each token. The
1042 # regexp for token FOO can be provided in two ways:
1043 # - as a string variable named t_FOO
1044 # - as the doc string for a function named t_FOO. In this case,
1045 # the function is also executed, allowing an action to be
1046 # associated with each token match.
1047 #
1048 #####################################################################
1049
1050 # Reserved words. These are listed separately as they are matched
1051 # using the same regexp as generic IDs, but distinguished in the
1052 # t_ID() function. The PLY documentation suggests this approach.
1053 reserved = (
1054 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
1055 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
1056 'OUTPUT', 'SIGNED', 'TEMPLATE'
1057 )
1058
1059 # List of tokens. The lex module requires this.
1060 tokens = reserved + (
1061 # identifier
1062 'ID',
1063
1064 # integer literal
1065 'INTLIT',
1066
1067 # string literal
1068 'STRLIT',
1069
1070 # code literal
1071 'CODELIT',
1072
1073 # ( ) [ ] { } < > , ; . : :: *
1074 'LPAREN', 'RPAREN',
1075 'LBRACKET', 'RBRACKET',
1076 'LBRACE', 'RBRACE',
1077 'LESS', 'GREATER', 'EQUALS',
1078 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON',
1079 'ASTERISK',
1080
1081 # C preprocessor directives
1082 'CPPDIRECTIVE'
1083
1084 # The following are matched but never returned. commented out to
1085 # suppress PLY warning
1086 # newfile directive
1087 # 'NEWFILE',
1088
1089 # endfile directive
1090 # 'ENDFILE'
1091 )
1092
1093 # Regular expressions for token matching
1094 t_LPAREN = r'\('
1095 t_RPAREN = r'\)'
1096 t_LBRACKET = r'\['
1097 t_RBRACKET = r'\]'
1098 t_LBRACE = r'\{'
1099 t_RBRACE = r'\}'
1100 t_LESS = r'\<'
1101 t_GREATER = r'\>'
1102 t_EQUALS = r'='
1103 t_COMMA = r','
1104 t_SEMI = r';'
1105 t_DOT = r'\.'
1106 t_COLON = r':'
1107 t_DBLCOLON = r'::'
1108 t_ASTERISK = r'\*'
1109
1110 # Identifiers and reserved words
1111 reserved_map = { }
1112 for r in reserved:
1113 reserved_map[r.lower()] = r
1114
1115 def t_ID(self, t):
1116 r'[A-Za-z_]\w*'
1117 t.type = self.reserved_map.get(t.value, 'ID')
1118 return t
1119
1120 # Integer literal
1121 def t_INTLIT(self, t):
1122 r'-?(0x[\da-fA-F]+)|\d+'
1123 try:
1124 t.value = int(t.value,0)
1125 except ValueError:
1126 error(t, 'Integer value "%s" too large' % t.value)
1127 t.value = 0
1128 return t
1129
1130 # String literal. Note that these use only single quotes, and
1131 # can span multiple lines.
1132 def t_STRLIT(self, t):
1133 r"(?m)'([^'])+'"
1134 # strip off quotes
1135 t.value = t.value[1:-1]
1136 t.lexer.lineno += t.value.count('\n')
1137 return t
1138
1139
1140 # "Code literal"... like a string literal, but delimiters are
1141 # '{{' and '}}' so they get formatted nicely under emacs c-mode
1142 def t_CODELIT(self, t):
1143 r"(?m)\{\{([^\}]|}(?!\}))+\}\}"
1144 # strip off {{ & }}
1145 t.value = t.value[2:-2]
1146 t.lexer.lineno += t.value.count('\n')
1147 return t
1148
1149 def t_CPPDIRECTIVE(self, t):
1150 r'^\#[^\#].*\n'
1151 t.lexer.lineno += t.value.count('\n')
1152 return t
1153
1154 def t_NEWFILE(self, t):
1155 r'^\#\#newfile\s+"[^"]*"'
1156 self.fileNameStack.push((t.value[11:-1], t.lexer.lineno))
1157 t.lexer.lineno = 0
1158
1159 def t_ENDFILE(self, t):
1160 r'^\#\#endfile'
1161 (old_filename, t.lexer.lineno) = self.fileNameStack.pop()
1162
1163 #
1164 # The functions t_NEWLINE, t_ignore, and t_error are
1165 # special for the lex module.
1166 #
1167
1168 # Newlines
1169 def t_NEWLINE(self, t):
1170 r'\n+'
1171 t.lexer.lineno += t.value.count('\n')
1172
1173 # Comments
1174 def t_comment(self, t):
1175 r'//.*'
1176
1177 # Completely ignored characters
1178 t_ignore = ' \t\x0c'
1179
1180 # Error handler
1181 def t_error(self, t):
1182 error(t, "illegal character '%s'" % t.value[0])
1183 t.skip(1)
1184
1185 #####################################################################
1186 #
1187 # Parser
1188 #
1189 # Every function whose name starts with 'p_' defines a grammar
1190 # rule. The rule is encoded in the function's doc string, while
1191 # the function body provides the action taken when the rule is
1192 # matched. The argument to each function is a list of the values
1193 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the
1194 # symbols on the RHS. For tokens, the value is copied from the
1195 # t.value attribute provided by the lexer. For non-terminals, the
1196 # value is assigned by the producing rule; i.e., the job of the
1197 # grammar rule function is to set the value for the non-terminal
1198 # on the LHS (by assigning to t[0]).
1199 #####################################################################
1200
1201 # The LHS of the first grammar rule is used as the start symbol
1202 # (in this case, 'specification'). Note that this rule enforces
1203 # that there will be exactly one namespace declaration, with 0 or
1204 # more global defs/decls before and after it. The defs & decls
1205 # before the namespace decl will be outside the namespace; those
1206 # after will be inside. The decoder function is always inside the
1207 # namespace.
1208 def p_specification(self, t):
1209 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
1210 global_code = t[1]
1211 isa_name = t[2]
1212 namespace = isa_name + "Inst"
1213 # wrap the decode block as a function definition
1214 t[4].wrap_decode_block('''
1215 StaticInstPtr
1216 %(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst)
1217 {
1218 using namespace %(namespace)s;
1219 ''' % vars(), '}')
1220 # both the latter output blocks and the decode block are in
1221 # the namespace
1222 namespace_code = t[3] + t[4]
1223 # pass it all back to the caller of yacc.parse()
1224 t[0] = (isa_name, namespace, global_code, namespace_code)
1225
1226 # ISA name declaration looks like "namespace <foo>;"
1227 def p_name_decl(self, t):
1228 'name_decl : NAMESPACE ID SEMI'
1229 t[0] = t[2]
1230
1231 # 'opt_defs_and_outputs' is a possibly empty sequence of
1232 # def and/or output statements.
1233 def p_opt_defs_and_outputs_0(self, t):
1234 'opt_defs_and_outputs : empty'
1235 t[0] = GenCode(self)
1236
1237 def p_opt_defs_and_outputs_1(self, t):
1238 'opt_defs_and_outputs : defs_and_outputs'
1239 t[0] = t[1]
1240
1241 def p_defs_and_outputs_0(self, t):
1242 'defs_and_outputs : def_or_output'
1243 t[0] = t[1]
1244
1245 def p_defs_and_outputs_1(self, t):
1246 'defs_and_outputs : defs_and_outputs def_or_output'
1247 t[0] = t[1] + t[2]
1248
1249 # The list of possible definition/output statements.
1250 def p_def_or_output(self, t):
1251 '''def_or_output : def_format
1252 | def_bitfield
1253 | def_bitfield_struct
1254 | def_template
1255 | def_operand_types
1256 | def_operands
1257 | output_header
1258 | output_decoder
1259 | output_exec
1260 | global_let'''
1261 t[0] = t[1]
1262
1263 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1264 # directly to the appropriate output section.
1265
1266 # Massage output block by substituting in template definitions and
1267 # bit operators. We handle '%'s embedded in the string that don't
1268 # indicate template substitutions (or CPU-specific symbols, which
1269 # get handled in GenCode) by doubling them first so that the
1270 # format operation will reduce them back to single '%'s.
1271 def process_output(self, s):
1272 s = self.protectNonSubstPercents(s)
1273 # protects cpu-specific symbols too
1274 s = self.protectCpuSymbols(s)
1275 return substBitOps(s % self.templateMap)
1276
1277 def p_output_header(self, t):
1278 'output_header : OUTPUT HEADER CODELIT SEMI'
1279 t[0] = GenCode(self, header_output = self.process_output(t[3]))
1280
1281 def p_output_decoder(self, t):
1282 'output_decoder : OUTPUT DECODER CODELIT SEMI'
1283 t[0] = GenCode(self, decoder_output = self.process_output(t[3]))
1284
1285 def p_output_exec(self, t):
1286 'output_exec : OUTPUT EXEC CODELIT SEMI'
1287 t[0] = GenCode(self, exec_output = self.process_output(t[3]))
1288
1289 # global let blocks 'let {{...}}' (Python code blocks) are
1290 # executed directly when seen. Note that these execute in a
1291 # special variable context 'exportContext' to prevent the code
1292 # from polluting this script's namespace.
1293 def p_global_let(self, t):
1294 'global_let : LET CODELIT SEMI'
1295 self.updateExportContext()
1296 self.exportContext["header_output"] = ''
1297 self.exportContext["decoder_output"] = ''
1298 self.exportContext["exec_output"] = ''
1299 self.exportContext["decode_block"] = ''
1300 try:
1301 exec fixPythonIndentation(t[2]) in self.exportContext
1302 except Exception, exc:
1303 if debug:
1304 raise
1305 error(t, 'error: %s in global let block "%s".' % (exc, t[2]))
1306 t[0] = GenCode(self,
1307 header_output=self.exportContext["header_output"],
1308 decoder_output=self.exportContext["decoder_output"],
1309 exec_output=self.exportContext["exec_output"],
1310 decode_block=self.exportContext["decode_block"])
1311
1312 # Define the mapping from operand type extensions to C++ types and
1313 # bit widths (stored in operandTypeMap).
1314 def p_def_operand_types(self, t):
1315 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1316 try:
1317 self.operandTypeMap = eval('{' + t[3] + '}')
1318 except Exception, exc:
1319 if debug:
1320 raise
1321 error(t,
1322 'error: %s in def operand_types block "%s".' % (exc, t[3]))
1323 t[0] = GenCode(self) # contributes nothing to the output C++ file
1324
1325 # Define the mapping from operand names to operand classes and
1326 # other traits. Stored in operandNameMap.
1327 def p_def_operands(self, t):
1328 'def_operands : DEF OPERANDS CODELIT SEMI'
1329 if not hasattr(self, 'operandTypeMap'):
1330 error(t, 'error: operand types must be defined before operands')
1331 try:
1332 user_dict = eval('{' + t[3] + '}', self.exportContext)
1333 except Exception, exc:
1334 if debug:
1335 raise
1336 error(t, 'error: %s in def operands block "%s".' % (exc, t[3]))
1337 self.buildOperandNameMap(user_dict, t.lexer.lineno)
1338 t[0] = GenCode(self) # contributes nothing to the output C++ file
1339
1340 # A bitfield definition looks like:
1341 # 'def [signed] bitfield <ID> [<first>:<last>]'
1342 # This generates a preprocessor macro in the output file.
1343 def p_def_bitfield_0(self, t):
1344 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
1345 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8])
1346 if (t[2] == 'signed'):
1347 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr)
1348 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
1349 t[0] = GenCode(self, header_output=hash_define)
1350
1351 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
1352 def p_def_bitfield_1(self, t):
1353 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
1354 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6])
1355 if (t[2] == 'signed'):
1356 expr = 'sext<%d>(%s)' % (1, expr)
1357 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
1358 t[0] = GenCode(self, header_output=hash_define)
1359
1360 # alternate form for structure member: 'def bitfield <ID> <ID>'
1361 def p_def_bitfield_struct(self, t):
1362 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI'
1363 if (t[2] != ''):
1364 error(t, 'error: structure bitfields are always unsigned.')
1365 expr = 'machInst.%s' % t[5]
1366 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
1367 t[0] = GenCode(self, header_output=hash_define)
1368
1369 def p_id_with_dot_0(self, t):
1370 'id_with_dot : ID'
1371 t[0] = t[1]
1372
1373 def p_id_with_dot_1(self, t):
1374 'id_with_dot : ID DOT id_with_dot'
1375 t[0] = t[1] + t[2] + t[3]
1376
1377 def p_opt_signed_0(self, t):
1378 'opt_signed : SIGNED'
1379 t[0] = t[1]
1380
1381 def p_opt_signed_1(self, t):
1382 'opt_signed : empty'
1383 t[0] = ''
1384
1385 def p_def_template(self, t):
1386 'def_template : DEF TEMPLATE ID CODELIT SEMI'
1387 self.templateMap[t[3]] = Template(self, t[4])
1388 t[0] = GenCode(self)
1389
1390 # An instruction format definition looks like
1391 # "def format <fmt>(<params>) {{...}};"
1392 def p_def_format(self, t):
1393 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1394 (id, params, code) = (t[3], t[5], t[7])
1395 self.defFormat(id, params, code, t.lexer.lineno)
1396 t[0] = GenCode(self)
1397
1398 # The formal parameter list for an instruction format is a
1399 # possibly empty list of comma-separated parameters. Positional
1400 # (standard, non-keyword) parameters must come first, followed by
1401 # keyword parameters, followed by a '*foo' parameter that gets
1402 # excess positional arguments (as in Python). Each of these three
1403 # parameter categories is optional.
1404 #
1405 # Note that we do not support the '**foo' parameter for collecting
1406 # otherwise undefined keyword args. Otherwise the parameter list
1407 # is (I believe) identical to what is supported in Python.
1408 #
1409 # The param list generates a tuple, where the first element is a
1410 # list of the positional params and the second element is a dict
1411 # containing the keyword params.
1412 def p_param_list_0(self, t):
1413 'param_list : positional_param_list COMMA nonpositional_param_list'
1414 t[0] = t[1] + t[3]
1415
1416 def p_param_list_1(self, t):
1417 '''param_list : positional_param_list
1418 | nonpositional_param_list'''
1419 t[0] = t[1]
1420
1421 def p_positional_param_list_0(self, t):
1422 'positional_param_list : empty'
1423 t[0] = []
1424
1425 def p_positional_param_list_1(self, t):
1426 'positional_param_list : ID'
1427 t[0] = [t[1]]
1428
1429 def p_positional_param_list_2(self, t):
1430 'positional_param_list : positional_param_list COMMA ID'
1431 t[0] = t[1] + [t[3]]
1432
1433 def p_nonpositional_param_list_0(self, t):
1434 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
1435 t[0] = t[1] + t[3]
1436
1437 def p_nonpositional_param_list_1(self, t):
1438 '''nonpositional_param_list : keyword_param_list
1439 | excess_args_param'''
1440 t[0] = t[1]
1441
1442 def p_keyword_param_list_0(self, t):
1443 'keyword_param_list : keyword_param'
1444 t[0] = [t[1]]
1445
1446 def p_keyword_param_list_1(self, t):
1447 'keyword_param_list : keyword_param_list COMMA keyword_param'
1448 t[0] = t[1] + [t[3]]
1449
1450 def p_keyword_param(self, t):
1451 'keyword_param : ID EQUALS expr'
1452 t[0] = t[1] + ' = ' + t[3].__repr__()
1453
1454 def p_excess_args_param(self, t):
1455 'excess_args_param : ASTERISK ID'
1456 # Just concatenate them: '*ID'. Wrap in list to be consistent
1457 # with positional_param_list and keyword_param_list.
1458 t[0] = [t[1] + t[2]]
1459
1460 # End of format definition-related rules.
1461 ##############
1462
1463 #
1464 # A decode block looks like:
1465 # decode <field1> [, <field2>]* [default <inst>] { ... }
1466 #
1467 def p_decode_block(self, t):
1468 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
1469 default_defaults = self.defaultStack.pop()
1470 codeObj = t[5]
1471 # use the "default defaults" only if there was no explicit
1472 # default statement in decode_stmt_list
1473 if not codeObj.has_decode_default:
1474 codeObj += default_defaults
1475 codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n')
1476 t[0] = codeObj
1477
1478 # The opt_default statement serves only to push the "default
1479 # defaults" onto defaultStack. This value will be used by nested
1480 # decode blocks, and used and popped off when the current
1481 # decode_block is processed (in p_decode_block() above).
1482 def p_opt_default_0(self, t):
1483 'opt_default : empty'
1484 # no default specified: reuse the one currently at the top of
1485 # the stack
1486 self.defaultStack.push(self.defaultStack.top())
1487 # no meaningful value returned
1488 t[0] = None
1489
1490 def p_opt_default_1(self, t):
1491 'opt_default : DEFAULT inst'
1492 # push the new default
1493 codeObj = t[2]
1494 codeObj.wrap_decode_block('\ndefault:\n', 'break;\n')
1495 self.defaultStack.push(codeObj)
1496 # no meaningful value returned
1497 t[0] = None
1498
1499 def p_decode_stmt_list_0(self, t):
1500 'decode_stmt_list : decode_stmt'
1501 t[0] = t[1]
1502
1503 def p_decode_stmt_list_1(self, t):
1504 'decode_stmt_list : decode_stmt decode_stmt_list'
1505 if (t[1].has_decode_default and t[2].has_decode_default):
1506 error(t, 'Two default cases in decode block')
1507 t[0] = t[1] + t[2]
1508
1509 #
1510 # Decode statement rules
1511 #
1512 # There are four types of statements allowed in a decode block:
1513 # 1. Format blocks 'format <foo> { ... }'
1514 # 2. Nested decode blocks
1515 # 3. Instruction definitions.
1516 # 4. C preprocessor directives.
1517
1518
1519 # Preprocessor directives found in a decode statement list are
1520 # passed through to the output, replicated to all of the output
1521 # code streams. This works well for ifdefs, so we can ifdef out
1522 # both the declarations and the decode cases generated by an
1523 # instruction definition. Handling them as part of the grammar
1524 # makes it easy to keep them in the right place with respect to
1525 # the code generated by the other statements.
1526 def p_decode_stmt_cpp(self, t):
1527 'decode_stmt : CPPDIRECTIVE'
1528 t[0] = GenCode(self, t[1], t[1], t[1], t[1])
1529
1530 # A format block 'format <foo> { ... }' sets the default
1531 # instruction format used to handle instruction definitions inside
1532 # the block. This format can be overridden by using an explicit
1533 # format on the instruction definition or with a nested format
1534 # block.
1535 def p_decode_stmt_format(self, t):
1536 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
1537 # The format will be pushed on the stack when 'push_format_id'
1538 # is processed (see below). Once the parser has recognized
1539 # the full production (though the right brace), we're done
1540 # with the format, so now we can pop it.
1541 self.formatStack.pop()
1542 t[0] = t[4]
1543
1544 # This rule exists so we can set the current format (& push the
1545 # stack) when we recognize the format name part of the format
1546 # block.
1547 def p_push_format_id(self, t):
1548 'push_format_id : ID'
1549 try:
1550 self.formatStack.push(self.formatMap[t[1]])
1551 t[0] = ('', '// format %s' % t[1])
1552 except KeyError:
1553 error(t, 'instruction format "%s" not defined.' % t[1])
1554
1555 # Nested decode block: if the value of the current field matches
1556 # the specified constant, do a nested decode on some other field.
1557 def p_decode_stmt_decode(self, t):
1558 'decode_stmt : case_label COLON decode_block'
1559 label = t[1]
1560 codeObj = t[3]
1561 # just wrap the decoding code from the block as a case in the
1562 # outer switch statement.
1563 codeObj.wrap_decode_block('\n%s:\n' % label)
1564 codeObj.has_decode_default = (label == 'default')
1565 t[0] = codeObj
1566
1567 # Instruction definition (finally!).
1568 def p_decode_stmt_inst(self, t):
1569 'decode_stmt : case_label COLON inst SEMI'
1570 label = t[1]
1571 codeObj = t[3]
1572 codeObj.wrap_decode_block('\n%s:' % label, 'break;\n')
1573 codeObj.has_decode_default = (label == 'default')
1574 t[0] = codeObj
1575
1576 # The case label is either a list of one or more constants or
1577 # 'default'
1578 def p_case_label_0(self, t):
1579 'case_label : intlit_list'
1580 def make_case(intlit):
1581 if intlit >= 2**32:
1582 return 'case ULL(%#x)' % intlit
1583 else:
1584 return 'case %#x' % intlit
1585 t[0] = ': '.join(map(make_case, t[1]))
1586
1587 def p_case_label_1(self, t):
1588 'case_label : DEFAULT'
1589 t[0] = 'default'
1590
1591 #
1592 # The constant list for a decode case label must be non-empty, but
1593 # may have one or more comma-separated integer literals in it.
1594 #
1595 def p_intlit_list_0(self, t):
1596 'intlit_list : INTLIT'
1597 t[0] = [t[1]]
1598
1599 def p_intlit_list_1(self, t):
1600 'intlit_list : intlit_list COMMA INTLIT'
1601 t[0] = t[1]
1602 t[0].append(t[3])
1603
1604 # Define an instruction using the current instruction format
1605 # (specified by an enclosing format block).
1606 # "<mnemonic>(<args>)"
1607 def p_inst_0(self, t):
1608 'inst : ID LPAREN arg_list RPAREN'
1609 # Pass the ID and arg list to the current format class to deal with.
1610 currentFormat = self.formatStack.top()
1611 codeObj = currentFormat.defineInst(self, t[1], t[3], t.lexer.lineno)
1612 args = ','.join(map(str, t[3]))
1613 args = re.sub('(?m)^', '//', args)
1614 args = re.sub('^//', '', args)
1615 comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args)
1616 codeObj.prepend_all(comment)
1617 t[0] = codeObj
1618
1619 # Define an instruction using an explicitly specified format:
1620 # "<fmt>::<mnemonic>(<args>)"
1621 def p_inst_1(self, t):
1622 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1623 try:
1624 format = self.formatMap[t[1]]
1625 except KeyError:
1626 error(t, 'instruction format "%s" not defined.' % t[1])
1627
1628 codeObj = format.defineInst(self, t[3], t[5], t.lexer.lineno)
1629 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5])
1630 codeObj.prepend_all(comment)
1631 t[0] = codeObj
1632
1633 # The arg list generates a tuple, where the first element is a
1634 # list of the positional args and the second element is a dict
1635 # containing the keyword args.
1636 def p_arg_list_0(self, t):
1637 'arg_list : positional_arg_list COMMA keyword_arg_list'
1638 t[0] = ( t[1], t[3] )
1639
1640 def p_arg_list_1(self, t):
1641 'arg_list : positional_arg_list'
1642 t[0] = ( t[1], {} )
1643
1644 def p_arg_list_2(self, t):
1645 'arg_list : keyword_arg_list'
1646 t[0] = ( [], t[1] )
1647
1648 def p_positional_arg_list_0(self, t):
1649 'positional_arg_list : empty'
1650 t[0] = []
1651
1652 def p_positional_arg_list_1(self, t):
1653 'positional_arg_list : expr'
1654 t[0] = [t[1]]
1655
1656 def p_positional_arg_list_2(self, t):
1657 'positional_arg_list : positional_arg_list COMMA expr'
1658 t[0] = t[1] + [t[3]]
1659
1660 def p_keyword_arg_list_0(self, t):
1661 'keyword_arg_list : keyword_arg'
1662 t[0] = t[1]
1663
1664 def p_keyword_arg_list_1(self, t):
1665 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
1666 t[0] = t[1]
1667 t[0].update(t[3])
1668
1669 def p_keyword_arg(self, t):
1670 'keyword_arg : ID EQUALS expr'
1671 t[0] = { t[1] : t[3] }
1672
1673 #
1674 # Basic expressions. These constitute the argument values of
1675 # "function calls" (i.e. instruction definitions in the decode
1676 # block) and default values for formal parameters of format
1677 # functions.
1678 #
1679 # Right now, these are either strings, integers, or (recursively)
1680 # lists of exprs (using Python square-bracket list syntax). Note
1681 # that bare identifiers are trated as string constants here (since
1682 # there isn't really a variable namespace to refer to).
1683 #
1684 def p_expr_0(self, t):
1685 '''expr : ID
1686 | INTLIT
1687 | STRLIT
1688 | CODELIT'''
1689 t[0] = t[1]
1690
1691 def p_expr_1(self, t):
1692 '''expr : LBRACKET list_expr RBRACKET'''
1693 t[0] = t[2]
1694
1695 def p_list_expr_0(self, t):
1696 'list_expr : expr'
1697 t[0] = [t[1]]
1698
1699 def p_list_expr_1(self, t):
1700 'list_expr : list_expr COMMA expr'
1701 t[0] = t[1] + [t[3]]
1702
1703 def p_list_expr_2(self, t):
1704 'list_expr : empty'
1705 t[0] = []
1706
1707 #
1708 # Empty production... use in other rules for readability.
1709 #
1710 def p_empty(self, t):
1711 'empty :'
1712 pass
1713
1714 # Parse error handler. Note that the argument here is the
1715 # offending *token*, not a grammar symbol (hence the need to use
1716 # t.value)
1717 def p_error(self, t):
1718 if t:
1719 error(t, "syntax error at '%s'" % t.value)
1720 else:
1721 error("unknown syntax error")
1722
1723 # END OF GRAMMAR RULES
1724
1725 def updateExportContext(self):
1726
1727 # create a continuation that allows us to grab the current parser
1728 def wrapInstObjParams(*args):
1729 return InstObjParams(self, *args)
1730 self.exportContext['InstObjParams'] = wrapInstObjParams
1731 self.exportContext.update(self.templateMap)
1732
1733 def defFormat(self, id, params, code, lineno):
1734 '''Define a new format'''
1735
1736 # make sure we haven't already defined this one
1737 if id in self.formatMap:
1738 error(lineno, 'format %s redefined.' % id)
1739
1740 # create new object and store in global map
1741 self.formatMap[id] = Format(id, params, code)
1742
1743 def expandCpuSymbolsToDict(self, template):
1744 '''Expand template with CPU-specific references into a
1745 dictionary with an entry for each CPU model name. The entry
1746 key is the model name and the corresponding value is the
1747 template with the CPU-specific refs substituted for that
1748 model.'''
1749
1750 # Protect '%'s that don't go with CPU-specific terms
1751 t = re.sub(r'%(?!\(CPU_)', '%%', template)
1752 result = {}
1753 for cpu in self.cpuModels:
1754 result[cpu.name] = t % cpu.strings
1755 return result
1756
1757 def expandCpuSymbolsToString(self, template):
1758 '''*If* the template has CPU-specific references, return a
1759 single string containing a copy of the template for each CPU
1760 model with the corresponding values substituted in. If the
1761 template has no CPU-specific references, it is returned
1762 unmodified.'''
1763
1764 if template.find('%(CPU_') != -1:
1765 return reduce(lambda x,y: x+y,
1766 self.expandCpuSymbolsToDict(template).values())
1767 else:
1768 return template
1769
1770 def protectCpuSymbols(self, template):
1771 '''Protect CPU-specific references by doubling the
1772 corresponding '%'s (in preparation for substituting a different
1773 set of references into the template).'''
1774
1775 return re.sub(r'%(?=\(CPU_)', '%%', template)
1776
1777 def protectNonSubstPercents(self, s):
1778 '''Protect any non-dict-substitution '%'s in a format string
1779 (i.e. those not followed by '(')'''
1780
1781 return re.sub(r'%(?!\()', '%%', s)
1782
1783 def buildOperandNameMap(self, user_dict, lineno):
1784 operand_name = {}
1785 for op_name, val in user_dict.iteritems():
1786 base_cls_name, dflt_ext, reg_spec, flags, sort_pri = val[:5]
1787 if len(val) > 5:
1788 read_code = val[5]
1789 else:
1790 read_code = None
1791 if len(val) > 6:
1792 write_code = val[6]
1793 else:
1794 write_code = None
1795 if len(val) > 7:
1796 error(lineno,
1797 'error: too many attributes for operand "%s"' %
1798 base_cls_name)
1799
1800 # Canonical flag structure is a triple of lists, where each list
1801 # indicates the set of flags implied by this operand always, when
1802 # used as a source, and when used as a dest, respectively.
1803 # For simplicity this can be initialized using a variety of fairly
1804 # obvious shortcuts; we convert these to canonical form here.
1805 if not flags:
1806 # no flags specified (e.g., 'None')
1807 flags = ( [], [], [] )
1808 elif isinstance(flags, str):
1809 # a single flag: assumed to be unconditional
1810 flags = ( [ flags ], [], [] )
1811 elif isinstance(flags, list):
1812 # a list of flags: also assumed to be unconditional
1813 flags = ( flags, [], [] )
1814 elif isinstance(flags, tuple):
1815 # it's a tuple: it should be a triple,
1816 # but each item could be a single string or a list
1817 (uncond_flags, src_flags, dest_flags) = flags
1818 flags = (makeList(uncond_flags),
1819 makeList(src_flags), makeList(dest_flags))
1820 # Accumulate attributes of new operand class in tmp_dict
1821 tmp_dict = {}
1822 attrList = ['reg_spec', 'flags', 'sort_pri',
1823 'read_code', 'write_code']
1824 if dflt_ext:
1825 dflt_ctype = self.operandTypeMap[dflt_ext]
1826 attrList.extend(['dflt_ctype', 'dflt_ext'])
1827 for attr in attrList:
1828 tmp_dict[attr] = eval(attr)
1829 tmp_dict['base_name'] = op_name
1830 # New class name will be e.g. "IntReg_Ra"
1831 cls_name = base_cls_name + '_' + op_name
1832 # Evaluate string arg to get class object. Note that the
1833 # actual base class for "IntReg" is "IntRegOperand", i.e. we
1834 # have to append "Operand".
1835 try:
1836 base_cls = eval(base_cls_name + 'Operand')
1837 except NameError:
1838 error(lineno,
1839 'error: unknown operand base class "%s"' % base_cls_name)
1840 # The following statement creates a new class called
1841 # <cls_name> as a subclass of <base_cls> with the attributes
1842 # in tmp_dict, just as if we evaluated a class declaration.
1843 operand_name[op_name] = type(cls_name, (base_cls,), tmp_dict)
1844
1845 self.operandNameMap = operand_name
1846
1847 # Define operand variables.
1848 operands = user_dict.keys()
1849
1850 operandsREString = (r'''
1851 (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
1852 ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
1853 (?![\w\.]) # neg. lookahead assertion: prevent partial matches
1854 '''
1855 % string.join(operands, '|'))
1856
1857 self.operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
1858
1859 # Same as operandsREString, but extension is mandatory, and only two
1860 # groups are returned (base and ext, not full name as above).
1861 # Used for subtituting '_' for '.' to make C++ identifiers.
1862 operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
1863 % string.join(operands, '|'))
1864
1865 self.operandsWithExtRE = \
1866 re.compile(operandsWithExtREString, re.MULTILINE)
1867
1868 def substMungedOpNames(self, code):
1869 '''Munge operand names in code string to make legal C++
1870 variable names. This means getting rid of the type extension
1871 if any. Will match base_name attribute of Operand object.)'''
1872 return self.operandsWithExtRE.sub(r'\1', code)
1873
1874 def mungeSnippet(self, s):
1875 '''Fix up code snippets for final substitution in templates.'''
1876 if isinstance(s, str):
1877 return self.substMungedOpNames(substBitOps(s))
1878 else:
1879 return s
1880
1881 def update_if_needed(self, file, contents):
1882 '''Update the output file only if the new contents are
1883 different from the current contents. Minimizes the files that
1884 need to be rebuilt after minor changes.'''
1885
1886 file = os.path.join(self.output_dir, file)
1887 update = False
1888 if os.access(file, os.R_OK):
1889 f = open(file, 'r')
1890 old_contents = f.read()
1891 f.close()
1892 if contents != old_contents:
1893 os.remove(file) # in case it's write-protected
1894 update = True
1895 else:
1896 print 'File', file, 'is unchanged'
1897 else:
1898 update = True
1899 if update:
1900 f = open(file, 'w')
1901 f.write(contents)
1902 f.close()
1903
1904 # This regular expression matches '##include' directives
1905 includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[^"]*)".*$',
1906 re.MULTILINE)
1907
1908 def replace_include(self, matchobj, dirname):
1909 """Function to replace a matched '##include' directive with the
1910 contents of the specified file (with nested ##includes
1911 replaced recursively). 'matchobj' is an re match object
1912 (from a match of includeRE) and 'dirname' is the directory
1913 relative to which the file path should be resolved."""
1914
1915 fname = matchobj.group('filename')
1916 full_fname = os.path.normpath(os.path.join(dirname, fname))
1917 contents = '##newfile "%s"\n%s\n##endfile\n' % \
1918 (full_fname, self.read_and_flatten(full_fname))
1919 return contents
1920
1921 def read_and_flatten(self, filename):
1922 """Read a file and recursively flatten nested '##include' files."""
1923
1924 current_dir = os.path.dirname(filename)
1925 try:
1926 contents = open(filename).read()
1927 except IOError:
1928 error('Error including file "%s"' % filename)
1929
1930 self.fileNameStack.push((filename, 0))
1931
1932 # Find any includes and include them
1933 def replace(matchobj):
1934 return self.replace_include(matchobj, current_dir)
1935 contents = self.includeRE.sub(replace, contents)
1936
1937 self.fileNameStack.pop()
1938 return contents
1939
1940 def _parse_isa_desc(self, isa_desc_file):
1941 '''Read in and parse the ISA description.'''
1942
1943 # Read file and (recursively) all included files into a string.
1944 # PLY requires that the input be in a single string so we have to
1945 # do this up front.
1946 isa_desc = self.read_and_flatten(isa_desc_file)
1947
1948 # Initialize filename stack with outer file.
1949 self.fileNameStack.push((isa_desc_file, 0))
1950
1951 # Parse it.
1952 (isa_name, namespace, global_code, namespace_code) = \
1953 self.parse_string(isa_desc)
1954
1955 # grab the last three path components of isa_desc_file to put in
1956 # the output
1957 filename = '/'.join(isa_desc_file.split('/')[-3:])
1958
1959 # generate decoder.hh
1960 includes = '#include "base/bitfield.hh" // for bitfield support'
1961 global_output = global_code.header_output
1962 namespace_output = namespace_code.header_output
1963 decode_function = ''
1964 self.update_if_needed('decoder.hh', file_template % vars())
1965
1966 # generate decoder.cc
1967 includes = '#include "decoder.hh"'
1968 global_output = global_code.decoder_output
1969 namespace_output = namespace_code.decoder_output
1970 # namespace_output += namespace_code.decode_block
1971 decode_function = namespace_code.decode_block
1972 self.update_if_needed('decoder.cc', file_template % vars())
1973
1974 # generate per-cpu exec files
1975 for cpu in self.cpuModels:
1976 includes = '#include "decoder.hh"\n'
1977 includes += cpu.includes
1978 global_output = global_code.exec_output[cpu.name]
1979 namespace_output = namespace_code.exec_output[cpu.name]
1980 decode_function = ''
1981 self.update_if_needed(cpu.filename, file_template % vars())
1982
1983 # The variable names here are hacky, but this will creat local
1984 # variables which will be referenced in vars() which have the
1985 # value of the globals.
1986 MaxInstSrcRegs = self.maxInstSrcRegs
1987 MaxInstDestRegs = self.maxInstDestRegs
1988 # max_inst_regs.hh
1989 self.update_if_needed('max_inst_regs.hh',
1990 max_inst_regs_template % vars())
1991
1992 def parse_isa_desc(self, *args, **kwargs):
1993 try:
1994 self._parse_isa_desc(*args, **kwargs)
1995 except ISAParserError, e:
1996 e.exit(self.fileNameStack)
1997
1998 # Called as script: get args from command line.
1999 # Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2000 if __name__ == '__main__':
2001 execfile(sys.argv[1]) # read in CpuModel definitions
2002 cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
2003 ISAParser(sys.argv[3], cpu_models).parse_isa_desc(sys.argv[2])