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