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