Type.py revision 13672
16019Shines@cs.fsu.edu# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
26019Shines@cs.fsu.edu# Copyright (c) 2009 The Hewlett-Packard Development Company
37178Sgblack@eecs.umich.edu# All rights reserved.
47178Sgblack@eecs.umich.edu#
57178Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
67178Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are
77178Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright
87178Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
97178Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
107178Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
117178Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution;
127178Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its
137178Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from
147178Sgblack@eecs.umich.edu# this software without specific prior written permission.
156019Shines@cs.fsu.edu#
166019Shines@cs.fsu.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176019Shines@cs.fsu.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186019Shines@cs.fsu.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196019Shines@cs.fsu.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206019Shines@cs.fsu.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216019Shines@cs.fsu.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226019Shines@cs.fsu.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236019Shines@cs.fsu.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246019Shines@cs.fsu.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256019Shines@cs.fsu.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266019Shines@cs.fsu.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276019Shines@cs.fsu.edu
286019Shines@cs.fsu.edufrom collections import OrderedDict
296019Shines@cs.fsu.edu
306019Shines@cs.fsu.edufrom slicc.util import PairContainer
316019Shines@cs.fsu.edufrom slicc.symbols.Symbol import Symbol
326019Shines@cs.fsu.edufrom slicc.symbols.Var import Var
336019Shines@cs.fsu.edu
346019Shines@cs.fsu.educlass DataMember(Var):
356019Shines@cs.fsu.edu    def __init__(self, symtab, ident, location, type, code, pairs,
366019Shines@cs.fsu.edu                 machine, init_code):
376019Shines@cs.fsu.edu        super(DataMember, self).__init__(symtab, ident, location, type,
386019Shines@cs.fsu.edu                                         code, pairs, machine)
396019Shines@cs.fsu.edu        self.init_code = init_code
406019Shines@cs.fsu.edu
416019Shines@cs.fsu.educlass Enumeration(PairContainer):
426019Shines@cs.fsu.edu    def __init__(self, ident, pairs):
436019Shines@cs.fsu.edu        super(Enumeration, self).__init__(pairs)
446019Shines@cs.fsu.edu        self.ident = ident
456019Shines@cs.fsu.edu        self.primary = False
466019Shines@cs.fsu.edu
476019Shines@cs.fsu.educlass Type(Symbol):
486019Shines@cs.fsu.edu    def __init__(self, table, ident, location, pairs, machine=None):
496019Shines@cs.fsu.edu        super(Type, self).__init__(table, ident, location, pairs)
506019Shines@cs.fsu.edu        self.c_ident = ident
516019Shines@cs.fsu.edu        self.abstract_ident = ""
526019Shines@cs.fsu.edu        if machine:
536019Shines@cs.fsu.edu            if self.isExternal or self.isPrimitive:
546019Shines@cs.fsu.edu                if "external_name" in self:
556019Shines@cs.fsu.edu                    self.c_ident = self["external_name"]
566019Shines@cs.fsu.edu            else:
576019Shines@cs.fsu.edu                # Append with machine name
586243Sgblack@eecs.umich.edu                self.c_ident = "%s_%s" % (machine, ident)
596243Sgblack@eecs.umich.edu
606243Sgblack@eecs.umich.edu        self.pairs.setdefault("desc", "No description avaliable")
616243Sgblack@eecs.umich.edu
626243Sgblack@eecs.umich.edu        # check for interface that this Type implements
636019Shines@cs.fsu.edu        if "interface" in self:
646019Shines@cs.fsu.edu            interface = self["interface"]
656019Shines@cs.fsu.edu            if interface in ("Message"):
666019Shines@cs.fsu.edu                self["message"] = "yes"
676019Shines@cs.fsu.edu
686019Shines@cs.fsu.edu        # FIXME - all of the following id comparisons are fragile hacks
696019Shines@cs.fsu.edu        if self.ident in ("CacheMemory"):
706019Shines@cs.fsu.edu            self["cache"] = "yes"
716019Shines@cs.fsu.edu
726019Shines@cs.fsu.edu        if self.ident in ("TBETable"):
736019Shines@cs.fsu.edu            self["tbe"] = "yes"
746019Shines@cs.fsu.edu
756019Shines@cs.fsu.edu        if self.ident == "TimerTable":
766019Shines@cs.fsu.edu            self["timer"] = "yes"
776019Shines@cs.fsu.edu
786019Shines@cs.fsu.edu        if self.ident == "DirectoryMemory":
796019Shines@cs.fsu.edu            self["dir"] = "yes"
806019Shines@cs.fsu.edu
816019Shines@cs.fsu.edu        if self.ident == "PersistentTable":
826019Shines@cs.fsu.edu            self["persistent"] = "yes"
836019Shines@cs.fsu.edu
846019Shines@cs.fsu.edu        if self.ident == "Prefetcher":
856019Shines@cs.fsu.edu            self["prefetcher"] = "yes"
866019Shines@cs.fsu.edu
876019Shines@cs.fsu.edu        self.isMachineType = (ident == "MachineType")
886019Shines@cs.fsu.edu
896019Shines@cs.fsu.edu        self.isStateDecl = ("state_decl" in self)
906019Shines@cs.fsu.edu        self.statePermPairs = []
916019Shines@cs.fsu.edu
926019Shines@cs.fsu.edu        self.data_members = OrderedDict()
936019Shines@cs.fsu.edu        self.methods = {}
946252Sgblack@eecs.umich.edu        self.enums = OrderedDict()
956243Sgblack@eecs.umich.edu
966243Sgblack@eecs.umich.edu    @property
976243Sgblack@eecs.umich.edu    def isPrimitive(self):
986019Shines@cs.fsu.edu        return "primitive" in self
996019Shines@cs.fsu.edu
1006019Shines@cs.fsu.edu    @property
1016019Shines@cs.fsu.edu    def isMessage(self):
1026019Shines@cs.fsu.edu        return "message" in self
1036252Sgblack@eecs.umich.edu    @property
1046243Sgblack@eecs.umich.edu    def isBuffer(self):
1056243Sgblack@eecs.umich.edu        return "buffer" in self
1066243Sgblack@eecs.umich.edu    @property
1076019Shines@cs.fsu.edu    def isInPort(self):
1086019Shines@cs.fsu.edu        return "inport" in self
1096019Shines@cs.fsu.edu    @property
1106019Shines@cs.fsu.edu    def isOutPort(self):
1116019Shines@cs.fsu.edu        return "outport" in self
1126019Shines@cs.fsu.edu    @property
1136019Shines@cs.fsu.edu    def isEnumeration(self):
1146252Sgblack@eecs.umich.edu        return "enumeration" in self
1156243Sgblack@eecs.umich.edu    @property
1166243Sgblack@eecs.umich.edu    def isExternal(self):
1176243Sgblack@eecs.umich.edu        return "external" in self
1186019Shines@cs.fsu.edu    @property
1196019Shines@cs.fsu.edu    def isGlobal(self):
1206019Shines@cs.fsu.edu        return "global" in self
1216019Shines@cs.fsu.edu    @property
1226019Shines@cs.fsu.edu    def isInterface(self):
1236019Shines@cs.fsu.edu        return "interface" in self
1246019Shines@cs.fsu.edu
1256019Shines@cs.fsu.edu    # Return false on error
1266019Shines@cs.fsu.edu    def addDataMember(self, ident, type, pairs, init_code):
1276019Shines@cs.fsu.edu        if ident in self.data_members:
1286019Shines@cs.fsu.edu            return False
1296019Shines@cs.fsu.edu
1306019Shines@cs.fsu.edu        member = DataMember(self.symtab, ident, self.location, type,
1316019Shines@cs.fsu.edu                            "m_%s" % ident, pairs, None, init_code)
1326019Shines@cs.fsu.edu
1336019Shines@cs.fsu.edu        self.data_members[ident] = member
1346724Sgblack@eecs.umich.edu        self.symtab.registerSym(ident, member)
1356724Sgblack@eecs.umich.edu        return True
1366019Shines@cs.fsu.edu
1376019Shines@cs.fsu.edu    def dataMemberType(self, ident):
1386019Shines@cs.fsu.edu        return self.data_members[ident].type
1396019Shines@cs.fsu.edu
1406019Shines@cs.fsu.edu    def methodId(self, name, param_type_vec):
1416252Sgblack@eecs.umich.edu        return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
1426243Sgblack@eecs.umich.edu
1436243Sgblack@eecs.umich.edu    def methodIdAbstract(self, name, param_type_vec):
1446243Sgblack@eecs.umich.edu        return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
1456019Shines@cs.fsu.edu
1466019Shines@cs.fsu.edu    def statePermPairAdd(self, state_name, perm_name):
1476019Shines@cs.fsu.edu        self.statePermPairs.append([state_name, perm_name])
1486019Shines@cs.fsu.edu
1496019Shines@cs.fsu.edu    def addFunc(self, func):
1506019Shines@cs.fsu.edu        ident = self.methodId(func.ident, func.param_types)
1517356Sgblack@eecs.umich.edu        if ident in self.methods:
1527356Sgblack@eecs.umich.edu            return False
1537356Sgblack@eecs.umich.edu
1547356Sgblack@eecs.umich.edu        self.methods[ident] = func
1557356Sgblack@eecs.umich.edu        return True
1567356Sgblack@eecs.umich.edu
1577356Sgblack@eecs.umich.edu    def addEnum(self, ident, pairs):
1587356Sgblack@eecs.umich.edu        if ident in self.enums:
1597178Sgblack@eecs.umich.edu            return False
1607178Sgblack@eecs.umich.edu
1617178Sgblack@eecs.umich.edu        self.enums[ident] = Enumeration(ident, pairs)
1627337Sgblack@eecs.umich.edu
1637178Sgblack@eecs.umich.edu        # Add default
1647178Sgblack@eecs.umich.edu        if "default" not in self:
1657178Sgblack@eecs.umich.edu            self["default"] = "%s_NUM" % self.c_ident
1667178Sgblack@eecs.umich.edu
1677178Sgblack@eecs.umich.edu        return True
1687178Sgblack@eecs.umich.edu
1697178Sgblack@eecs.umich.edu    ## Used to check if an enum has been already used and therefore
1707178Sgblack@eecs.umich.edu    ## should not be used again.
1717178Sgblack@eecs.umich.edu    def checkEnum(self, ident):
1727178Sgblack@eecs.umich.edu        if ident in self.enums and not self.enums[ident].primary:
1737178Sgblack@eecs.umich.edu            self.enums[ident].primary = True
1747335Sgblack@eecs.umich.edu            return True
1757335Sgblack@eecs.umich.edu        return False
1767335Sgblack@eecs.umich.edu
1777335Sgblack@eecs.umich.edu    def writeCodeFiles(self, path, includes):
1787335Sgblack@eecs.umich.edu        if self.isExternal:
1797335Sgblack@eecs.umich.edu            # Do nothing
1807335Sgblack@eecs.umich.edu            pass
1817335Sgblack@eecs.umich.edu        elif self.isEnumeration:
1827335Sgblack@eecs.umich.edu            self.printEnumHH(path)
1837335Sgblack@eecs.umich.edu            self.printEnumCC(path)
1847335Sgblack@eecs.umich.edu        else:
1857335Sgblack@eecs.umich.edu            # User defined structs and messages
1867337Sgblack@eecs.umich.edu            self.printTypeHH(path)
1877335Sgblack@eecs.umich.edu            self.printTypeCC(path)
1887335Sgblack@eecs.umich.edu
1897335Sgblack@eecs.umich.edu    def printTypeHH(self, path):
1907335Sgblack@eecs.umich.edu        code = self.symtab.codeFormatter()
1917335Sgblack@eecs.umich.edu        code('''
1927335Sgblack@eecs.umich.edu/** \\file ${{self.c_ident}}.hh
1937335Sgblack@eecs.umich.edu *
1947335Sgblack@eecs.umich.edu *
1957335Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__
1967335Sgblack@eecs.umich.edu */
1977335Sgblack@eecs.umich.edu
1987335Sgblack@eecs.umich.edu#ifndef __${{self.c_ident}}_HH__
1997178Sgblack@eecs.umich.edu#define __${{self.c_ident}}_HH__
2007178Sgblack@eecs.umich.edu
2017178Sgblack@eecs.umich.edu#include <iostream>
2027178Sgblack@eecs.umich.edu
2037178Sgblack@eecs.umich.edu#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
2047178Sgblack@eecs.umich.edu''')
2057178Sgblack@eecs.umich.edu
2067178Sgblack@eecs.umich.edu        for dm in self.data_members.values():
2077178Sgblack@eecs.umich.edu            if not dm.type.isPrimitive:
2087178Sgblack@eecs.umich.edu                code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
2097178Sgblack@eecs.umich.edu
2107178Sgblack@eecs.umich.edu        parent = ""
2117178Sgblack@eecs.umich.edu        if "interface" in self:
2127178Sgblack@eecs.umich.edu            code('#include "mem/protocol/$0.hh"', self["interface"])
2137178Sgblack@eecs.umich.edu            parent = " :  public %s" % self["interface"]
2147178Sgblack@eecs.umich.edu
2157178Sgblack@eecs.umich.edu        code('''
2167178Sgblack@eecs.umich.edu$klass ${{self.c_ident}}$parent
2177178Sgblack@eecs.umich.edu{
2187178Sgblack@eecs.umich.edu  public:
2197178Sgblack@eecs.umich.edu    ${{self.c_ident}}
2207178Sgblack@eecs.umich.edu''', klass="class")
2217178Sgblack@eecs.umich.edu
2227178Sgblack@eecs.umich.edu        if self.isMessage:
2237178Sgblack@eecs.umich.edu            code('(Tick curTime) : %s(curTime) {' % self["interface"])
2247178Sgblack@eecs.umich.edu        else:
2257178Sgblack@eecs.umich.edu            code('()\n\t\t{')
2267178Sgblack@eecs.umich.edu
2277178Sgblack@eecs.umich.edu        code.indent()
2287346Sgblack@eecs.umich.edu        if not self.isGlobal:
2297346Sgblack@eecs.umich.edu            code.indent()
2307346Sgblack@eecs.umich.edu            for dm in self.data_members.values():
2317346Sgblack@eecs.umich.edu                ident = dm.ident
2327346Sgblack@eecs.umich.edu                if "default" in dm:
2337346Sgblack@eecs.umich.edu                    # look for default value
2347346Sgblack@eecs.umich.edu                    code('m_$ident = ${{dm["default"]}}; // default for this field')
2357346Sgblack@eecs.umich.edu                elif "default" in dm.type:
2367346Sgblack@eecs.umich.edu                    # Look for the type default
2377346Sgblack@eecs.umich.edu                    tid = dm.type.c_ident
2387178Sgblack@eecs.umich.edu                    code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
2397346Sgblack@eecs.umich.edu                else:
2407346Sgblack@eecs.umich.edu                    code('// m_$ident has no default')
2417346Sgblack@eecs.umich.edu            code.dedent()
2427346Sgblack@eecs.umich.edu        code('}')
2437346Sgblack@eecs.umich.edu
2447346Sgblack@eecs.umich.edu        # ******** Copy constructor ********
2457346Sgblack@eecs.umich.edu        if not self.isGlobal:
2467346Sgblack@eecs.umich.edu            code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
2477346Sgblack@eecs.umich.edu
2487346Sgblack@eecs.umich.edu            # Call superclass constructor
2497346Sgblack@eecs.umich.edu            if "interface" in self:
2507346Sgblack@eecs.umich.edu                code('    : ${{self["interface"]}}(other)')
2517346Sgblack@eecs.umich.edu
2527346Sgblack@eecs.umich.edu            code('{')
2537346Sgblack@eecs.umich.edu            code.indent()
2547178Sgblack@eecs.umich.edu
2557337Sgblack@eecs.umich.edu            for dm in self.data_members.values():
2567337Sgblack@eecs.umich.edu                code('m_${{dm.ident}} = other.m_${{dm.ident}};')
2577337Sgblack@eecs.umich.edu
2587337Sgblack@eecs.umich.edu            code.dedent()
2597337Sgblack@eecs.umich.edu            code('}')
2607337Sgblack@eecs.umich.edu
2617337Sgblack@eecs.umich.edu        # ******** Full init constructor ********
2627337Sgblack@eecs.umich.edu        if not self.isGlobal:
2637337Sgblack@eecs.umich.edu            params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
2647337Sgblack@eecs.umich.edu                       for dm in self.data_members.itervalues() ]
2657337Sgblack@eecs.umich.edu            params = ', '.join(params)
2667337Sgblack@eecs.umich.edu
2677337Sgblack@eecs.umich.edu            if self.isMessage:
2687337Sgblack@eecs.umich.edu                params = "const Tick curTime, " + params
2697337Sgblack@eecs.umich.edu
2707178Sgblack@eecs.umich.edu            code('${{self.c_ident}}($params)')
2717178Sgblack@eecs.umich.edu
2727178Sgblack@eecs.umich.edu            # Call superclass constructor
2737178Sgblack@eecs.umich.edu            if "interface" in self:
2747337Sgblack@eecs.umich.edu                if self.isMessage:
2757337Sgblack@eecs.umich.edu                    code('    : ${{self["interface"]}}(curTime)')
2767337Sgblack@eecs.umich.edu                else:
2777337Sgblack@eecs.umich.edu                    code('    : ${{self["interface"]}}()')
2787346Sgblack@eecs.umich.edu
2797346Sgblack@eecs.umich.edu            code('{')
2807346Sgblack@eecs.umich.edu            code.indent()
2817346Sgblack@eecs.umich.edu            for dm in self.data_members.values():
2827346Sgblack@eecs.umich.edu                code('m_${{dm.ident}} = local_${{dm.ident}};')
2837337Sgblack@eecs.umich.edu
2847178Sgblack@eecs.umich.edu            code.dedent()
2857321Sgblack@eecs.umich.edu            code('}')
2867356Sgblack@eecs.umich.edu
2877321Sgblack@eecs.umich.edu        # create a clone member
2887356Sgblack@eecs.umich.edu        if self.isMessage:
2897356Sgblack@eecs.umich.edu            code('''
2907356Sgblack@eecs.umich.eduMsgPtr
2917356Sgblack@eecs.umich.educlone() const
2927356Sgblack@eecs.umich.edu{
2937356Sgblack@eecs.umich.edu     return std::shared_ptr<Message>(new ${{self.c_ident}}(*this));
2947356Sgblack@eecs.umich.edu}
2957356Sgblack@eecs.umich.edu''')
2967356Sgblack@eecs.umich.edu        else:
2977356Sgblack@eecs.umich.edu            code('''
2987356Sgblack@eecs.umich.edu${{self.c_ident}}*
2997356Sgblack@eecs.umich.educlone() const
3007321Sgblack@eecs.umich.edu{
3017321Sgblack@eecs.umich.edu     return new ${{self.c_ident}}(*this);
3027321Sgblack@eecs.umich.edu}
3037321Sgblack@eecs.umich.edu''')
3047321Sgblack@eecs.umich.edu
3057321Sgblack@eecs.umich.edu        if not self.isGlobal:
3067321Sgblack@eecs.umich.edu            # const Get methods for each field
3077321Sgblack@eecs.umich.edu            code('// Const accessors methods for each field')
3087321Sgblack@eecs.umich.edu            for dm in self.data_members.values():
3097321Sgblack@eecs.umich.edu                code('''
3107321Sgblack@eecs.umich.edu/** \\brief Const accessor method for ${{dm.ident}} field.
3117335Sgblack@eecs.umich.edu *  \\return ${{dm.ident}} field
3127335Sgblack@eecs.umich.edu */
3137335Sgblack@eecs.umich.educonst ${{dm.type.c_ident}}&
3147335Sgblack@eecs.umich.eduget${{dm.ident}}() const
3157335Sgblack@eecs.umich.edu{
3167335Sgblack@eecs.umich.edu    return m_${{dm.ident}};
3177335Sgblack@eecs.umich.edu}
3187335Sgblack@eecs.umich.edu''')
3197335Sgblack@eecs.umich.edu
3207321Sgblack@eecs.umich.edu            # Non-const Get methods for each field
3217323Sgblack@eecs.umich.edu            code('// Non const Accessors methods for each field')
3227323Sgblack@eecs.umich.edu            for dm in self.data_members.values():
3237323Sgblack@eecs.umich.edu                code('''
3247323Sgblack@eecs.umich.edu/** \\brief Non-const accessor method for ${{dm.ident}} field.
3257323Sgblack@eecs.umich.edu *  \\return ${{dm.ident}} field
3267323Sgblack@eecs.umich.edu */
3277323Sgblack@eecs.umich.edu${{dm.type.c_ident}}&
3287323Sgblack@eecs.umich.eduget${{dm.ident}}()
3297323Sgblack@eecs.umich.edu{
3307323Sgblack@eecs.umich.edu    return m_${{dm.ident}};
3317323Sgblack@eecs.umich.edu}
3327323Sgblack@eecs.umich.edu''')
3337323Sgblack@eecs.umich.edu
3347323Sgblack@eecs.umich.edu            #Set methods for each field
3357323Sgblack@eecs.umich.edu            code('// Mutator methods for each field')
3367323Sgblack@eecs.umich.edu            for dm in self.data_members.values():
3377323Sgblack@eecs.umich.edu                code('''
3387321Sgblack@eecs.umich.edu/** \\brief Mutator method for ${{dm.ident}} field */
3397321Sgblack@eecs.umich.eduvoid
3407321Sgblack@eecs.umich.eduset${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
3417335Sgblack@eecs.umich.edu{
3427335Sgblack@eecs.umich.edu    m_${{dm.ident}} = local_${{dm.ident}};
3437335Sgblack@eecs.umich.edu}
3447335Sgblack@eecs.umich.edu''')
3457335Sgblack@eecs.umich.edu
3467335Sgblack@eecs.umich.edu        code('void print(std::ostream& out) const;')
3477335Sgblack@eecs.umich.edu        code.dedent()
3487335Sgblack@eecs.umich.edu        code('  //private:')
3497335Sgblack@eecs.umich.edu        code.indent()
3507335Sgblack@eecs.umich.edu
3517335Sgblack@eecs.umich.edu        # Data members for each field
3527335Sgblack@eecs.umich.edu        for dm in self.data_members.values():
3537335Sgblack@eecs.umich.edu            if "abstract" not in dm:
3547335Sgblack@eecs.umich.edu                const = ""
3557335Sgblack@eecs.umich.edu                init = ""
3567335Sgblack@eecs.umich.edu
3577335Sgblack@eecs.umich.edu                # global structure
3587335Sgblack@eecs.umich.edu                if self.isGlobal:
3597335Sgblack@eecs.umich.edu                    const = "static const "
3607335Sgblack@eecs.umich.edu
3617335Sgblack@eecs.umich.edu                # init value
3627335Sgblack@eecs.umich.edu                if dm.init_code:
3637335Sgblack@eecs.umich.edu                    # only global structure can have init value here
3647335Sgblack@eecs.umich.edu                    assert self.isGlobal
3657335Sgblack@eecs.umich.edu                    init = " = %s" % (dm.init_code)
3667335Sgblack@eecs.umich.edu
3677335Sgblack@eecs.umich.edu                if "desc" in dm:
3687335Sgblack@eecs.umich.edu                    code('/** ${{dm["desc"]}} */')
3697335Sgblack@eecs.umich.edu
3707335Sgblack@eecs.umich.edu                code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
3717335Sgblack@eecs.umich.edu
3727335Sgblack@eecs.umich.edu        # Prototypes for methods defined for the Type
3737335Sgblack@eecs.umich.edu        for item in self.methods:
3747321Sgblack@eecs.umich.edu            proto = self.methods[item].prototype
3757321Sgblack@eecs.umich.edu            if proto:
3767321Sgblack@eecs.umich.edu                code('$proto')
3777321Sgblack@eecs.umich.edu
3787321Sgblack@eecs.umich.edu        code.dedent()
3797321Sgblack@eecs.umich.edu        code('};')
3807335Sgblack@eecs.umich.edu
3817335Sgblack@eecs.umich.edu        code('''
3827335Sgblack@eecs.umich.eduinline std::ostream&
3837335Sgblack@eecs.umich.eduoperator<<(std::ostream& out, const ${{self.c_ident}}& obj)
3847335Sgblack@eecs.umich.edu{
3857335Sgblack@eecs.umich.edu    obj.print(out);
3867335Sgblack@eecs.umich.edu    out << std::flush;
3877335Sgblack@eecs.umich.edu    return out;
3887335Sgblack@eecs.umich.edu}
3897321Sgblack@eecs.umich.edu
3907326Sgblack@eecs.umich.edu#endif // __${{self.c_ident}}_HH__
3917326Sgblack@eecs.umich.edu''')
3927326Sgblack@eecs.umich.edu
3937326Sgblack@eecs.umich.edu        code.write(path, "%s.hh" % self.c_ident)
3947326Sgblack@eecs.umich.edu
3957326Sgblack@eecs.umich.edu    def printTypeCC(self, path):
3967326Sgblack@eecs.umich.edu        code = self.symtab.codeFormatter()
3977326Sgblack@eecs.umich.edu
3987326Sgblack@eecs.umich.edu        code('''
3997326Sgblack@eecs.umich.edu/** \\file ${{self.c_ident}}.cc
4007326Sgblack@eecs.umich.edu *
4017326Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__
4027326Sgblack@eecs.umich.edu */
4037326Sgblack@eecs.umich.edu
4047326Sgblack@eecs.umich.edu#include <iostream>
4057326Sgblack@eecs.umich.edu#include <memory>
4067326Sgblack@eecs.umich.edu
4077326Sgblack@eecs.umich.edu#include "mem/protocol/${{self.c_ident}}.hh"
4087326Sgblack@eecs.umich.edu#include "mem/ruby/system/RubySystem.hh"
4097326Sgblack@eecs.umich.edu
4107326Sgblack@eecs.umich.eduusing namespace std;
4117326Sgblack@eecs.umich.edu''')
4127326Sgblack@eecs.umich.edu
4137321Sgblack@eecs.umich.edu        code('''
4147321Sgblack@eecs.umich.edu/** \\brief Print the state of this object */
4157335Sgblack@eecs.umich.eduvoid
4167335Sgblack@eecs.umich.edu${{self.c_ident}}::print(ostream& out) const
4177335Sgblack@eecs.umich.edu{
4187335Sgblack@eecs.umich.edu    out << "[${{self.c_ident}}: ";
4197335Sgblack@eecs.umich.edu''')
4207335Sgblack@eecs.umich.edu
4217335Sgblack@eecs.umich.edu        # For each field
4227335Sgblack@eecs.umich.edu        code.indent()
4237335Sgblack@eecs.umich.edu        for dm in self.data_members.values():
4247335Sgblack@eecs.umich.edu            if dm.type.c_ident == "Addr":
4257335Sgblack@eecs.umich.edu                code('''
4267335Sgblack@eecs.umich.eduout << "${{dm.ident}} = " << printAddress(m_${{dm.ident}}) << " ";''')
4277335Sgblack@eecs.umich.edu            else:
4287335Sgblack@eecs.umich.edu                code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
4297335Sgblack@eecs.umich.edu
4307335Sgblack@eecs.umich.edu        code.dedent()
4317335Sgblack@eecs.umich.edu
4327335Sgblack@eecs.umich.edu        # Trailer
4337335Sgblack@eecs.umich.edu        code('''
4347335Sgblack@eecs.umich.edu    out << "]";
4357335Sgblack@eecs.umich.edu}''')
4367335Sgblack@eecs.umich.edu
4377335Sgblack@eecs.umich.edu        # print the code for the methods in the type
4387335Sgblack@eecs.umich.edu        for item in self.methods:
4397335Sgblack@eecs.umich.edu            code(self.methods[item].generateCode())
4407335Sgblack@eecs.umich.edu
4417335Sgblack@eecs.umich.edu        code.write(path, "%s.cc" % self.c_ident)
4427335Sgblack@eecs.umich.edu
4437335Sgblack@eecs.umich.edu    def printEnumHH(self, path):
4447335Sgblack@eecs.umich.edu        code = self.symtab.codeFormatter()
4457335Sgblack@eecs.umich.edu        code('''
4467335Sgblack@eecs.umich.edu/** \\file ${{self.c_ident}}.hh
4477335Sgblack@eecs.umich.edu *
4487335Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__
4497335Sgblack@eecs.umich.edu */
4507335Sgblack@eecs.umich.edu
4517335Sgblack@eecs.umich.edu#ifndef __${{self.c_ident}}_HH__
4527335Sgblack@eecs.umich.edu#define __${{self.c_ident}}_HH__
4537335Sgblack@eecs.umich.edu
4547335Sgblack@eecs.umich.edu#include <iostream>
4557335Sgblack@eecs.umich.edu#include <string>
4567335Sgblack@eecs.umich.edu
4577335Sgblack@eecs.umich.edu''')
4587335Sgblack@eecs.umich.edu        if self.isStateDecl:
4597321Sgblack@eecs.umich.edu            code('#include "mem/protocol/AccessPermission.hh"')
4607321Sgblack@eecs.umich.edu
4617321Sgblack@eecs.umich.edu        if self.isMachineType:
4627321Sgblack@eecs.umich.edu            code('#include <functional>')
4637321Sgblack@eecs.umich.edu            code('#include "base/logging.hh"')
4647356Sgblack@eecs.umich.edu            code('#include "mem/ruby/common/Address.hh"')
4657356Sgblack@eecs.umich.edu            code('#include "mem/ruby/common/TypeDefines.hh"')
4667356Sgblack@eecs.umich.edu            code('struct MachineID;')
4677356Sgblack@eecs.umich.edu
4687356Sgblack@eecs.umich.edu        code('''
4697356Sgblack@eecs.umich.edu
4707363Sgblack@eecs.umich.edu// Class definition
4717363Sgblack@eecs.umich.edu/** \\enum ${{self.c_ident}}
4727363Sgblack@eecs.umich.edu *  \\brief ${{self.desc}}
4737363Sgblack@eecs.umich.edu */
4747363Sgblack@eecs.umich.eduenum ${{self.c_ident}} {
4757363Sgblack@eecs.umich.edu    ${{self.c_ident}}_FIRST,
4767363Sgblack@eecs.umich.edu''')
4777363Sgblack@eecs.umich.edu
4787363Sgblack@eecs.umich.edu        code.indent()
4797363Sgblack@eecs.umich.edu        # For each field
4807363Sgblack@eecs.umich.edu        for i,(ident,enum) in enumerate(self.enums.iteritems()):
4817363Sgblack@eecs.umich.edu            desc = enum.get("desc", "No description avaliable")
4827363Sgblack@eecs.umich.edu            if i == 0:
4837363Sgblack@eecs.umich.edu                init = ' = %s_FIRST' % self.c_ident
4847363Sgblack@eecs.umich.edu            else:
4857363Sgblack@eecs.umich.edu                init = ''
4867363Sgblack@eecs.umich.edu            code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
4877363Sgblack@eecs.umich.edu        code.dedent()
4887363Sgblack@eecs.umich.edu        code('''
4897364Sgblack@eecs.umich.edu    ${{self.c_ident}}_NUM
4907364Sgblack@eecs.umich.edu};
4917364Sgblack@eecs.umich.edu
4927364Sgblack@eecs.umich.edu// Code to convert from a string to the enumeration
4937364Sgblack@eecs.umich.edu${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
4947364Sgblack@eecs.umich.edu
4957364Sgblack@eecs.umich.edu// Code to convert state to a string
4967364Sgblack@eecs.umich.edustd::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
4977364Sgblack@eecs.umich.edu
4987364Sgblack@eecs.umich.edu// Code to increment an enumeration type
4997364Sgblack@eecs.umich.edu${{self.c_ident}} &operator++(${{self.c_ident}} &e);
5007364Sgblack@eecs.umich.edu''')
5017364Sgblack@eecs.umich.edu
5027364Sgblack@eecs.umich.edu        if self.isMachineType:
5037364Sgblack@eecs.umich.edu            code('''
5047364Sgblack@eecs.umich.edu
5057364Sgblack@eecs.umich.edu// define a hash function for the MachineType class
5067364Sgblack@eecs.umich.edunamespace std {
5077364Sgblack@eecs.umich.edutemplate<>
5087363Sgblack@eecs.umich.edustruct hash<MachineType> {
5097363Sgblack@eecs.umich.edu    std::size_t operator()(const MachineType &mtype) const {
5107363Sgblack@eecs.umich.edu        return hash<size_t>()(static_cast<size_t>(mtype));
5117363Sgblack@eecs.umich.edu    }
5127363Sgblack@eecs.umich.edu};
5137363Sgblack@eecs.umich.edu}
5147363Sgblack@eecs.umich.edu
5157363Sgblack@eecs.umich.edu''')
5167363Sgblack@eecs.umich.edu        # MachineType hack used to set the base component id for each Machine
5177363Sgblack@eecs.umich.edu        if self.isMachineType:
5187363Sgblack@eecs.umich.edu            code('''
5197363Sgblack@eecs.umich.eduint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
5207363Sgblack@eecs.umich.eduMachineType ${{self.c_ident}}_from_base_level(int);
5217363Sgblack@eecs.umich.eduint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
5227363Sgblack@eecs.umich.eduint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
5237363Sgblack@eecs.umich.edu''')
5247363Sgblack@eecs.umich.edu
5257363Sgblack@eecs.umich.edu            for enum in self.enums.itervalues():
5267363Sgblack@eecs.umich.edu                code('''
5277363Sgblack@eecs.umich.edu
5287363Sgblack@eecs.umich.eduMachineID get${{enum.ident}}MachineID(NodeID RubyNode);
5297363Sgblack@eecs.umich.edu''')
5307363Sgblack@eecs.umich.edu
5317363Sgblack@eecs.umich.edu        if self.isStateDecl:
5327363Sgblack@eecs.umich.edu            code('''
5337363Sgblack@eecs.umich.edu
5347363Sgblack@eecs.umich.edu// Code to convert the current state to an access permission
5357363Sgblack@eecs.umich.eduAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
5367363Sgblack@eecs.umich.edu
5377363Sgblack@eecs.umich.edu''')
5387363Sgblack@eecs.umich.edu
5397363Sgblack@eecs.umich.edu        # Trailer
5407363Sgblack@eecs.umich.edu        code('''
5417363Sgblack@eecs.umich.edustd::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
5427363Sgblack@eecs.umich.edu
5437363Sgblack@eecs.umich.edu#endif // __${{self.c_ident}}_HH__
5447363Sgblack@eecs.umich.edu''')
5457363Sgblack@eecs.umich.edu
5467363Sgblack@eecs.umich.edu        code.write(path, "%s.hh" % self.c_ident)
5477363Sgblack@eecs.umich.edu
5487363Sgblack@eecs.umich.edu    def printEnumCC(self, path):
5497363Sgblack@eecs.umich.edu        code = self.symtab.codeFormatter()
5507363Sgblack@eecs.umich.edu        code('''
5517363Sgblack@eecs.umich.edu/** \\file ${{self.c_ident}}.hh
5527363Sgblack@eecs.umich.edu *
5537363Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__
5547363Sgblack@eecs.umich.edu */
5557363Sgblack@eecs.umich.edu
5567363Sgblack@eecs.umich.edu#include <cassert>
5577366Sgblack@eecs.umich.edu#include <iostream>
5587366Sgblack@eecs.umich.edu#include <string>
5597366Sgblack@eecs.umich.edu
5607366Sgblack@eecs.umich.edu#include "base/logging.hh"
5617366Sgblack@eecs.umich.edu#include "mem/protocol/${{self.c_ident}}.hh"
5627366Sgblack@eecs.umich.edu
5637366Sgblack@eecs.umich.eduusing namespace std;
5647366Sgblack@eecs.umich.edu
5657366Sgblack@eecs.umich.edu''')
5667366Sgblack@eecs.umich.edu
5677366Sgblack@eecs.umich.edu        if self.isStateDecl:
5687366Sgblack@eecs.umich.edu            code('''
5697366Sgblack@eecs.umich.edu// Code to convert the current state to an access permission
5707366Sgblack@eecs.umich.eduAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
5717366Sgblack@eecs.umich.edu{
5727363Sgblack@eecs.umich.edu    switch(obj) {
5737363Sgblack@eecs.umich.edu''')
5747363Sgblack@eecs.umich.edu            # For each case
5757365Sgblack@eecs.umich.edu            code.indent()
5767365Sgblack@eecs.umich.edu            for statePerm in self.statePermPairs:
5777365Sgblack@eecs.umich.edu                code('  case ${{self.c_ident}}_${{statePerm[0]}}:')
5787365Sgblack@eecs.umich.edu                code('    return AccessPermission_${{statePerm[1]}};')
5797365Sgblack@eecs.umich.edu            code.dedent()
5807365Sgblack@eecs.umich.edu            code ('''
5817365Sgblack@eecs.umich.edu      default:
5827365Sgblack@eecs.umich.edu        panic("Unknown state access permission converstion for ${{self.c_ident}}");
5837365Sgblack@eecs.umich.edu    }
5847365Sgblack@eecs.umich.edu}
5857365Sgblack@eecs.umich.edu
5867365Sgblack@eecs.umich.edu''')
5877365Sgblack@eecs.umich.edu
5887365Sgblack@eecs.umich.edu        if self.isMachineType:
5897365Sgblack@eecs.umich.edu            for enum in self.enums.itervalues():
5907363Sgblack@eecs.umich.edu                if enum.primary:
5917363Sgblack@eecs.umich.edu                    code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
5927363Sgblack@eecs.umich.edu            code('#include "mem/ruby/common/MachineID.hh"')
5937363Sgblack@eecs.umich.edu
5947363Sgblack@eecs.umich.edu        code('''
5957363Sgblack@eecs.umich.edu// Code for output operator
5967363Sgblack@eecs.umich.eduostream&
5977363Sgblack@eecs.umich.eduoperator<<(ostream& out, const ${{self.c_ident}}& obj)
5987363Sgblack@eecs.umich.edu{
5997363Sgblack@eecs.umich.edu    out << ${{self.c_ident}}_to_string(obj);
6007363Sgblack@eecs.umich.edu    out << flush;
6017363Sgblack@eecs.umich.edu    return out;
6027363Sgblack@eecs.umich.edu}
6037363Sgblack@eecs.umich.edu
6047363Sgblack@eecs.umich.edu// Code to convert state to a string
6057363Sgblack@eecs.umich.edustring
6067363Sgblack@eecs.umich.edu${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
6077363Sgblack@eecs.umich.edu{
6087363Sgblack@eecs.umich.edu    switch(obj) {
6097363Sgblack@eecs.umich.edu''')
6107363Sgblack@eecs.umich.edu
6117363Sgblack@eecs.umich.edu        # For each field
6127363Sgblack@eecs.umich.edu        code.indent()
6137363Sgblack@eecs.umich.edu        for enum in self.enums.itervalues():
6147363Sgblack@eecs.umich.edu            code('  case ${{self.c_ident}}_${{enum.ident}}:')
6157363Sgblack@eecs.umich.edu            code('    return "${{enum.ident}}";')
6167363Sgblack@eecs.umich.edu        code.dedent()
6177363Sgblack@eecs.umich.edu
6187363Sgblack@eecs.umich.edu        # Trailer
6197363Sgblack@eecs.umich.edu        code('''
6207363Sgblack@eecs.umich.edu      default:
6217363Sgblack@eecs.umich.edu        panic("Invalid range for type ${{self.c_ident}}");
6227363Sgblack@eecs.umich.edu    }
6237363Sgblack@eecs.umich.edu}
6247363Sgblack@eecs.umich.edu
6257363Sgblack@eecs.umich.edu// Code to convert from a string to the enumeration
6267363Sgblack@eecs.umich.edu${{self.c_ident}}
6277363Sgblack@eecs.umich.edustring_to_${{self.c_ident}}(const string& str)
6287363Sgblack@eecs.umich.edu{
6297363Sgblack@eecs.umich.edu''')
6307363Sgblack@eecs.umich.edu
6317363Sgblack@eecs.umich.edu        # For each field
6327363Sgblack@eecs.umich.edu        start = ""
6337363Sgblack@eecs.umich.edu        code.indent()
634        for enum in self.enums.itervalues():
635            code('${start}if (str == "${{enum.ident}}") {')
636            code('    return ${{self.c_ident}}_${{enum.ident}};')
637            start = "} else "
638        code.dedent()
639
640        code('''
641    } else {
642        panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
643    }
644}
645
646// Code to increment an enumeration type
647${{self.c_ident}}&
648operator++(${{self.c_ident}}& e)
649{
650    assert(e < ${{self.c_ident}}_NUM);
651    return e = ${{self.c_ident}}(e+1);
652}
653''')
654
655        # MachineType hack used to set the base level and number of
656        # components for each Machine
657        if self.isMachineType:
658            code('''
659/** \\brief returns the base vector index for each machine type to be
660  * used by NetDest
661  *
662  * \\return the base vector index for each machine type to be used by NetDest
663  * \\see NetDest.hh
664  */
665int
666${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
667{
668    switch(obj) {
669''')
670
671            # For each field
672            code.indent()
673            for i,enum in enumerate(self.enums.itervalues()):
674                code('  case ${{self.c_ident}}_${{enum.ident}}:')
675                code('    return $i;')
676            code.dedent()
677
678            # total num
679            code('''
680      case ${{self.c_ident}}_NUM:
681        return ${{len(self.enums)}};
682
683      default:
684        panic("Invalid range for type ${{self.c_ident}}");
685    }
686}
687
688/** \\brief returns the machine type for each base vector index used by NetDest
689 *
690 * \\return the MachineType
691 */
692MachineType
693${{self.c_ident}}_from_base_level(int type)
694{
695    switch(type) {
696''')
697
698            # For each field
699            code.indent()
700            for i,enum in enumerate(self.enums.itervalues()):
701                code('  case $i:')
702                code('    return ${{self.c_ident}}_${{enum.ident}};')
703            code.dedent()
704
705            # Trailer
706            code('''
707      default:
708        panic("Invalid range for type ${{self.c_ident}}");
709    }
710}
711
712/** \\brief The return value indicates the number of components created
713 * before a particular machine\'s components
714 *
715 * \\return the base number of components for each machine
716 */
717int
718${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
719{
720    int base = 0;
721    switch(obj) {
722''')
723
724            # For each field
725            code.indent()
726            code('  case ${{self.c_ident}}_NUM:')
727            for enum in reversed(self.enums.values()):
728                # Check if there is a defined machine with this type
729                if enum.primary:
730                    code('    base += ${{enum.ident}}_Controller::getNumControllers();')
731                else:
732                    code('    base += 0;')
733                code('    M5_FALLTHROUGH;')
734                code('  case ${{self.c_ident}}_${{enum.ident}}:')
735            code('    break;')
736            code.dedent()
737
738            code('''
739      default:
740        panic("Invalid range for type ${{self.c_ident}}");
741    }
742
743    return base;
744}
745
746/** \\brief returns the total number of components for each machine
747 * \\return the total number of components for each machine
748 */
749int
750${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
751{
752    switch(obj) {
753''')
754
755            # For each field
756            for enum in self.enums.itervalues():
757                code('case ${{self.c_ident}}_${{enum.ident}}:')
758                if enum.primary:
759                    code('return ${{enum.ident}}_Controller::getNumControllers();')
760                else:
761                    code('return 0;')
762
763            # total num
764            code('''
765      case ${{self.c_ident}}_NUM:
766      default:
767        panic("Invalid range for type ${{self.c_ident}}");
768    }
769}
770''')
771
772            for enum in self.enums.itervalues():
773                code('''
774
775MachineID
776get${{enum.ident}}MachineID(NodeID RubyNode)
777{
778      MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
779      return mach;
780}
781''')
782
783        # Write the file
784        code.write(path, "%s.cc" % self.c_ident)
785
786__all__ = [ "Type" ]
787