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