isa_parser.py (9022:bb25e7646c41) isa_parser.py (9046:a1104cc13db2)
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
29import os
30import sys
31import re
32import string
33import inspect, traceback
34# get type names
35from types import *
36
37from m5.util.grammar import Grammar
38
39debug=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#
49def 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
69def 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
76class 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
114def 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
123labelRE = re.compile(r'(?<!%)%\(([^\)]+)\)[sd]')
124
125class 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
235class 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.
272class 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
294class 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
348bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>')
349
350bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
351bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
352
353def 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.
395def 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
405class 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
512class 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
550class 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
593class 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
630class 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
653class 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
684class 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 strings and comments so we don't match on operands inside
691 for regEx in (stringRE, commentRE):
692 code = regEx.sub('', code)
693 # search for operands
694 next_pos = 0
695 while 1:
696 match = parser.operandsRE.search(code, next_pos)
697 if not match:
698 # no more matches: we're done
699 break
700 op = match.groups()
701 # regexp groups are operand full name, base, and extension
702 (op_full, op_base, op_ext) = op
703 # if the token following the operand is an assignment, this is
704 # a destination (LHS), else it's a source (RHS)
705 is_dest = (assignRE.match(code, match.end()) != None)
706 is_src = not is_dest
707 # see if we've already seen this one
708 op_desc = self.find_base(op_base)
709 if op_desc:
710 if op_desc.ext != op_ext:
711 error('Inconsistent extensions for operand %s' % \
712 op_base)
713 op_desc.is_src = op_desc.is_src or is_src
714 op_desc.is_dest = op_desc.is_dest or is_dest
715 else:
716 # new operand: create new descriptor
717 op_desc = parser.operandNameMap[op_base](parser,
718 op_full, op_ext, is_src, is_dest)
719 self.append(op_desc)
720 # start next search after end of current match
721 next_pos = match.end()
722 self.sort()
723 # enumerate source & dest register operands... used in building
724 # constructor later
725 self.numSrcRegs = 0
726 self.numDestRegs = 0
727 self.numFPDestRegs = 0
728 self.numIntDestRegs = 0
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
29import os
30import sys
31import re
32import string
33import inspect, traceback
34# get type names
35from types import *
36
37from m5.util.grammar import Grammar
38
39debug=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#
49def 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
69def 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
76class 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
114def 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
123labelRE = re.compile(r'(?<!%)%\(([^\)]+)\)[sd]')
124
125class 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
235class 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.
272class 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
294class 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
348bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>')
349
350bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
351bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
352
353def 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.
395def 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
405class 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
512class 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
550class 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
593class 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
630class 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
653class 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
684class 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 strings and comments so we don't match on operands inside
691 for regEx in (stringRE, commentRE):
692 code = regEx.sub('', code)
693 # search for operands
694 next_pos = 0
695 while 1:
696 match = parser.operandsRE.search(code, next_pos)
697 if not match:
698 # no more matches: we're done
699 break
700 op = match.groups()
701 # regexp groups are operand full name, base, and extension
702 (op_full, op_base, op_ext) = op
703 # if the token following the operand is an assignment, this is
704 # a destination (LHS), else it's a source (RHS)
705 is_dest = (assignRE.match(code, match.end()) != None)
706 is_src = not is_dest
707 # see if we've already seen this one
708 op_desc = self.find_base(op_base)
709 if op_desc:
710 if op_desc.ext != op_ext:
711 error('Inconsistent extensions for operand %s' % \
712 op_base)
713 op_desc.is_src = op_desc.is_src or is_src
714 op_desc.is_dest = op_desc.is_dest or is_dest
715 else:
716 # new operand: create new descriptor
717 op_desc = parser.operandNameMap[op_base](parser,
718 op_full, op_ext, is_src, is_dest)
719 self.append(op_desc)
720 # start next search after end of current match
721 next_pos = match.end()
722 self.sort()
723 # enumerate source & dest register operands... used in building
724 # constructor later
725 self.numSrcRegs = 0
726 self.numDestRegs = 0
727 self.numFPDestRegs = 0
728 self.numIntDestRegs = 0
729 self.numMiscDestRegs = 0
729 self.memOperand = None
730 for op_desc in self.items:
731 if op_desc.isReg():
732 if op_desc.is_src:
733 op_desc.src_reg_idx = self.numSrcRegs
734 self.numSrcRegs += 1
735 if op_desc.is_dest:
736 op_desc.dest_reg_idx = self.numDestRegs
737 self.numDestRegs += 1
738 if op_desc.isFloatReg():
739 self.numFPDestRegs += 1
740 elif op_desc.isIntReg():
741 self.numIntDestRegs += 1
730 self.memOperand = None
731 for op_desc in self.items:
732 if op_desc.isReg():
733 if op_desc.is_src:
734 op_desc.src_reg_idx = self.numSrcRegs
735 self.numSrcRegs += 1
736 if op_desc.is_dest:
737 op_desc.dest_reg_idx = self.numDestRegs
738 self.numDestRegs += 1
739 if op_desc.isFloatReg():
740 self.numFPDestRegs += 1
741 elif op_desc.isIntReg():
742 self.numIntDestRegs += 1
743 elif op_desc.isControlReg():
744 self.numMiscDestRegs += 1
742 elif op_desc.isMem():
743 if self.memOperand:
744 error("Code block has more than one memory operand.")
745 self.memOperand = op_desc
746 if parser.maxInstSrcRegs < self.numSrcRegs:
747 parser.maxInstSrcRegs = self.numSrcRegs
748 if parser.maxInstDestRegs < self.numDestRegs:
749 parser.maxInstDestRegs = self.numDestRegs
745 elif op_desc.isMem():
746 if self.memOperand:
747 error("Code block has more than one memory operand.")
748 self.memOperand = op_desc
749 if parser.maxInstSrcRegs < self.numSrcRegs:
750 parser.maxInstSrcRegs = self.numSrcRegs
751 if parser.maxInstDestRegs < self.numDestRegs:
752 parser.maxInstDestRegs = self.numDestRegs
753 if parser.maxMiscDestRegs < self.numMiscDestRegs:
754 parser.maxMiscDestRegs = self.numMiscDestRegs
750 # now make a final pass to finalize op_desc fields that may depend
751 # on the register enumeration
752 for op_desc in self.items:
753 op_desc.finalize()
754
755 def __len__(self):
756 return len(self.items)
757
758 def __getitem__(self, index):
759 return self.items[index]
760
761 def append(self, op_desc):
762 self.items.append(op_desc)
763 self.bases[op_desc.base_name] = op_desc
764
765 def find_base(self, base_name):
766 # like self.bases[base_name], but returns None if not found
767 # (rather than raising exception)
768 return self.bases.get(base_name)
769
770 # internal helper function for concat[Some]Attr{Strings|Lists}
771 def __internalConcatAttrs(self, attr_name, filter, result):
772 for op_desc in self.items:
773 if filter(op_desc):
774 result += getattr(op_desc, attr_name)
775 return result
776
777 # return a single string that is the concatenation of the (string)
778 # values of the specified attribute for all operands
779 def concatAttrStrings(self, attr_name):
780 return self.__internalConcatAttrs(attr_name, lambda x: 1, '')
781
782 # like concatAttrStrings, but only include the values for the operands
783 # for which the provided filter function returns true
784 def concatSomeAttrStrings(self, filter, attr_name):
785 return self.__internalConcatAttrs(attr_name, filter, '')
786
787 # return a single list that is the concatenation of the (list)
788 # values of the specified attribute for all operands
789 def concatAttrLists(self, attr_name):
790 return self.__internalConcatAttrs(attr_name, lambda x: 1, [])
791
792 # like concatAttrLists, but only include the values for the operands
793 # for which the provided filter function returns true
794 def concatSomeAttrLists(self, filter, attr_name):
795 return self.__internalConcatAttrs(attr_name, filter, [])
796
797 def sort(self):
798 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
799
800class SubOperandList(OperandList):
801 '''Find all the operands in the given code block. Returns an operand
802 descriptor list (instance of class OperandList).'''
803 def __init__(self, parser, code, master_list):
804 self.items = []
805 self.bases = {}
806 # delete strings and comments so we don't match on operands inside
807 for regEx in (stringRE, commentRE):
808 code = regEx.sub('', code)
809 # search for operands
810 next_pos = 0
811 while 1:
812 match = parser.operandsRE.search(code, next_pos)
813 if not match:
814 # no more matches: we're done
815 break
816 op = match.groups()
817 # regexp groups are operand full name, base, and extension
818 (op_full, op_base, op_ext) = op
819 # find this op in the master list
820 op_desc = master_list.find_base(op_base)
821 if not op_desc:
822 error('Found operand %s which is not in the master list!' \
823 ' This is an internal error' % op_base)
824 else:
825 # See if we've already found this operand
826 op_desc = self.find_base(op_base)
827 if not op_desc:
828 # if not, add a reference to it to this sub list
829 self.append(master_list.bases[op_base])
830
831 # start next search after end of current match
832 next_pos = match.end()
833 self.sort()
834 self.memOperand = None
835 # Whether the whole PC needs to be read so parts of it can be accessed
836 self.readPC = False
837 # Whether the whole PC needs to be written after parts of it were
838 # changed
839 self.setPC = False
840 # Whether this instruction manipulates the whole PC or parts of it.
841 # Mixing the two is a bad idea and flagged as an error.
842 self.pcPart = None
843 for op_desc in self.items:
844 if op_desc.isPCPart():
845 self.readPC = True
846 if op_desc.is_dest:
847 self.setPC = True
848 if op_desc.isPCState():
849 if self.pcPart is not None:
850 if self.pcPart and not op_desc.isPCPart() or \
851 not self.pcPart and op_desc.isPCPart():
852 error("Mixed whole and partial PC state operands.")
853 self.pcPart = op_desc.isPCPart()
854 if op_desc.isMem():
855 if self.memOperand:
856 error("Code block has more than one memory operand.")
857 self.memOperand = op_desc
858
859# Regular expression object to match C++ strings
860stringRE = re.compile(r'"([^"\\]|\\.)*"')
861
862# Regular expression object to match C++ comments
863# (used in findOperands())
864commentRE = re.compile(r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
865 re.DOTALL | re.MULTILINE)
866
867# Regular expression object to match assignment statements
868# (used in findOperands())
869assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
870
871def makeFlagConstructor(flag_list):
872 if len(flag_list) == 0:
873 return ''
874 # filter out repeated flags
875 flag_list.sort()
876 i = 1
877 while i < len(flag_list):
878 if flag_list[i] == flag_list[i-1]:
879 del flag_list[i]
880 else:
881 i += 1
882 pre = '\n\tflags['
883 post = '] = true;'
884 code = pre + string.join(flag_list, post + pre) + post
885 return code
886
887# Assume all instruction flags are of the form 'IsFoo'
888instFlagRE = re.compile(r'Is.*')
889
890# OpClass constants end in 'Op' except No_OpClass
891opClassRE = re.compile(r'.*Op|No_OpClass')
892
893class InstObjParams(object):
894 def __init__(self, parser, mnem, class_name, base_class = '',
895 snippets = {}, opt_args = []):
896 self.mnemonic = mnem
897 self.class_name = class_name
898 self.base_class = base_class
899 if not isinstance(snippets, dict):
900 snippets = {'code' : snippets}
901 compositeCode = ' '.join(map(str, snippets.values()))
902 self.snippets = snippets
903
904 self.operands = OperandList(parser, compositeCode)
905 self.constructor = self.operands.concatAttrStrings('constructor')
906 self.constructor += \
907 '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
908 self.constructor += \
909 '\n\t_numDestRegs = %d;' % self.operands.numDestRegs
910 self.constructor += \
911 '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs
912 self.constructor += \
913 '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
914 self.flags = self.operands.concatAttrLists('flags')
915
916 # Make a basic guess on the operand class (function unit type).
917 # These are good enough for most cases, and can be overridden
918 # later otherwise.
919 if 'IsStore' in self.flags:
920 self.op_class = 'MemWriteOp'
921 elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags:
922 self.op_class = 'MemReadOp'
923 elif 'IsFloating' in self.flags:
924 self.op_class = 'FloatAddOp'
925 else:
926 self.op_class = 'IntAluOp'
927
928 # Optional arguments are assumed to be either StaticInst flags
929 # or an OpClass value. To avoid having to import a complete
930 # list of these values to match against, we do it ad-hoc
931 # with regexps.
932 for oa in opt_args:
933 if instFlagRE.match(oa):
934 self.flags.append(oa)
935 elif opClassRE.match(oa):
936 self.op_class = oa
937 else:
938 error('InstObjParams: optional arg "%s" not recognized '
939 'as StaticInst::Flag or OpClass.' % oa)
940
941 # add flag initialization to contructor here to include
942 # any flags added via opt_args
943 self.constructor += makeFlagConstructor(self.flags)
944
945 # if 'IsFloating' is set, add call to the FP enable check
946 # function (which should be provided by isa_desc via a declare)
947 if 'IsFloating' in self.flags:
948 self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
949 else:
950 self.fp_enable_check = ''
951
952##############
953# Stack: a simple stack object. Used for both formats (formatStack)
954# and default cases (defaultStack). Simply wraps a list to give more
955# stack-like syntax and enable initialization with an argument list
956# (as opposed to an argument that's a list).
957
958class Stack(list):
959 def __init__(self, *items):
960 list.__init__(self, items)
961
962 def push(self, item):
963 self.append(item);
964
965 def top(self):
966 return self[-1]
967
968#######################
969#
970# Output file template
971#
972
973file_template = '''
974/*
975 * DO NOT EDIT THIS FILE!!!
976 *
977 * It was automatically generated from the ISA description in %(filename)s
978 */
979
980%(includes)s
981
982%(global_output)s
983
984namespace %(namespace)s {
985
986%(namespace_output)s
987
988} // namespace %(namespace)s
989
990%(decode_function)s
991'''
992
993max_inst_regs_template = '''
994/*
995 * DO NOT EDIT THIS FILE!!!
996 *
997 * It was automatically generated from the ISA description in %(filename)s
998 */
999
1000namespace %(namespace)s {
1001
1002 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
1003 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
755 # now make a final pass to finalize op_desc fields that may depend
756 # on the register enumeration
757 for op_desc in self.items:
758 op_desc.finalize()
759
760 def __len__(self):
761 return len(self.items)
762
763 def __getitem__(self, index):
764 return self.items[index]
765
766 def append(self, op_desc):
767 self.items.append(op_desc)
768 self.bases[op_desc.base_name] = op_desc
769
770 def find_base(self, base_name):
771 # like self.bases[base_name], but returns None if not found
772 # (rather than raising exception)
773 return self.bases.get(base_name)
774
775 # internal helper function for concat[Some]Attr{Strings|Lists}
776 def __internalConcatAttrs(self, attr_name, filter, result):
777 for op_desc in self.items:
778 if filter(op_desc):
779 result += getattr(op_desc, attr_name)
780 return result
781
782 # return a single string that is the concatenation of the (string)
783 # values of the specified attribute for all operands
784 def concatAttrStrings(self, attr_name):
785 return self.__internalConcatAttrs(attr_name, lambda x: 1, '')
786
787 # like concatAttrStrings, but only include the values for the operands
788 # for which the provided filter function returns true
789 def concatSomeAttrStrings(self, filter, attr_name):
790 return self.__internalConcatAttrs(attr_name, filter, '')
791
792 # return a single list that is the concatenation of the (list)
793 # values of the specified attribute for all operands
794 def concatAttrLists(self, attr_name):
795 return self.__internalConcatAttrs(attr_name, lambda x: 1, [])
796
797 # like concatAttrLists, but only include the values for the operands
798 # for which the provided filter function returns true
799 def concatSomeAttrLists(self, filter, attr_name):
800 return self.__internalConcatAttrs(attr_name, filter, [])
801
802 def sort(self):
803 self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
804
805class SubOperandList(OperandList):
806 '''Find all the operands in the given code block. Returns an operand
807 descriptor list (instance of class OperandList).'''
808 def __init__(self, parser, code, master_list):
809 self.items = []
810 self.bases = {}
811 # delete strings and comments so we don't match on operands inside
812 for regEx in (stringRE, commentRE):
813 code = regEx.sub('', code)
814 # search for operands
815 next_pos = 0
816 while 1:
817 match = parser.operandsRE.search(code, next_pos)
818 if not match:
819 # no more matches: we're done
820 break
821 op = match.groups()
822 # regexp groups are operand full name, base, and extension
823 (op_full, op_base, op_ext) = op
824 # find this op in the master list
825 op_desc = master_list.find_base(op_base)
826 if not op_desc:
827 error('Found operand %s which is not in the master list!' \
828 ' This is an internal error' % op_base)
829 else:
830 # See if we've already found this operand
831 op_desc = self.find_base(op_base)
832 if not op_desc:
833 # if not, add a reference to it to this sub list
834 self.append(master_list.bases[op_base])
835
836 # start next search after end of current match
837 next_pos = match.end()
838 self.sort()
839 self.memOperand = None
840 # Whether the whole PC needs to be read so parts of it can be accessed
841 self.readPC = False
842 # Whether the whole PC needs to be written after parts of it were
843 # changed
844 self.setPC = False
845 # Whether this instruction manipulates the whole PC or parts of it.
846 # Mixing the two is a bad idea and flagged as an error.
847 self.pcPart = None
848 for op_desc in self.items:
849 if op_desc.isPCPart():
850 self.readPC = True
851 if op_desc.is_dest:
852 self.setPC = True
853 if op_desc.isPCState():
854 if self.pcPart is not None:
855 if self.pcPart and not op_desc.isPCPart() or \
856 not self.pcPart and op_desc.isPCPart():
857 error("Mixed whole and partial PC state operands.")
858 self.pcPart = op_desc.isPCPart()
859 if op_desc.isMem():
860 if self.memOperand:
861 error("Code block has more than one memory operand.")
862 self.memOperand = op_desc
863
864# Regular expression object to match C++ strings
865stringRE = re.compile(r'"([^"\\]|\\.)*"')
866
867# Regular expression object to match C++ comments
868# (used in findOperands())
869commentRE = re.compile(r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
870 re.DOTALL | re.MULTILINE)
871
872# Regular expression object to match assignment statements
873# (used in findOperands())
874assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
875
876def makeFlagConstructor(flag_list):
877 if len(flag_list) == 0:
878 return ''
879 # filter out repeated flags
880 flag_list.sort()
881 i = 1
882 while i < len(flag_list):
883 if flag_list[i] == flag_list[i-1]:
884 del flag_list[i]
885 else:
886 i += 1
887 pre = '\n\tflags['
888 post = '] = true;'
889 code = pre + string.join(flag_list, post + pre) + post
890 return code
891
892# Assume all instruction flags are of the form 'IsFoo'
893instFlagRE = re.compile(r'Is.*')
894
895# OpClass constants end in 'Op' except No_OpClass
896opClassRE = re.compile(r'.*Op|No_OpClass')
897
898class InstObjParams(object):
899 def __init__(self, parser, mnem, class_name, base_class = '',
900 snippets = {}, opt_args = []):
901 self.mnemonic = mnem
902 self.class_name = class_name
903 self.base_class = base_class
904 if not isinstance(snippets, dict):
905 snippets = {'code' : snippets}
906 compositeCode = ' '.join(map(str, snippets.values()))
907 self.snippets = snippets
908
909 self.operands = OperandList(parser, compositeCode)
910 self.constructor = self.operands.concatAttrStrings('constructor')
911 self.constructor += \
912 '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
913 self.constructor += \
914 '\n\t_numDestRegs = %d;' % self.operands.numDestRegs
915 self.constructor += \
916 '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs
917 self.constructor += \
918 '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
919 self.flags = self.operands.concatAttrLists('flags')
920
921 # Make a basic guess on the operand class (function unit type).
922 # These are good enough for most cases, and can be overridden
923 # later otherwise.
924 if 'IsStore' in self.flags:
925 self.op_class = 'MemWriteOp'
926 elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags:
927 self.op_class = 'MemReadOp'
928 elif 'IsFloating' in self.flags:
929 self.op_class = 'FloatAddOp'
930 else:
931 self.op_class = 'IntAluOp'
932
933 # Optional arguments are assumed to be either StaticInst flags
934 # or an OpClass value. To avoid having to import a complete
935 # list of these values to match against, we do it ad-hoc
936 # with regexps.
937 for oa in opt_args:
938 if instFlagRE.match(oa):
939 self.flags.append(oa)
940 elif opClassRE.match(oa):
941 self.op_class = oa
942 else:
943 error('InstObjParams: optional arg "%s" not recognized '
944 'as StaticInst::Flag or OpClass.' % oa)
945
946 # add flag initialization to contructor here to include
947 # any flags added via opt_args
948 self.constructor += makeFlagConstructor(self.flags)
949
950 # if 'IsFloating' is set, add call to the FP enable check
951 # function (which should be provided by isa_desc via a declare)
952 if 'IsFloating' in self.flags:
953 self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
954 else:
955 self.fp_enable_check = ''
956
957##############
958# Stack: a simple stack object. Used for both formats (formatStack)
959# and default cases (defaultStack). Simply wraps a list to give more
960# stack-like syntax and enable initialization with an argument list
961# (as opposed to an argument that's a list).
962
963class Stack(list):
964 def __init__(self, *items):
965 list.__init__(self, items)
966
967 def push(self, item):
968 self.append(item);
969
970 def top(self):
971 return self[-1]
972
973#######################
974#
975# Output file template
976#
977
978file_template = '''
979/*
980 * DO NOT EDIT THIS FILE!!!
981 *
982 * It was automatically generated from the ISA description in %(filename)s
983 */
984
985%(includes)s
986
987%(global_output)s
988
989namespace %(namespace)s {
990
991%(namespace_output)s
992
993} // namespace %(namespace)s
994
995%(decode_function)s
996'''
997
998max_inst_regs_template = '''
999/*
1000 * DO NOT EDIT THIS FILE!!!
1001 *
1002 * It was automatically generated from the ISA description in %(filename)s
1003 */
1004
1005namespace %(namespace)s {
1006
1007 const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
1008 const int MaxInstDestRegs = %(MaxInstDestRegs)d;
1009 const int MaxMiscDestRegs = %(MaxMiscDestRegs)d;
1004
1005} // namespace %(namespace)s
1006
1007'''
1008
1009class ISAParser(Grammar):
1010 def __init__(self, output_dir, cpu_models):
1011 super(ISAParser, self).__init__()
1012 self.output_dir = output_dir
1013
1014 self.cpuModels = cpu_models
1015
1016 # variable to hold templates
1017 self.templateMap = {}
1018
1019 # This dictionary maps format name strings to Format objects.
1020 self.formatMap = {}
1021
1022 # The format stack.
1023 self.formatStack = Stack(NoFormat())
1024
1025 # The default case stack.
1026 self.defaultStack = Stack(None)
1027
1028 # Stack that tracks current file and line number. Each
1029 # element is a tuple (filename, lineno) that records the
1030 # *current* filename and the line number in the *previous*
1031 # file where it was included.
1032 self.fileNameStack = Stack()
1033
1034 symbols = ('makeList', 're', 'string')
1035 self.exportContext = dict([(s, eval(s)) for s in symbols])
1036
1037 self.maxInstSrcRegs = 0
1038 self.maxInstDestRegs = 0
1010
1011} // namespace %(namespace)s
1012
1013'''
1014
1015class ISAParser(Grammar):
1016 def __init__(self, output_dir, cpu_models):
1017 super(ISAParser, self).__init__()
1018 self.output_dir = output_dir
1019
1020 self.cpuModels = cpu_models
1021
1022 # variable to hold templates
1023 self.templateMap = {}
1024
1025 # This dictionary maps format name strings to Format objects.
1026 self.formatMap = {}
1027
1028 # The format stack.
1029 self.formatStack = Stack(NoFormat())
1030
1031 # The default case stack.
1032 self.defaultStack = Stack(None)
1033
1034 # Stack that tracks current file and line number. Each
1035 # element is a tuple (filename, lineno) that records the
1036 # *current* filename and the line number in the *previous*
1037 # file where it was included.
1038 self.fileNameStack = Stack()
1039
1040 symbols = ('makeList', 're', 'string')
1041 self.exportContext = dict([(s, eval(s)) for s in symbols])
1042
1043 self.maxInstSrcRegs = 0
1044 self.maxInstDestRegs = 0
1045 self.maxMiscDestRegs = 0
1039
1040 #####################################################################
1041 #
1042 # Lexer
1043 #
1044 # The PLY lexer module takes two things as input:
1045 # - A list of token names (the string list 'tokens')
1046 # - A regular expression describing a match for each token. The
1047 # regexp for token FOO can be provided in two ways:
1048 # - as a string variable named t_FOO
1049 # - as the doc string for a function named t_FOO. In this case,
1050 # the function is also executed, allowing an action to be
1051 # associated with each token match.
1052 #
1053 #####################################################################
1054
1055 # Reserved words. These are listed separately as they are matched
1056 # using the same regexp as generic IDs, but distinguished in the
1057 # t_ID() function. The PLY documentation suggests this approach.
1058 reserved = (
1059 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
1060 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
1061 'OUTPUT', 'SIGNED', 'TEMPLATE'
1062 )
1063
1064 # List of tokens. The lex module requires this.
1065 tokens = reserved + (
1066 # identifier
1067 'ID',
1068
1069 # integer literal
1070 'INTLIT',
1071
1072 # string literal
1073 'STRLIT',
1074
1075 # code literal
1076 'CODELIT',
1077
1078 # ( ) [ ] { } < > , ; . : :: *
1079 'LPAREN', 'RPAREN',
1080 'LBRACKET', 'RBRACKET',
1081 'LBRACE', 'RBRACE',
1082 'LESS', 'GREATER', 'EQUALS',
1083 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON',
1084 'ASTERISK',
1085
1086 # C preprocessor directives
1087 'CPPDIRECTIVE'
1088
1089 # The following are matched but never returned. commented out to
1090 # suppress PLY warning
1091 # newfile directive
1092 # 'NEWFILE',
1093
1094 # endfile directive
1095 # 'ENDFILE'
1096 )
1097
1098 # Regular expressions for token matching
1099 t_LPAREN = r'\('
1100 t_RPAREN = r'\)'
1101 t_LBRACKET = r'\['
1102 t_RBRACKET = r'\]'
1103 t_LBRACE = r'\{'
1104 t_RBRACE = r'\}'
1105 t_LESS = r'\<'
1106 t_GREATER = r'\>'
1107 t_EQUALS = r'='
1108 t_COMMA = r','
1109 t_SEMI = r';'
1110 t_DOT = r'\.'
1111 t_COLON = r':'
1112 t_DBLCOLON = r'::'
1113 t_ASTERISK = r'\*'
1114
1115 # Identifiers and reserved words
1116 reserved_map = { }
1117 for r in reserved:
1118 reserved_map[r.lower()] = r
1119
1120 def t_ID(self, t):
1121 r'[A-Za-z_]\w*'
1122 t.type = self.reserved_map.get(t.value, 'ID')
1123 return t
1124
1125 # Integer literal
1126 def t_INTLIT(self, t):
1127 r'-?(0x[\da-fA-F]+)|\d+'
1128 try:
1129 t.value = int(t.value,0)
1130 except ValueError:
1131 error(t, 'Integer value "%s" too large' % t.value)
1132 t.value = 0
1133 return t
1134
1135 # String literal. Note that these use only single quotes, and
1136 # can span multiple lines.
1137 def t_STRLIT(self, t):
1138 r"(?m)'([^'])+'"
1139 # strip off quotes
1140 t.value = t.value[1:-1]
1141 t.lexer.lineno += t.value.count('\n')
1142 return t
1143
1144
1145 # "Code literal"... like a string literal, but delimiters are
1146 # '{{' and '}}' so they get formatted nicely under emacs c-mode
1147 def t_CODELIT(self, t):
1148 r"(?m)\{\{([^\}]|}(?!\}))+\}\}"
1149 # strip off {{ & }}
1150 t.value = t.value[2:-2]
1151 t.lexer.lineno += t.value.count('\n')
1152 return t
1153
1154 def t_CPPDIRECTIVE(self, t):
1155 r'^\#[^\#].*\n'
1156 t.lexer.lineno += t.value.count('\n')
1157 return t
1158
1159 def t_NEWFILE(self, t):
1160 r'^\#\#newfile\s+"[^"]*"'
1161 self.fileNameStack.push((t.value[11:-1], t.lexer.lineno))
1162 t.lexer.lineno = 0
1163
1164 def t_ENDFILE(self, t):
1165 r'^\#\#endfile'
1166 (old_filename, t.lexer.lineno) = self.fileNameStack.pop()
1167
1168 #
1169 # The functions t_NEWLINE, t_ignore, and t_error are
1170 # special for the lex module.
1171 #
1172
1173 # Newlines
1174 def t_NEWLINE(self, t):
1175 r'\n+'
1176 t.lexer.lineno += t.value.count('\n')
1177
1178 # Comments
1179 def t_comment(self, t):
1180 r'//.*'
1181
1182 # Completely ignored characters
1183 t_ignore = ' \t\x0c'
1184
1185 # Error handler
1186 def t_error(self, t):
1187 error(t, "illegal character '%s'" % t.value[0])
1188 t.skip(1)
1189
1190 #####################################################################
1191 #
1192 # Parser
1193 #
1194 # Every function whose name starts with 'p_' defines a grammar
1195 # rule. The rule is encoded in the function's doc string, while
1196 # the function body provides the action taken when the rule is
1197 # matched. The argument to each function is a list of the values
1198 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the
1199 # symbols on the RHS. For tokens, the value is copied from the
1200 # t.value attribute provided by the lexer. For non-terminals, the
1201 # value is assigned by the producing rule; i.e., the job of the
1202 # grammar rule function is to set the value for the non-terminal
1203 # on the LHS (by assigning to t[0]).
1204 #####################################################################
1205
1206 # The LHS of the first grammar rule is used as the start symbol
1207 # (in this case, 'specification'). Note that this rule enforces
1208 # that there will be exactly one namespace declaration, with 0 or
1209 # more global defs/decls before and after it. The defs & decls
1210 # before the namespace decl will be outside the namespace; those
1211 # after will be inside. The decoder function is always inside the
1212 # namespace.
1213 def p_specification(self, t):
1214 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
1215 global_code = t[1]
1216 isa_name = t[2]
1217 namespace = isa_name + "Inst"
1218 # wrap the decode block as a function definition
1219 t[4].wrap_decode_block('''
1220StaticInstPtr
1221%(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst)
1222{
1223 using namespace %(namespace)s;
1224''' % vars(), '}')
1225 # both the latter output blocks and the decode block are in
1226 # the namespace
1227 namespace_code = t[3] + t[4]
1228 # pass it all back to the caller of yacc.parse()
1229 t[0] = (isa_name, namespace, global_code, namespace_code)
1230
1231 # ISA name declaration looks like "namespace <foo>;"
1232 def p_name_decl(self, t):
1233 'name_decl : NAMESPACE ID SEMI'
1234 t[0] = t[2]
1235
1236 # 'opt_defs_and_outputs' is a possibly empty sequence of
1237 # def and/or output statements.
1238 def p_opt_defs_and_outputs_0(self, t):
1239 'opt_defs_and_outputs : empty'
1240 t[0] = GenCode(self)
1241
1242 def p_opt_defs_and_outputs_1(self, t):
1243 'opt_defs_and_outputs : defs_and_outputs'
1244 t[0] = t[1]
1245
1246 def p_defs_and_outputs_0(self, t):
1247 'defs_and_outputs : def_or_output'
1248 t[0] = t[1]
1249
1250 def p_defs_and_outputs_1(self, t):
1251 'defs_and_outputs : defs_and_outputs def_or_output'
1252 t[0] = t[1] + t[2]
1253
1254 # The list of possible definition/output statements.
1255 def p_def_or_output(self, t):
1256 '''def_or_output : def_format
1257 | def_bitfield
1258 | def_bitfield_struct
1259 | def_template
1260 | def_operand_types
1261 | def_operands
1262 | output_header
1263 | output_decoder
1264 | output_exec
1265 | global_let'''
1266 t[0] = t[1]
1267
1268 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1269 # directly to the appropriate output section.
1270
1271 # Massage output block by substituting in template definitions and
1272 # bit operators. We handle '%'s embedded in the string that don't
1273 # indicate template substitutions (or CPU-specific symbols, which
1274 # get handled in GenCode) by doubling them first so that the
1275 # format operation will reduce them back to single '%'s.
1276 def process_output(self, s):
1277 s = self.protectNonSubstPercents(s)
1278 # protects cpu-specific symbols too
1279 s = self.protectCpuSymbols(s)
1280 return substBitOps(s % self.templateMap)
1281
1282 def p_output_header(self, t):
1283 'output_header : OUTPUT HEADER CODELIT SEMI'
1284 t[0] = GenCode(self, header_output = self.process_output(t[3]))
1285
1286 def p_output_decoder(self, t):
1287 'output_decoder : OUTPUT DECODER CODELIT SEMI'
1288 t[0] = GenCode(self, decoder_output = self.process_output(t[3]))
1289
1290 def p_output_exec(self, t):
1291 'output_exec : OUTPUT EXEC CODELIT SEMI'
1292 t[0] = GenCode(self, exec_output = self.process_output(t[3]))
1293
1294 # global let blocks 'let {{...}}' (Python code blocks) are
1295 # executed directly when seen. Note that these execute in a
1296 # special variable context 'exportContext' to prevent the code
1297 # from polluting this script's namespace.
1298 def p_global_let(self, t):
1299 'global_let : LET CODELIT SEMI'
1300 self.updateExportContext()
1301 self.exportContext["header_output"] = ''
1302 self.exportContext["decoder_output"] = ''
1303 self.exportContext["exec_output"] = ''
1304 self.exportContext["decode_block"] = ''
1305 try:
1306 exec fixPythonIndentation(t[2]) in self.exportContext
1307 except Exception, exc:
1308 if debug:
1309 raise
1310 error(t, 'error: %s in global let block "%s".' % (exc, t[2]))
1311 t[0] = GenCode(self,
1312 header_output=self.exportContext["header_output"],
1313 decoder_output=self.exportContext["decoder_output"],
1314 exec_output=self.exportContext["exec_output"],
1315 decode_block=self.exportContext["decode_block"])
1316
1317 # Define the mapping from operand type extensions to C++ types and
1318 # bit widths (stored in operandTypeMap).
1319 def p_def_operand_types(self, t):
1320 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1321 try:
1322 self.operandTypeMap = eval('{' + t[3] + '}')
1323 except Exception, exc:
1324 if debug:
1325 raise
1326 error(t,
1327 'error: %s in def operand_types block "%s".' % (exc, t[3]))
1328 t[0] = GenCode(self) # contributes nothing to the output C++ file
1329
1330 # Define the mapping from operand names to operand classes and
1331 # other traits. Stored in operandNameMap.
1332 def p_def_operands(self, t):
1333 'def_operands : DEF OPERANDS CODELIT SEMI'
1334 if not hasattr(self, 'operandTypeMap'):
1335 error(t, 'error: operand types must be defined before operands')
1336 try:
1337 user_dict = eval('{' + t[3] + '}', self.exportContext)
1338 except Exception, exc:
1339 if debug:
1340 raise
1341 error(t, 'error: %s in def operands block "%s".' % (exc, t[3]))
1342 self.buildOperandNameMap(user_dict, t.lexer.lineno)
1343 t[0] = GenCode(self) # contributes nothing to the output C++ file
1344
1345 # A bitfield definition looks like:
1346 # 'def [signed] bitfield <ID> [<first>:<last>]'
1347 # This generates a preprocessor macro in the output file.
1348 def p_def_bitfield_0(self, t):
1349 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
1350 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8])
1351 if (t[2] == 'signed'):
1352 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr)
1353 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
1354 t[0] = GenCode(self, header_output=hash_define)
1355
1356 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
1357 def p_def_bitfield_1(self, t):
1358 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
1359 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6])
1360 if (t[2] == 'signed'):
1361 expr = 'sext<%d>(%s)' % (1, expr)
1362 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
1363 t[0] = GenCode(self, header_output=hash_define)
1364
1365 # alternate form for structure member: 'def bitfield <ID> <ID>'
1366 def p_def_bitfield_struct(self, t):
1367 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI'
1368 if (t[2] != ''):
1369 error(t, 'error: structure bitfields are always unsigned.')
1370 expr = 'machInst.%s' % t[5]
1371 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
1372 t[0] = GenCode(self, header_output=hash_define)
1373
1374 def p_id_with_dot_0(self, t):
1375 'id_with_dot : ID'
1376 t[0] = t[1]
1377
1378 def p_id_with_dot_1(self, t):
1379 'id_with_dot : ID DOT id_with_dot'
1380 t[0] = t[1] + t[2] + t[3]
1381
1382 def p_opt_signed_0(self, t):
1383 'opt_signed : SIGNED'
1384 t[0] = t[1]
1385
1386 def p_opt_signed_1(self, t):
1387 'opt_signed : empty'
1388 t[0] = ''
1389
1390 def p_def_template(self, t):
1391 'def_template : DEF TEMPLATE ID CODELIT SEMI'
1392 self.templateMap[t[3]] = Template(self, t[4])
1393 t[0] = GenCode(self)
1394
1395 # An instruction format definition looks like
1396 # "def format <fmt>(<params>) {{...}};"
1397 def p_def_format(self, t):
1398 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1399 (id, params, code) = (t[3], t[5], t[7])
1400 self.defFormat(id, params, code, t.lexer.lineno)
1401 t[0] = GenCode(self)
1402
1403 # The formal parameter list for an instruction format is a
1404 # possibly empty list of comma-separated parameters. Positional
1405 # (standard, non-keyword) parameters must come first, followed by
1406 # keyword parameters, followed by a '*foo' parameter that gets
1407 # excess positional arguments (as in Python). Each of these three
1408 # parameter categories is optional.
1409 #
1410 # Note that we do not support the '**foo' parameter for collecting
1411 # otherwise undefined keyword args. Otherwise the parameter list
1412 # is (I believe) identical to what is supported in Python.
1413 #
1414 # The param list generates a tuple, where the first element is a
1415 # list of the positional params and the second element is a dict
1416 # containing the keyword params.
1417 def p_param_list_0(self, t):
1418 'param_list : positional_param_list COMMA nonpositional_param_list'
1419 t[0] = t[1] + t[3]
1420
1421 def p_param_list_1(self, t):
1422 '''param_list : positional_param_list
1423 | nonpositional_param_list'''
1424 t[0] = t[1]
1425
1426 def p_positional_param_list_0(self, t):
1427 'positional_param_list : empty'
1428 t[0] = []
1429
1430 def p_positional_param_list_1(self, t):
1431 'positional_param_list : ID'
1432 t[0] = [t[1]]
1433
1434 def p_positional_param_list_2(self, t):
1435 'positional_param_list : positional_param_list COMMA ID'
1436 t[0] = t[1] + [t[3]]
1437
1438 def p_nonpositional_param_list_0(self, t):
1439 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
1440 t[0] = t[1] + t[3]
1441
1442 def p_nonpositional_param_list_1(self, t):
1443 '''nonpositional_param_list : keyword_param_list
1444 | excess_args_param'''
1445 t[0] = t[1]
1446
1447 def p_keyword_param_list_0(self, t):
1448 'keyword_param_list : keyword_param'
1449 t[0] = [t[1]]
1450
1451 def p_keyword_param_list_1(self, t):
1452 'keyword_param_list : keyword_param_list COMMA keyword_param'
1453 t[0] = t[1] + [t[3]]
1454
1455 def p_keyword_param(self, t):
1456 'keyword_param : ID EQUALS expr'
1457 t[0] = t[1] + ' = ' + t[3].__repr__()
1458
1459 def p_excess_args_param(self, t):
1460 'excess_args_param : ASTERISK ID'
1461 # Just concatenate them: '*ID'. Wrap in list to be consistent
1462 # with positional_param_list and keyword_param_list.
1463 t[0] = [t[1] + t[2]]
1464
1465 # End of format definition-related rules.
1466 ##############
1467
1468 #
1469 # A decode block looks like:
1470 # decode <field1> [, <field2>]* [default <inst>] { ... }
1471 #
1472 def p_decode_block(self, t):
1473 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
1474 default_defaults = self.defaultStack.pop()
1475 codeObj = t[5]
1476 # use the "default defaults" only if there was no explicit
1477 # default statement in decode_stmt_list
1478 if not codeObj.has_decode_default:
1479 codeObj += default_defaults
1480 codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n')
1481 t[0] = codeObj
1482
1483 # The opt_default statement serves only to push the "default
1484 # defaults" onto defaultStack. This value will be used by nested
1485 # decode blocks, and used and popped off when the current
1486 # decode_block is processed (in p_decode_block() above).
1487 def p_opt_default_0(self, t):
1488 'opt_default : empty'
1489 # no default specified: reuse the one currently at the top of
1490 # the stack
1491 self.defaultStack.push(self.defaultStack.top())
1492 # no meaningful value returned
1493 t[0] = None
1494
1495 def p_opt_default_1(self, t):
1496 'opt_default : DEFAULT inst'
1497 # push the new default
1498 codeObj = t[2]
1499 codeObj.wrap_decode_block('\ndefault:\n', 'break;\n')
1500 self.defaultStack.push(codeObj)
1501 # no meaningful value returned
1502 t[0] = None
1503
1504 def p_decode_stmt_list_0(self, t):
1505 'decode_stmt_list : decode_stmt'
1506 t[0] = t[1]
1507
1508 def p_decode_stmt_list_1(self, t):
1509 'decode_stmt_list : decode_stmt decode_stmt_list'
1510 if (t[1].has_decode_default and t[2].has_decode_default):
1511 error(t, 'Two default cases in decode block')
1512 t[0] = t[1] + t[2]
1513
1514 #
1515 # Decode statement rules
1516 #
1517 # There are four types of statements allowed in a decode block:
1518 # 1. Format blocks 'format <foo> { ... }'
1519 # 2. Nested decode blocks
1520 # 3. Instruction definitions.
1521 # 4. C preprocessor directives.
1522
1523
1524 # Preprocessor directives found in a decode statement list are
1525 # passed through to the output, replicated to all of the output
1526 # code streams. This works well for ifdefs, so we can ifdef out
1527 # both the declarations and the decode cases generated by an
1528 # instruction definition. Handling them as part of the grammar
1529 # makes it easy to keep them in the right place with respect to
1530 # the code generated by the other statements.
1531 def p_decode_stmt_cpp(self, t):
1532 'decode_stmt : CPPDIRECTIVE'
1533 t[0] = GenCode(self, t[1], t[1], t[1], t[1])
1534
1535 # A format block 'format <foo> { ... }' sets the default
1536 # instruction format used to handle instruction definitions inside
1537 # the block. This format can be overridden by using an explicit
1538 # format on the instruction definition or with a nested format
1539 # block.
1540 def p_decode_stmt_format(self, t):
1541 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
1542 # The format will be pushed on the stack when 'push_format_id'
1543 # is processed (see below). Once the parser has recognized
1544 # the full production (though the right brace), we're done
1545 # with the format, so now we can pop it.
1546 self.formatStack.pop()
1547 t[0] = t[4]
1548
1549 # This rule exists so we can set the current format (& push the
1550 # stack) when we recognize the format name part of the format
1551 # block.
1552 def p_push_format_id(self, t):
1553 'push_format_id : ID'
1554 try:
1555 self.formatStack.push(self.formatMap[t[1]])
1556 t[0] = ('', '// format %s' % t[1])
1557 except KeyError:
1558 error(t, 'instruction format "%s" not defined.' % t[1])
1559
1560 # Nested decode block: if the value of the current field matches
1561 # the specified constant, do a nested decode on some other field.
1562 def p_decode_stmt_decode(self, t):
1563 'decode_stmt : case_label COLON decode_block'
1564 label = t[1]
1565 codeObj = t[3]
1566 # just wrap the decoding code from the block as a case in the
1567 # outer switch statement.
1568 codeObj.wrap_decode_block('\n%s:\n' % label)
1569 codeObj.has_decode_default = (label == 'default')
1570 t[0] = codeObj
1571
1572 # Instruction definition (finally!).
1573 def p_decode_stmt_inst(self, t):
1574 'decode_stmt : case_label COLON inst SEMI'
1575 label = t[1]
1576 codeObj = t[3]
1577 codeObj.wrap_decode_block('\n%s:' % label, 'break;\n')
1578 codeObj.has_decode_default = (label == 'default')
1579 t[0] = codeObj
1580
1581 # The case label is either a list of one or more constants or
1582 # 'default'
1583 def p_case_label_0(self, t):
1584 'case_label : intlit_list'
1585 def make_case(intlit):
1586 if intlit >= 2**32:
1587 return 'case ULL(%#x)' % intlit
1588 else:
1589 return 'case %#x' % intlit
1590 t[0] = ': '.join(map(make_case, t[1]))
1591
1592 def p_case_label_1(self, t):
1593 'case_label : DEFAULT'
1594 t[0] = 'default'
1595
1596 #
1597 # The constant list for a decode case label must be non-empty, but
1598 # may have one or more comma-separated integer literals in it.
1599 #
1600 def p_intlit_list_0(self, t):
1601 'intlit_list : INTLIT'
1602 t[0] = [t[1]]
1603
1604 def p_intlit_list_1(self, t):
1605 'intlit_list : intlit_list COMMA INTLIT'
1606 t[0] = t[1]
1607 t[0].append(t[3])
1608
1609 # Define an instruction using the current instruction format
1610 # (specified by an enclosing format block).
1611 # "<mnemonic>(<args>)"
1612 def p_inst_0(self, t):
1613 'inst : ID LPAREN arg_list RPAREN'
1614 # Pass the ID and arg list to the current format class to deal with.
1615 currentFormat = self.formatStack.top()
1616 codeObj = currentFormat.defineInst(self, t[1], t[3], t.lexer.lineno)
1617 args = ','.join(map(str, t[3]))
1618 args = re.sub('(?m)^', '//', args)
1619 args = re.sub('^//', '', args)
1620 comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args)
1621 codeObj.prepend_all(comment)
1622 t[0] = codeObj
1623
1624 # Define an instruction using an explicitly specified format:
1625 # "<fmt>::<mnemonic>(<args>)"
1626 def p_inst_1(self, t):
1627 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1628 try:
1629 format = self.formatMap[t[1]]
1630 except KeyError:
1631 error(t, 'instruction format "%s" not defined.' % t[1])
1632
1633 codeObj = format.defineInst(self, t[3], t[5], t.lexer.lineno)
1634 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5])
1635 codeObj.prepend_all(comment)
1636 t[0] = codeObj
1637
1638 # The arg list generates a tuple, where the first element is a
1639 # list of the positional args and the second element is a dict
1640 # containing the keyword args.
1641 def p_arg_list_0(self, t):
1642 'arg_list : positional_arg_list COMMA keyword_arg_list'
1643 t[0] = ( t[1], t[3] )
1644
1645 def p_arg_list_1(self, t):
1646 'arg_list : positional_arg_list'
1647 t[0] = ( t[1], {} )
1648
1649 def p_arg_list_2(self, t):
1650 'arg_list : keyword_arg_list'
1651 t[0] = ( [], t[1] )
1652
1653 def p_positional_arg_list_0(self, t):
1654 'positional_arg_list : empty'
1655 t[0] = []
1656
1657 def p_positional_arg_list_1(self, t):
1658 'positional_arg_list : expr'
1659 t[0] = [t[1]]
1660
1661 def p_positional_arg_list_2(self, t):
1662 'positional_arg_list : positional_arg_list COMMA expr'
1663 t[0] = t[1] + [t[3]]
1664
1665 def p_keyword_arg_list_0(self, t):
1666 'keyword_arg_list : keyword_arg'
1667 t[0] = t[1]
1668
1669 def p_keyword_arg_list_1(self, t):
1670 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
1671 t[0] = t[1]
1672 t[0].update(t[3])
1673
1674 def p_keyword_arg(self, t):
1675 'keyword_arg : ID EQUALS expr'
1676 t[0] = { t[1] : t[3] }
1677
1678 #
1679 # Basic expressions. These constitute the argument values of
1680 # "function calls" (i.e. instruction definitions in the decode
1681 # block) and default values for formal parameters of format
1682 # functions.
1683 #
1684 # Right now, these are either strings, integers, or (recursively)
1685 # lists of exprs (using Python square-bracket list syntax). Note
1686 # that bare identifiers are trated as string constants here (since
1687 # there isn't really a variable namespace to refer to).
1688 #
1689 def p_expr_0(self, t):
1690 '''expr : ID
1691 | INTLIT
1692 | STRLIT
1693 | CODELIT'''
1694 t[0] = t[1]
1695
1696 def p_expr_1(self, t):
1697 '''expr : LBRACKET list_expr RBRACKET'''
1698 t[0] = t[2]
1699
1700 def p_list_expr_0(self, t):
1701 'list_expr : expr'
1702 t[0] = [t[1]]
1703
1704 def p_list_expr_1(self, t):
1705 'list_expr : list_expr COMMA expr'
1706 t[0] = t[1] + [t[3]]
1707
1708 def p_list_expr_2(self, t):
1709 'list_expr : empty'
1710 t[0] = []
1711
1712 #
1713 # Empty production... use in other rules for readability.
1714 #
1715 def p_empty(self, t):
1716 'empty :'
1717 pass
1718
1719 # Parse error handler. Note that the argument here is the
1720 # offending *token*, not a grammar symbol (hence the need to use
1721 # t.value)
1722 def p_error(self, t):
1723 if t:
1724 error(t, "syntax error at '%s'" % t.value)
1725 else:
1726 error("unknown syntax error")
1727
1728 # END OF GRAMMAR RULES
1729
1730 def updateExportContext(self):
1731
1732 # create a continuation that allows us to grab the current parser
1733 def wrapInstObjParams(*args):
1734 return InstObjParams(self, *args)
1735 self.exportContext['InstObjParams'] = wrapInstObjParams
1736 self.exportContext.update(self.templateMap)
1737
1738 def defFormat(self, id, params, code, lineno):
1739 '''Define a new format'''
1740
1741 # make sure we haven't already defined this one
1742 if id in self.formatMap:
1743 error(lineno, 'format %s redefined.' % id)
1744
1745 # create new object and store in global map
1746 self.formatMap[id] = Format(id, params, code)
1747
1748 def expandCpuSymbolsToDict(self, template):
1749 '''Expand template with CPU-specific references into a
1750 dictionary with an entry for each CPU model name. The entry
1751 key is the model name and the corresponding value is the
1752 template with the CPU-specific refs substituted for that
1753 model.'''
1754
1755 # Protect '%'s that don't go with CPU-specific terms
1756 t = re.sub(r'%(?!\(CPU_)', '%%', template)
1757 result = {}
1758 for cpu in self.cpuModels:
1759 result[cpu.name] = t % cpu.strings
1760 return result
1761
1762 def expandCpuSymbolsToString(self, template):
1763 '''*If* the template has CPU-specific references, return a
1764 single string containing a copy of the template for each CPU
1765 model with the corresponding values substituted in. If the
1766 template has no CPU-specific references, it is returned
1767 unmodified.'''
1768
1769 if template.find('%(CPU_') != -1:
1770 return reduce(lambda x,y: x+y,
1771 self.expandCpuSymbolsToDict(template).values())
1772 else:
1773 return template
1774
1775 def protectCpuSymbols(self, template):
1776 '''Protect CPU-specific references by doubling the
1777 corresponding '%'s (in preparation for substituting a different
1778 set of references into the template).'''
1779
1780 return re.sub(r'%(?=\(CPU_)', '%%', template)
1781
1782 def protectNonSubstPercents(self, s):
1783 '''Protect any non-dict-substitution '%'s in a format string
1784 (i.e. those not followed by '(')'''
1785
1786 return re.sub(r'%(?!\()', '%%', s)
1787
1788 def buildOperandNameMap(self, user_dict, lineno):
1789 operand_name = {}
1790 for op_name, val in user_dict.iteritems():
1791 base_cls_name, dflt_ext, reg_spec, flags, sort_pri = val[:5]
1792 if len(val) > 5:
1793 read_code = val[5]
1794 else:
1795 read_code = None
1796 if len(val) > 6:
1797 write_code = val[6]
1798 else:
1799 write_code = None
1800 if len(val) > 7:
1801 error(lineno,
1802 'error: too many attributes for operand "%s"' %
1803 base_cls_name)
1804
1805 # Canonical flag structure is a triple of lists, where each list
1806 # indicates the set of flags implied by this operand always, when
1807 # used as a source, and when used as a dest, respectively.
1808 # For simplicity this can be initialized using a variety of fairly
1809 # obvious shortcuts; we convert these to canonical form here.
1810 if not flags:
1811 # no flags specified (e.g., 'None')
1812 flags = ( [], [], [] )
1813 elif isinstance(flags, str):
1814 # a single flag: assumed to be unconditional
1815 flags = ( [ flags ], [], [] )
1816 elif isinstance(flags, list):
1817 # a list of flags: also assumed to be unconditional
1818 flags = ( flags, [], [] )
1819 elif isinstance(flags, tuple):
1820 # it's a tuple: it should be a triple,
1821 # but each item could be a single string or a list
1822 (uncond_flags, src_flags, dest_flags) = flags
1823 flags = (makeList(uncond_flags),
1824 makeList(src_flags), makeList(dest_flags))
1825 # Accumulate attributes of new operand class in tmp_dict
1826 tmp_dict = {}
1827 attrList = ['reg_spec', 'flags', 'sort_pri',
1828 'read_code', 'write_code']
1829 if dflt_ext:
1830 dflt_ctype = self.operandTypeMap[dflt_ext]
1831 attrList.extend(['dflt_ctype', 'dflt_ext'])
1832 for attr in attrList:
1833 tmp_dict[attr] = eval(attr)
1834 tmp_dict['base_name'] = op_name
1835 # New class name will be e.g. "IntReg_Ra"
1836 cls_name = base_cls_name + '_' + op_name
1837 # Evaluate string arg to get class object. Note that the
1838 # actual base class for "IntReg" is "IntRegOperand", i.e. we
1839 # have to append "Operand".
1840 try:
1841 base_cls = eval(base_cls_name + 'Operand')
1842 except NameError:
1843 error(lineno,
1844 'error: unknown operand base class "%s"' % base_cls_name)
1845 # The following statement creates a new class called
1846 # <cls_name> as a subclass of <base_cls> with the attributes
1847 # in tmp_dict, just as if we evaluated a class declaration.
1848 operand_name[op_name] = type(cls_name, (base_cls,), tmp_dict)
1849
1850 self.operandNameMap = operand_name
1851
1852 # Define operand variables.
1853 operands = user_dict.keys()
1854 extensions = self.operandTypeMap.keys()
1855
1856 operandsREString = r'''
1857 (?<!\w) # neg. lookbehind assertion: prevent partial matches
1858 ((%s)(?:_(%s))?) # match: operand with optional '_' then suffix
1859 (?!\w) # neg. lookahead assertion: prevent partial matches
1860 ''' % (string.join(operands, '|'), string.join(extensions, '|'))
1861
1862 self.operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
1863
1864 # Same as operandsREString, but extension is mandatory, and only two
1865 # groups are returned (base and ext, not full name as above).
1866 # Used for subtituting '_' for '.' to make C++ identifiers.
1867 operandsWithExtREString = r'(?<!\w)(%s)_(%s)(?!\w)' \
1868 % (string.join(operands, '|'), string.join(extensions, '|'))
1869
1870 self.operandsWithExtRE = \
1871 re.compile(operandsWithExtREString, re.MULTILINE)
1872
1873 def substMungedOpNames(self, code):
1874 '''Munge operand names in code string to make legal C++
1875 variable names. This means getting rid of the type extension
1876 if any. Will match base_name attribute of Operand object.)'''
1877 return self.operandsWithExtRE.sub(r'\1', code)
1878
1879 def mungeSnippet(self, s):
1880 '''Fix up code snippets for final substitution in templates.'''
1881 if isinstance(s, str):
1882 return self.substMungedOpNames(substBitOps(s))
1883 else:
1884 return s
1885
1886 def update_if_needed(self, file, contents):
1887 '''Update the output file only if the new contents are
1888 different from the current contents. Minimizes the files that
1889 need to be rebuilt after minor changes.'''
1890
1891 file = os.path.join(self.output_dir, file)
1892 update = False
1893 if os.access(file, os.R_OK):
1894 f = open(file, 'r')
1895 old_contents = f.read()
1896 f.close()
1897 if contents != old_contents:
1898 os.remove(file) # in case it's write-protected
1899 update = True
1900 else:
1901 print 'File', file, 'is unchanged'
1902 else:
1903 update = True
1904 if update:
1905 f = open(file, 'w')
1906 f.write(contents)
1907 f.close()
1908
1909 # This regular expression matches '##include' directives
1910 includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[^"]*)".*$',
1911 re.MULTILINE)
1912
1913 def replace_include(self, matchobj, dirname):
1914 """Function to replace a matched '##include' directive with the
1915 contents of the specified file (with nested ##includes
1916 replaced recursively). 'matchobj' is an re match object
1917 (from a match of includeRE) and 'dirname' is the directory
1918 relative to which the file path should be resolved."""
1919
1920 fname = matchobj.group('filename')
1921 full_fname = os.path.normpath(os.path.join(dirname, fname))
1922 contents = '##newfile "%s"\n%s\n##endfile\n' % \
1923 (full_fname, self.read_and_flatten(full_fname))
1924 return contents
1925
1926 def read_and_flatten(self, filename):
1927 """Read a file and recursively flatten nested '##include' files."""
1928
1929 current_dir = os.path.dirname(filename)
1930 try:
1931 contents = open(filename).read()
1932 except IOError:
1933 error('Error including file "%s"' % filename)
1934
1935 self.fileNameStack.push((filename, 0))
1936
1937 # Find any includes and include them
1938 def replace(matchobj):
1939 return self.replace_include(matchobj, current_dir)
1940 contents = self.includeRE.sub(replace, contents)
1941
1942 self.fileNameStack.pop()
1943 return contents
1944
1945 def _parse_isa_desc(self, isa_desc_file):
1946 '''Read in and parse the ISA description.'''
1947
1948 # Read file and (recursively) all included files into a string.
1949 # PLY requires that the input be in a single string so we have to
1950 # do this up front.
1951 isa_desc = self.read_and_flatten(isa_desc_file)
1952
1953 # Initialize filename stack with outer file.
1954 self.fileNameStack.push((isa_desc_file, 0))
1955
1956 # Parse it.
1957 (isa_name, namespace, global_code, namespace_code) = \
1958 self.parse_string(isa_desc)
1959
1960 # grab the last three path components of isa_desc_file to put in
1961 # the output
1962 filename = '/'.join(isa_desc_file.split('/')[-3:])
1963
1964 # generate decoder.hh
1965 includes = '#include "base/bitfield.hh" // for bitfield support'
1966 global_output = global_code.header_output
1967 namespace_output = namespace_code.header_output
1968 decode_function = ''
1969 self.update_if_needed('decoder.hh', file_template % vars())
1970
1971 # generate decoder.cc
1972 includes = '#include "decoder.hh"'
1973 global_output = global_code.decoder_output
1974 namespace_output = namespace_code.decoder_output
1975 # namespace_output += namespace_code.decode_block
1976 decode_function = namespace_code.decode_block
1977 self.update_if_needed('decoder.cc', file_template % vars())
1978
1979 # generate per-cpu exec files
1980 for cpu in self.cpuModels:
1981 includes = '#include "decoder.hh"\n'
1982 includes += cpu.includes
1983 global_output = global_code.exec_output[cpu.name]
1984 namespace_output = namespace_code.exec_output[cpu.name]
1985 decode_function = ''
1986 self.update_if_needed(cpu.filename, file_template % vars())
1987
1988 # The variable names here are hacky, but this will creat local
1989 # variables which will be referenced in vars() which have the
1990 # value of the globals.
1991 MaxInstSrcRegs = self.maxInstSrcRegs
1992 MaxInstDestRegs = self.maxInstDestRegs
1046
1047 #####################################################################
1048 #
1049 # Lexer
1050 #
1051 # The PLY lexer module takes two things as input:
1052 # - A list of token names (the string list 'tokens')
1053 # - A regular expression describing a match for each token. The
1054 # regexp for token FOO can be provided in two ways:
1055 # - as a string variable named t_FOO
1056 # - as the doc string for a function named t_FOO. In this case,
1057 # the function is also executed, allowing an action to be
1058 # associated with each token match.
1059 #
1060 #####################################################################
1061
1062 # Reserved words. These are listed separately as they are matched
1063 # using the same regexp as generic IDs, but distinguished in the
1064 # t_ID() function. The PLY documentation suggests this approach.
1065 reserved = (
1066 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
1067 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
1068 'OUTPUT', 'SIGNED', 'TEMPLATE'
1069 )
1070
1071 # List of tokens. The lex module requires this.
1072 tokens = reserved + (
1073 # identifier
1074 'ID',
1075
1076 # integer literal
1077 'INTLIT',
1078
1079 # string literal
1080 'STRLIT',
1081
1082 # code literal
1083 'CODELIT',
1084
1085 # ( ) [ ] { } < > , ; . : :: *
1086 'LPAREN', 'RPAREN',
1087 'LBRACKET', 'RBRACKET',
1088 'LBRACE', 'RBRACE',
1089 'LESS', 'GREATER', 'EQUALS',
1090 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON',
1091 'ASTERISK',
1092
1093 # C preprocessor directives
1094 'CPPDIRECTIVE'
1095
1096 # The following are matched but never returned. commented out to
1097 # suppress PLY warning
1098 # newfile directive
1099 # 'NEWFILE',
1100
1101 # endfile directive
1102 # 'ENDFILE'
1103 )
1104
1105 # Regular expressions for token matching
1106 t_LPAREN = r'\('
1107 t_RPAREN = r'\)'
1108 t_LBRACKET = r'\['
1109 t_RBRACKET = r'\]'
1110 t_LBRACE = r'\{'
1111 t_RBRACE = r'\}'
1112 t_LESS = r'\<'
1113 t_GREATER = r'\>'
1114 t_EQUALS = r'='
1115 t_COMMA = r','
1116 t_SEMI = r';'
1117 t_DOT = r'\.'
1118 t_COLON = r':'
1119 t_DBLCOLON = r'::'
1120 t_ASTERISK = r'\*'
1121
1122 # Identifiers and reserved words
1123 reserved_map = { }
1124 for r in reserved:
1125 reserved_map[r.lower()] = r
1126
1127 def t_ID(self, t):
1128 r'[A-Za-z_]\w*'
1129 t.type = self.reserved_map.get(t.value, 'ID')
1130 return t
1131
1132 # Integer literal
1133 def t_INTLIT(self, t):
1134 r'-?(0x[\da-fA-F]+)|\d+'
1135 try:
1136 t.value = int(t.value,0)
1137 except ValueError:
1138 error(t, 'Integer value "%s" too large' % t.value)
1139 t.value = 0
1140 return t
1141
1142 # String literal. Note that these use only single quotes, and
1143 # can span multiple lines.
1144 def t_STRLIT(self, t):
1145 r"(?m)'([^'])+'"
1146 # strip off quotes
1147 t.value = t.value[1:-1]
1148 t.lexer.lineno += t.value.count('\n')
1149 return t
1150
1151
1152 # "Code literal"... like a string literal, but delimiters are
1153 # '{{' and '}}' so they get formatted nicely under emacs c-mode
1154 def t_CODELIT(self, t):
1155 r"(?m)\{\{([^\}]|}(?!\}))+\}\}"
1156 # strip off {{ & }}
1157 t.value = t.value[2:-2]
1158 t.lexer.lineno += t.value.count('\n')
1159 return t
1160
1161 def t_CPPDIRECTIVE(self, t):
1162 r'^\#[^\#].*\n'
1163 t.lexer.lineno += t.value.count('\n')
1164 return t
1165
1166 def t_NEWFILE(self, t):
1167 r'^\#\#newfile\s+"[^"]*"'
1168 self.fileNameStack.push((t.value[11:-1], t.lexer.lineno))
1169 t.lexer.lineno = 0
1170
1171 def t_ENDFILE(self, t):
1172 r'^\#\#endfile'
1173 (old_filename, t.lexer.lineno) = self.fileNameStack.pop()
1174
1175 #
1176 # The functions t_NEWLINE, t_ignore, and t_error are
1177 # special for the lex module.
1178 #
1179
1180 # Newlines
1181 def t_NEWLINE(self, t):
1182 r'\n+'
1183 t.lexer.lineno += t.value.count('\n')
1184
1185 # Comments
1186 def t_comment(self, t):
1187 r'//.*'
1188
1189 # Completely ignored characters
1190 t_ignore = ' \t\x0c'
1191
1192 # Error handler
1193 def t_error(self, t):
1194 error(t, "illegal character '%s'" % t.value[0])
1195 t.skip(1)
1196
1197 #####################################################################
1198 #
1199 # Parser
1200 #
1201 # Every function whose name starts with 'p_' defines a grammar
1202 # rule. The rule is encoded in the function's doc string, while
1203 # the function body provides the action taken when the rule is
1204 # matched. The argument to each function is a list of the values
1205 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the
1206 # symbols on the RHS. For tokens, the value is copied from the
1207 # t.value attribute provided by the lexer. For non-terminals, the
1208 # value is assigned by the producing rule; i.e., the job of the
1209 # grammar rule function is to set the value for the non-terminal
1210 # on the LHS (by assigning to t[0]).
1211 #####################################################################
1212
1213 # The LHS of the first grammar rule is used as the start symbol
1214 # (in this case, 'specification'). Note that this rule enforces
1215 # that there will be exactly one namespace declaration, with 0 or
1216 # more global defs/decls before and after it. The defs & decls
1217 # before the namespace decl will be outside the namespace; those
1218 # after will be inside. The decoder function is always inside the
1219 # namespace.
1220 def p_specification(self, t):
1221 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
1222 global_code = t[1]
1223 isa_name = t[2]
1224 namespace = isa_name + "Inst"
1225 # wrap the decode block as a function definition
1226 t[4].wrap_decode_block('''
1227StaticInstPtr
1228%(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst)
1229{
1230 using namespace %(namespace)s;
1231''' % vars(), '}')
1232 # both the latter output blocks and the decode block are in
1233 # the namespace
1234 namespace_code = t[3] + t[4]
1235 # pass it all back to the caller of yacc.parse()
1236 t[0] = (isa_name, namespace, global_code, namespace_code)
1237
1238 # ISA name declaration looks like "namespace <foo>;"
1239 def p_name_decl(self, t):
1240 'name_decl : NAMESPACE ID SEMI'
1241 t[0] = t[2]
1242
1243 # 'opt_defs_and_outputs' is a possibly empty sequence of
1244 # def and/or output statements.
1245 def p_opt_defs_and_outputs_0(self, t):
1246 'opt_defs_and_outputs : empty'
1247 t[0] = GenCode(self)
1248
1249 def p_opt_defs_and_outputs_1(self, t):
1250 'opt_defs_and_outputs : defs_and_outputs'
1251 t[0] = t[1]
1252
1253 def p_defs_and_outputs_0(self, t):
1254 'defs_and_outputs : def_or_output'
1255 t[0] = t[1]
1256
1257 def p_defs_and_outputs_1(self, t):
1258 'defs_and_outputs : defs_and_outputs def_or_output'
1259 t[0] = t[1] + t[2]
1260
1261 # The list of possible definition/output statements.
1262 def p_def_or_output(self, t):
1263 '''def_or_output : def_format
1264 | def_bitfield
1265 | def_bitfield_struct
1266 | def_template
1267 | def_operand_types
1268 | def_operands
1269 | output_header
1270 | output_decoder
1271 | output_exec
1272 | global_let'''
1273 t[0] = t[1]
1274
1275 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
1276 # directly to the appropriate output section.
1277
1278 # Massage output block by substituting in template definitions and
1279 # bit operators. We handle '%'s embedded in the string that don't
1280 # indicate template substitutions (or CPU-specific symbols, which
1281 # get handled in GenCode) by doubling them first so that the
1282 # format operation will reduce them back to single '%'s.
1283 def process_output(self, s):
1284 s = self.protectNonSubstPercents(s)
1285 # protects cpu-specific symbols too
1286 s = self.protectCpuSymbols(s)
1287 return substBitOps(s % self.templateMap)
1288
1289 def p_output_header(self, t):
1290 'output_header : OUTPUT HEADER CODELIT SEMI'
1291 t[0] = GenCode(self, header_output = self.process_output(t[3]))
1292
1293 def p_output_decoder(self, t):
1294 'output_decoder : OUTPUT DECODER CODELIT SEMI'
1295 t[0] = GenCode(self, decoder_output = self.process_output(t[3]))
1296
1297 def p_output_exec(self, t):
1298 'output_exec : OUTPUT EXEC CODELIT SEMI'
1299 t[0] = GenCode(self, exec_output = self.process_output(t[3]))
1300
1301 # global let blocks 'let {{...}}' (Python code blocks) are
1302 # executed directly when seen. Note that these execute in a
1303 # special variable context 'exportContext' to prevent the code
1304 # from polluting this script's namespace.
1305 def p_global_let(self, t):
1306 'global_let : LET CODELIT SEMI'
1307 self.updateExportContext()
1308 self.exportContext["header_output"] = ''
1309 self.exportContext["decoder_output"] = ''
1310 self.exportContext["exec_output"] = ''
1311 self.exportContext["decode_block"] = ''
1312 try:
1313 exec fixPythonIndentation(t[2]) in self.exportContext
1314 except Exception, exc:
1315 if debug:
1316 raise
1317 error(t, 'error: %s in global let block "%s".' % (exc, t[2]))
1318 t[0] = GenCode(self,
1319 header_output=self.exportContext["header_output"],
1320 decoder_output=self.exportContext["decoder_output"],
1321 exec_output=self.exportContext["exec_output"],
1322 decode_block=self.exportContext["decode_block"])
1323
1324 # Define the mapping from operand type extensions to C++ types and
1325 # bit widths (stored in operandTypeMap).
1326 def p_def_operand_types(self, t):
1327 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
1328 try:
1329 self.operandTypeMap = eval('{' + t[3] + '}')
1330 except Exception, exc:
1331 if debug:
1332 raise
1333 error(t,
1334 'error: %s in def operand_types block "%s".' % (exc, t[3]))
1335 t[0] = GenCode(self) # contributes nothing to the output C++ file
1336
1337 # Define the mapping from operand names to operand classes and
1338 # other traits. Stored in operandNameMap.
1339 def p_def_operands(self, t):
1340 'def_operands : DEF OPERANDS CODELIT SEMI'
1341 if not hasattr(self, 'operandTypeMap'):
1342 error(t, 'error: operand types must be defined before operands')
1343 try:
1344 user_dict = eval('{' + t[3] + '}', self.exportContext)
1345 except Exception, exc:
1346 if debug:
1347 raise
1348 error(t, 'error: %s in def operands block "%s".' % (exc, t[3]))
1349 self.buildOperandNameMap(user_dict, t.lexer.lineno)
1350 t[0] = GenCode(self) # contributes nothing to the output C++ file
1351
1352 # A bitfield definition looks like:
1353 # 'def [signed] bitfield <ID> [<first>:<last>]'
1354 # This generates a preprocessor macro in the output file.
1355 def p_def_bitfield_0(self, t):
1356 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
1357 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8])
1358 if (t[2] == 'signed'):
1359 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr)
1360 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
1361 t[0] = GenCode(self, header_output=hash_define)
1362
1363 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
1364 def p_def_bitfield_1(self, t):
1365 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
1366 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6])
1367 if (t[2] == 'signed'):
1368 expr = 'sext<%d>(%s)' % (1, expr)
1369 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
1370 t[0] = GenCode(self, header_output=hash_define)
1371
1372 # alternate form for structure member: 'def bitfield <ID> <ID>'
1373 def p_def_bitfield_struct(self, t):
1374 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI'
1375 if (t[2] != ''):
1376 error(t, 'error: structure bitfields are always unsigned.')
1377 expr = 'machInst.%s' % t[5]
1378 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
1379 t[0] = GenCode(self, header_output=hash_define)
1380
1381 def p_id_with_dot_0(self, t):
1382 'id_with_dot : ID'
1383 t[0] = t[1]
1384
1385 def p_id_with_dot_1(self, t):
1386 'id_with_dot : ID DOT id_with_dot'
1387 t[0] = t[1] + t[2] + t[3]
1388
1389 def p_opt_signed_0(self, t):
1390 'opt_signed : SIGNED'
1391 t[0] = t[1]
1392
1393 def p_opt_signed_1(self, t):
1394 'opt_signed : empty'
1395 t[0] = ''
1396
1397 def p_def_template(self, t):
1398 'def_template : DEF TEMPLATE ID CODELIT SEMI'
1399 self.templateMap[t[3]] = Template(self, t[4])
1400 t[0] = GenCode(self)
1401
1402 # An instruction format definition looks like
1403 # "def format <fmt>(<params>) {{...}};"
1404 def p_def_format(self, t):
1405 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
1406 (id, params, code) = (t[3], t[5], t[7])
1407 self.defFormat(id, params, code, t.lexer.lineno)
1408 t[0] = GenCode(self)
1409
1410 # The formal parameter list for an instruction format is a
1411 # possibly empty list of comma-separated parameters. Positional
1412 # (standard, non-keyword) parameters must come first, followed by
1413 # keyword parameters, followed by a '*foo' parameter that gets
1414 # excess positional arguments (as in Python). Each of these three
1415 # parameter categories is optional.
1416 #
1417 # Note that we do not support the '**foo' parameter for collecting
1418 # otherwise undefined keyword args. Otherwise the parameter list
1419 # is (I believe) identical to what is supported in Python.
1420 #
1421 # The param list generates a tuple, where the first element is a
1422 # list of the positional params and the second element is a dict
1423 # containing the keyword params.
1424 def p_param_list_0(self, t):
1425 'param_list : positional_param_list COMMA nonpositional_param_list'
1426 t[0] = t[1] + t[3]
1427
1428 def p_param_list_1(self, t):
1429 '''param_list : positional_param_list
1430 | nonpositional_param_list'''
1431 t[0] = t[1]
1432
1433 def p_positional_param_list_0(self, t):
1434 'positional_param_list : empty'
1435 t[0] = []
1436
1437 def p_positional_param_list_1(self, t):
1438 'positional_param_list : ID'
1439 t[0] = [t[1]]
1440
1441 def p_positional_param_list_2(self, t):
1442 'positional_param_list : positional_param_list COMMA ID'
1443 t[0] = t[1] + [t[3]]
1444
1445 def p_nonpositional_param_list_0(self, t):
1446 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
1447 t[0] = t[1] + t[3]
1448
1449 def p_nonpositional_param_list_1(self, t):
1450 '''nonpositional_param_list : keyword_param_list
1451 | excess_args_param'''
1452 t[0] = t[1]
1453
1454 def p_keyword_param_list_0(self, t):
1455 'keyword_param_list : keyword_param'
1456 t[0] = [t[1]]
1457
1458 def p_keyword_param_list_1(self, t):
1459 'keyword_param_list : keyword_param_list COMMA keyword_param'
1460 t[0] = t[1] + [t[3]]
1461
1462 def p_keyword_param(self, t):
1463 'keyword_param : ID EQUALS expr'
1464 t[0] = t[1] + ' = ' + t[3].__repr__()
1465
1466 def p_excess_args_param(self, t):
1467 'excess_args_param : ASTERISK ID'
1468 # Just concatenate them: '*ID'. Wrap in list to be consistent
1469 # with positional_param_list and keyword_param_list.
1470 t[0] = [t[1] + t[2]]
1471
1472 # End of format definition-related rules.
1473 ##############
1474
1475 #
1476 # A decode block looks like:
1477 # decode <field1> [, <field2>]* [default <inst>] { ... }
1478 #
1479 def p_decode_block(self, t):
1480 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
1481 default_defaults = self.defaultStack.pop()
1482 codeObj = t[5]
1483 # use the "default defaults" only if there was no explicit
1484 # default statement in decode_stmt_list
1485 if not codeObj.has_decode_default:
1486 codeObj += default_defaults
1487 codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n')
1488 t[0] = codeObj
1489
1490 # The opt_default statement serves only to push the "default
1491 # defaults" onto defaultStack. This value will be used by nested
1492 # decode blocks, and used and popped off when the current
1493 # decode_block is processed (in p_decode_block() above).
1494 def p_opt_default_0(self, t):
1495 'opt_default : empty'
1496 # no default specified: reuse the one currently at the top of
1497 # the stack
1498 self.defaultStack.push(self.defaultStack.top())
1499 # no meaningful value returned
1500 t[0] = None
1501
1502 def p_opt_default_1(self, t):
1503 'opt_default : DEFAULT inst'
1504 # push the new default
1505 codeObj = t[2]
1506 codeObj.wrap_decode_block('\ndefault:\n', 'break;\n')
1507 self.defaultStack.push(codeObj)
1508 # no meaningful value returned
1509 t[0] = None
1510
1511 def p_decode_stmt_list_0(self, t):
1512 'decode_stmt_list : decode_stmt'
1513 t[0] = t[1]
1514
1515 def p_decode_stmt_list_1(self, t):
1516 'decode_stmt_list : decode_stmt decode_stmt_list'
1517 if (t[1].has_decode_default and t[2].has_decode_default):
1518 error(t, 'Two default cases in decode block')
1519 t[0] = t[1] + t[2]
1520
1521 #
1522 # Decode statement rules
1523 #
1524 # There are four types of statements allowed in a decode block:
1525 # 1. Format blocks 'format <foo> { ... }'
1526 # 2. Nested decode blocks
1527 # 3. Instruction definitions.
1528 # 4. C preprocessor directives.
1529
1530
1531 # Preprocessor directives found in a decode statement list are
1532 # passed through to the output, replicated to all of the output
1533 # code streams. This works well for ifdefs, so we can ifdef out
1534 # both the declarations and the decode cases generated by an
1535 # instruction definition. Handling them as part of the grammar
1536 # makes it easy to keep them in the right place with respect to
1537 # the code generated by the other statements.
1538 def p_decode_stmt_cpp(self, t):
1539 'decode_stmt : CPPDIRECTIVE'
1540 t[0] = GenCode(self, t[1], t[1], t[1], t[1])
1541
1542 # A format block 'format <foo> { ... }' sets the default
1543 # instruction format used to handle instruction definitions inside
1544 # the block. This format can be overridden by using an explicit
1545 # format on the instruction definition or with a nested format
1546 # block.
1547 def p_decode_stmt_format(self, t):
1548 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
1549 # The format will be pushed on the stack when 'push_format_id'
1550 # is processed (see below). Once the parser has recognized
1551 # the full production (though the right brace), we're done
1552 # with the format, so now we can pop it.
1553 self.formatStack.pop()
1554 t[0] = t[4]
1555
1556 # This rule exists so we can set the current format (& push the
1557 # stack) when we recognize the format name part of the format
1558 # block.
1559 def p_push_format_id(self, t):
1560 'push_format_id : ID'
1561 try:
1562 self.formatStack.push(self.formatMap[t[1]])
1563 t[0] = ('', '// format %s' % t[1])
1564 except KeyError:
1565 error(t, 'instruction format "%s" not defined.' % t[1])
1566
1567 # Nested decode block: if the value of the current field matches
1568 # the specified constant, do a nested decode on some other field.
1569 def p_decode_stmt_decode(self, t):
1570 'decode_stmt : case_label COLON decode_block'
1571 label = t[1]
1572 codeObj = t[3]
1573 # just wrap the decoding code from the block as a case in the
1574 # outer switch statement.
1575 codeObj.wrap_decode_block('\n%s:\n' % label)
1576 codeObj.has_decode_default = (label == 'default')
1577 t[0] = codeObj
1578
1579 # Instruction definition (finally!).
1580 def p_decode_stmt_inst(self, t):
1581 'decode_stmt : case_label COLON inst SEMI'
1582 label = t[1]
1583 codeObj = t[3]
1584 codeObj.wrap_decode_block('\n%s:' % label, 'break;\n')
1585 codeObj.has_decode_default = (label == 'default')
1586 t[0] = codeObj
1587
1588 # The case label is either a list of one or more constants or
1589 # 'default'
1590 def p_case_label_0(self, t):
1591 'case_label : intlit_list'
1592 def make_case(intlit):
1593 if intlit >= 2**32:
1594 return 'case ULL(%#x)' % intlit
1595 else:
1596 return 'case %#x' % intlit
1597 t[0] = ': '.join(map(make_case, t[1]))
1598
1599 def p_case_label_1(self, t):
1600 'case_label : DEFAULT'
1601 t[0] = 'default'
1602
1603 #
1604 # The constant list for a decode case label must be non-empty, but
1605 # may have one or more comma-separated integer literals in it.
1606 #
1607 def p_intlit_list_0(self, t):
1608 'intlit_list : INTLIT'
1609 t[0] = [t[1]]
1610
1611 def p_intlit_list_1(self, t):
1612 'intlit_list : intlit_list COMMA INTLIT'
1613 t[0] = t[1]
1614 t[0].append(t[3])
1615
1616 # Define an instruction using the current instruction format
1617 # (specified by an enclosing format block).
1618 # "<mnemonic>(<args>)"
1619 def p_inst_0(self, t):
1620 'inst : ID LPAREN arg_list RPAREN'
1621 # Pass the ID and arg list to the current format class to deal with.
1622 currentFormat = self.formatStack.top()
1623 codeObj = currentFormat.defineInst(self, t[1], t[3], t.lexer.lineno)
1624 args = ','.join(map(str, t[3]))
1625 args = re.sub('(?m)^', '//', args)
1626 args = re.sub('^//', '', args)
1627 comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args)
1628 codeObj.prepend_all(comment)
1629 t[0] = codeObj
1630
1631 # Define an instruction using an explicitly specified format:
1632 # "<fmt>::<mnemonic>(<args>)"
1633 def p_inst_1(self, t):
1634 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
1635 try:
1636 format = self.formatMap[t[1]]
1637 except KeyError:
1638 error(t, 'instruction format "%s" not defined.' % t[1])
1639
1640 codeObj = format.defineInst(self, t[3], t[5], t.lexer.lineno)
1641 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5])
1642 codeObj.prepend_all(comment)
1643 t[0] = codeObj
1644
1645 # The arg list generates a tuple, where the first element is a
1646 # list of the positional args and the second element is a dict
1647 # containing the keyword args.
1648 def p_arg_list_0(self, t):
1649 'arg_list : positional_arg_list COMMA keyword_arg_list'
1650 t[0] = ( t[1], t[3] )
1651
1652 def p_arg_list_1(self, t):
1653 'arg_list : positional_arg_list'
1654 t[0] = ( t[1], {} )
1655
1656 def p_arg_list_2(self, t):
1657 'arg_list : keyword_arg_list'
1658 t[0] = ( [], t[1] )
1659
1660 def p_positional_arg_list_0(self, t):
1661 'positional_arg_list : empty'
1662 t[0] = []
1663
1664 def p_positional_arg_list_1(self, t):
1665 'positional_arg_list : expr'
1666 t[0] = [t[1]]
1667
1668 def p_positional_arg_list_2(self, t):
1669 'positional_arg_list : positional_arg_list COMMA expr'
1670 t[0] = t[1] + [t[3]]
1671
1672 def p_keyword_arg_list_0(self, t):
1673 'keyword_arg_list : keyword_arg'
1674 t[0] = t[1]
1675
1676 def p_keyword_arg_list_1(self, t):
1677 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
1678 t[0] = t[1]
1679 t[0].update(t[3])
1680
1681 def p_keyword_arg(self, t):
1682 'keyword_arg : ID EQUALS expr'
1683 t[0] = { t[1] : t[3] }
1684
1685 #
1686 # Basic expressions. These constitute the argument values of
1687 # "function calls" (i.e. instruction definitions in the decode
1688 # block) and default values for formal parameters of format
1689 # functions.
1690 #
1691 # Right now, these are either strings, integers, or (recursively)
1692 # lists of exprs (using Python square-bracket list syntax). Note
1693 # that bare identifiers are trated as string constants here (since
1694 # there isn't really a variable namespace to refer to).
1695 #
1696 def p_expr_0(self, t):
1697 '''expr : ID
1698 | INTLIT
1699 | STRLIT
1700 | CODELIT'''
1701 t[0] = t[1]
1702
1703 def p_expr_1(self, t):
1704 '''expr : LBRACKET list_expr RBRACKET'''
1705 t[0] = t[2]
1706
1707 def p_list_expr_0(self, t):
1708 'list_expr : expr'
1709 t[0] = [t[1]]
1710
1711 def p_list_expr_1(self, t):
1712 'list_expr : list_expr COMMA expr'
1713 t[0] = t[1] + [t[3]]
1714
1715 def p_list_expr_2(self, t):
1716 'list_expr : empty'
1717 t[0] = []
1718
1719 #
1720 # Empty production... use in other rules for readability.
1721 #
1722 def p_empty(self, t):
1723 'empty :'
1724 pass
1725
1726 # Parse error handler. Note that the argument here is the
1727 # offending *token*, not a grammar symbol (hence the need to use
1728 # t.value)
1729 def p_error(self, t):
1730 if t:
1731 error(t, "syntax error at '%s'" % t.value)
1732 else:
1733 error("unknown syntax error")
1734
1735 # END OF GRAMMAR RULES
1736
1737 def updateExportContext(self):
1738
1739 # create a continuation that allows us to grab the current parser
1740 def wrapInstObjParams(*args):
1741 return InstObjParams(self, *args)
1742 self.exportContext['InstObjParams'] = wrapInstObjParams
1743 self.exportContext.update(self.templateMap)
1744
1745 def defFormat(self, id, params, code, lineno):
1746 '''Define a new format'''
1747
1748 # make sure we haven't already defined this one
1749 if id in self.formatMap:
1750 error(lineno, 'format %s redefined.' % id)
1751
1752 # create new object and store in global map
1753 self.formatMap[id] = Format(id, params, code)
1754
1755 def expandCpuSymbolsToDict(self, template):
1756 '''Expand template with CPU-specific references into a
1757 dictionary with an entry for each CPU model name. The entry
1758 key is the model name and the corresponding value is the
1759 template with the CPU-specific refs substituted for that
1760 model.'''
1761
1762 # Protect '%'s that don't go with CPU-specific terms
1763 t = re.sub(r'%(?!\(CPU_)', '%%', template)
1764 result = {}
1765 for cpu in self.cpuModels:
1766 result[cpu.name] = t % cpu.strings
1767 return result
1768
1769 def expandCpuSymbolsToString(self, template):
1770 '''*If* the template has CPU-specific references, return a
1771 single string containing a copy of the template for each CPU
1772 model with the corresponding values substituted in. If the
1773 template has no CPU-specific references, it is returned
1774 unmodified.'''
1775
1776 if template.find('%(CPU_') != -1:
1777 return reduce(lambda x,y: x+y,
1778 self.expandCpuSymbolsToDict(template).values())
1779 else:
1780 return template
1781
1782 def protectCpuSymbols(self, template):
1783 '''Protect CPU-specific references by doubling the
1784 corresponding '%'s (in preparation for substituting a different
1785 set of references into the template).'''
1786
1787 return re.sub(r'%(?=\(CPU_)', '%%', template)
1788
1789 def protectNonSubstPercents(self, s):
1790 '''Protect any non-dict-substitution '%'s in a format string
1791 (i.e. those not followed by '(')'''
1792
1793 return re.sub(r'%(?!\()', '%%', s)
1794
1795 def buildOperandNameMap(self, user_dict, lineno):
1796 operand_name = {}
1797 for op_name, val in user_dict.iteritems():
1798 base_cls_name, dflt_ext, reg_spec, flags, sort_pri = val[:5]
1799 if len(val) > 5:
1800 read_code = val[5]
1801 else:
1802 read_code = None
1803 if len(val) > 6:
1804 write_code = val[6]
1805 else:
1806 write_code = None
1807 if len(val) > 7:
1808 error(lineno,
1809 'error: too many attributes for operand "%s"' %
1810 base_cls_name)
1811
1812 # Canonical flag structure is a triple of lists, where each list
1813 # indicates the set of flags implied by this operand always, when
1814 # used as a source, and when used as a dest, respectively.
1815 # For simplicity this can be initialized using a variety of fairly
1816 # obvious shortcuts; we convert these to canonical form here.
1817 if not flags:
1818 # no flags specified (e.g., 'None')
1819 flags = ( [], [], [] )
1820 elif isinstance(flags, str):
1821 # a single flag: assumed to be unconditional
1822 flags = ( [ flags ], [], [] )
1823 elif isinstance(flags, list):
1824 # a list of flags: also assumed to be unconditional
1825 flags = ( flags, [], [] )
1826 elif isinstance(flags, tuple):
1827 # it's a tuple: it should be a triple,
1828 # but each item could be a single string or a list
1829 (uncond_flags, src_flags, dest_flags) = flags
1830 flags = (makeList(uncond_flags),
1831 makeList(src_flags), makeList(dest_flags))
1832 # Accumulate attributes of new operand class in tmp_dict
1833 tmp_dict = {}
1834 attrList = ['reg_spec', 'flags', 'sort_pri',
1835 'read_code', 'write_code']
1836 if dflt_ext:
1837 dflt_ctype = self.operandTypeMap[dflt_ext]
1838 attrList.extend(['dflt_ctype', 'dflt_ext'])
1839 for attr in attrList:
1840 tmp_dict[attr] = eval(attr)
1841 tmp_dict['base_name'] = op_name
1842 # New class name will be e.g. "IntReg_Ra"
1843 cls_name = base_cls_name + '_' + op_name
1844 # Evaluate string arg to get class object. Note that the
1845 # actual base class for "IntReg" is "IntRegOperand", i.e. we
1846 # have to append "Operand".
1847 try:
1848 base_cls = eval(base_cls_name + 'Operand')
1849 except NameError:
1850 error(lineno,
1851 'error: unknown operand base class "%s"' % base_cls_name)
1852 # The following statement creates a new class called
1853 # <cls_name> as a subclass of <base_cls> with the attributes
1854 # in tmp_dict, just as if we evaluated a class declaration.
1855 operand_name[op_name] = type(cls_name, (base_cls,), tmp_dict)
1856
1857 self.operandNameMap = operand_name
1858
1859 # Define operand variables.
1860 operands = user_dict.keys()
1861 extensions = self.operandTypeMap.keys()
1862
1863 operandsREString = r'''
1864 (?<!\w) # neg. lookbehind assertion: prevent partial matches
1865 ((%s)(?:_(%s))?) # match: operand with optional '_' then suffix
1866 (?!\w) # neg. lookahead assertion: prevent partial matches
1867 ''' % (string.join(operands, '|'), string.join(extensions, '|'))
1868
1869 self.operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
1870
1871 # Same as operandsREString, but extension is mandatory, and only two
1872 # groups are returned (base and ext, not full name as above).
1873 # Used for subtituting '_' for '.' to make C++ identifiers.
1874 operandsWithExtREString = r'(?<!\w)(%s)_(%s)(?!\w)' \
1875 % (string.join(operands, '|'), string.join(extensions, '|'))
1876
1877 self.operandsWithExtRE = \
1878 re.compile(operandsWithExtREString, re.MULTILINE)
1879
1880 def substMungedOpNames(self, code):
1881 '''Munge operand names in code string to make legal C++
1882 variable names. This means getting rid of the type extension
1883 if any. Will match base_name attribute of Operand object.)'''
1884 return self.operandsWithExtRE.sub(r'\1', code)
1885
1886 def mungeSnippet(self, s):
1887 '''Fix up code snippets for final substitution in templates.'''
1888 if isinstance(s, str):
1889 return self.substMungedOpNames(substBitOps(s))
1890 else:
1891 return s
1892
1893 def update_if_needed(self, file, contents):
1894 '''Update the output file only if the new contents are
1895 different from the current contents. Minimizes the files that
1896 need to be rebuilt after minor changes.'''
1897
1898 file = os.path.join(self.output_dir, file)
1899 update = False
1900 if os.access(file, os.R_OK):
1901 f = open(file, 'r')
1902 old_contents = f.read()
1903 f.close()
1904 if contents != old_contents:
1905 os.remove(file) # in case it's write-protected
1906 update = True
1907 else:
1908 print 'File', file, 'is unchanged'
1909 else:
1910 update = True
1911 if update:
1912 f = open(file, 'w')
1913 f.write(contents)
1914 f.close()
1915
1916 # This regular expression matches '##include' directives
1917 includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[^"]*)".*$',
1918 re.MULTILINE)
1919
1920 def replace_include(self, matchobj, dirname):
1921 """Function to replace a matched '##include' directive with the
1922 contents of the specified file (with nested ##includes
1923 replaced recursively). 'matchobj' is an re match object
1924 (from a match of includeRE) and 'dirname' is the directory
1925 relative to which the file path should be resolved."""
1926
1927 fname = matchobj.group('filename')
1928 full_fname = os.path.normpath(os.path.join(dirname, fname))
1929 contents = '##newfile "%s"\n%s\n##endfile\n' % \
1930 (full_fname, self.read_and_flatten(full_fname))
1931 return contents
1932
1933 def read_and_flatten(self, filename):
1934 """Read a file and recursively flatten nested '##include' files."""
1935
1936 current_dir = os.path.dirname(filename)
1937 try:
1938 contents = open(filename).read()
1939 except IOError:
1940 error('Error including file "%s"' % filename)
1941
1942 self.fileNameStack.push((filename, 0))
1943
1944 # Find any includes and include them
1945 def replace(matchobj):
1946 return self.replace_include(matchobj, current_dir)
1947 contents = self.includeRE.sub(replace, contents)
1948
1949 self.fileNameStack.pop()
1950 return contents
1951
1952 def _parse_isa_desc(self, isa_desc_file):
1953 '''Read in and parse the ISA description.'''
1954
1955 # Read file and (recursively) all included files into a string.
1956 # PLY requires that the input be in a single string so we have to
1957 # do this up front.
1958 isa_desc = self.read_and_flatten(isa_desc_file)
1959
1960 # Initialize filename stack with outer file.
1961 self.fileNameStack.push((isa_desc_file, 0))
1962
1963 # Parse it.
1964 (isa_name, namespace, global_code, namespace_code) = \
1965 self.parse_string(isa_desc)
1966
1967 # grab the last three path components of isa_desc_file to put in
1968 # the output
1969 filename = '/'.join(isa_desc_file.split('/')[-3:])
1970
1971 # generate decoder.hh
1972 includes = '#include "base/bitfield.hh" // for bitfield support'
1973 global_output = global_code.header_output
1974 namespace_output = namespace_code.header_output
1975 decode_function = ''
1976 self.update_if_needed('decoder.hh', file_template % vars())
1977
1978 # generate decoder.cc
1979 includes = '#include "decoder.hh"'
1980 global_output = global_code.decoder_output
1981 namespace_output = namespace_code.decoder_output
1982 # namespace_output += namespace_code.decode_block
1983 decode_function = namespace_code.decode_block
1984 self.update_if_needed('decoder.cc', file_template % vars())
1985
1986 # generate per-cpu exec files
1987 for cpu in self.cpuModels:
1988 includes = '#include "decoder.hh"\n'
1989 includes += cpu.includes
1990 global_output = global_code.exec_output[cpu.name]
1991 namespace_output = namespace_code.exec_output[cpu.name]
1992 decode_function = ''
1993 self.update_if_needed(cpu.filename, file_template % vars())
1994
1995 # The variable names here are hacky, but this will creat local
1996 # variables which will be referenced in vars() which have the
1997 # value of the globals.
1998 MaxInstSrcRegs = self.maxInstSrcRegs
1999 MaxInstDestRegs = self.maxInstDestRegs
2000 MaxMiscDestRegs = self.maxMiscDestRegs
1993 # max_inst_regs.hh
1994 self.update_if_needed('max_inst_regs.hh',
1995 max_inst_regs_template % vars())
1996
1997 def parse_isa_desc(self, *args, **kwargs):
1998 try:
1999 self._parse_isa_desc(*args, **kwargs)
2000 except ISAParserError, e:
2001 e.exit(self.fileNameStack)
2002
2003# Called as script: get args from command line.
2004# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2005if __name__ == '__main__':
2006 execfile(sys.argv[1]) # read in CpuModel definitions
2007 cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
2008 ISAParser(sys.argv[3], cpu_models).parse_isa_desc(sys.argv[2])
2001 # max_inst_regs.hh
2002 self.update_if_needed('max_inst_regs.hh',
2003 max_inst_regs_template % vars())
2004
2005 def parse_isa_desc(self, *args, **kwargs):
2006 try:
2007 self._parse_isa_desc(*args, **kwargs)
2008 except ISAParserError, e:
2009 e.exit(self.fileNameStack)
2010
2011# Called as script: get args from command line.
2012# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
2013if __name__ == '__main__':
2014 execfile(sys.argv[1]) # read in CpuModel definitions
2015 cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
2016 ISAParser(sys.argv[3], cpu_models).parse_isa_desc(sys.argv[2])