Type.py revision 9508
16657Snate@binkert.org# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
26657Snate@binkert.org# Copyright (c) 2009 The Hewlett-Packard Development Company
36657Snate@binkert.org# All rights reserved.
46657Snate@binkert.org#
56657Snate@binkert.org# Redistribution and use in source and binary forms, with or without
66657Snate@binkert.org# modification, are permitted provided that the following conditions are
76657Snate@binkert.org# met: redistributions of source code must retain the above copyright
86657Snate@binkert.org# notice, this list of conditions and the following disclaimer;
96657Snate@binkert.org# redistributions in binary form must reproduce the above copyright
106657Snate@binkert.org# notice, this list of conditions and the following disclaimer in the
116657Snate@binkert.org# documentation and/or other materials provided with the distribution;
126657Snate@binkert.org# neither the name of the copyright holders nor the names of its
136657Snate@binkert.org# contributors may be used to endorse or promote products derived from
146657Snate@binkert.org# this software without specific prior written permission.
156657Snate@binkert.org#
166657Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176657Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186657Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196657Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206657Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216657Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226657Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236657Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246657Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256657Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266657Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276657Snate@binkert.org
286999Snate@binkert.orgfrom m5.util import orderdict
296657Snate@binkert.org
306657Snate@binkert.orgfrom slicc.util import PairContainer
316657Snate@binkert.orgfrom slicc.symbols.Symbol import Symbol
329302Snilay@cs.wisc.edufrom slicc.symbols.Var import Var
336657Snate@binkert.org
346657Snate@binkert.orgclass DataMember(PairContainer):
356657Snate@binkert.org    def __init__(self, ident, type, pairs, init_code):
366657Snate@binkert.org        super(DataMember, self).__init__(pairs)
376657Snate@binkert.org        self.ident = ident
386657Snate@binkert.org        self.type = type
396657Snate@binkert.org        self.init_code = init_code
406657Snate@binkert.org
416657Snate@binkert.orgclass Enumeration(PairContainer):
426657Snate@binkert.org    def __init__(self, ident, pairs):
436657Snate@binkert.org        super(Enumeration, self).__init__(pairs)
446657Snate@binkert.org        self.ident = ident
456657Snate@binkert.org
466657Snate@binkert.orgclass Method(object):
476657Snate@binkert.org    def __init__(self, return_type, param_types):
486657Snate@binkert.org        self.return_type = return_type
496657Snate@binkert.org        self.param_types = param_types
506657Snate@binkert.org
516657Snate@binkert.orgclass Type(Symbol):
526657Snate@binkert.org    def __init__(self, table, ident, location, pairs, machine=None):
536657Snate@binkert.org        super(Type, self).__init__(table, ident, location, pairs)
546657Snate@binkert.org        self.c_ident = ident
556882SBrad.Beckmann@amd.com        self.abstract_ident = ""
566657Snate@binkert.org        if machine:
576657Snate@binkert.org            if self.isExternal or self.isPrimitive:
586657Snate@binkert.org                if "external_name" in self:
596657Snate@binkert.org                    self.c_ident = self["external_name"]
606657Snate@binkert.org            else:
616657Snate@binkert.org                # Append with machine name
626657Snate@binkert.org                self.c_ident = "%s_%s" % (machine, ident)
636657Snate@binkert.org
646657Snate@binkert.org        self.pairs.setdefault("desc", "No description avaliable")
656657Snate@binkert.org
666657Snate@binkert.org        # check for interface that this Type implements
676657Snate@binkert.org        if "interface" in self:
686657Snate@binkert.org            interface = self["interface"]
696657Snate@binkert.org            if interface in ("Message", "NetworkMessage"):
706657Snate@binkert.org                self["message"] = "yes"
716657Snate@binkert.org            if interface == "NetworkMessage":
726657Snate@binkert.org                self["networkmessage"] = "yes"
736657Snate@binkert.org
746657Snate@binkert.org        # FIXME - all of the following id comparisons are fragile hacks
756657Snate@binkert.org        if self.ident in ("CacheMemory", "NewCacheMemory",
766657Snate@binkert.org                          "TLCCacheMemory", "DNUCACacheMemory",
776657Snate@binkert.org                          "DNUCABankCacheMemory", "L2BankCacheMemory",
786657Snate@binkert.org                          "CompressedCacheMemory", "PrefetchCacheMemory"):
796657Snate@binkert.org            self["cache"] = "yes"
806657Snate@binkert.org
816657Snate@binkert.org        if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
826657Snate@binkert.org            self["tbe"] = "yes"
836657Snate@binkert.org
846657Snate@binkert.org        if self.ident == "NewTBETable":
856657Snate@binkert.org            self["newtbe"] = "yes"
866657Snate@binkert.org
876657Snate@binkert.org        if self.ident == "TimerTable":
886657Snate@binkert.org            self["timer"] = "yes"
896657Snate@binkert.org
906657Snate@binkert.org        if self.ident == "DirectoryMemory":
916657Snate@binkert.org            self["dir"] = "yes"
926657Snate@binkert.org
936657Snate@binkert.org        if self.ident == "PersistentTable":
946657Snate@binkert.org            self["persistent"] = "yes"
956657Snate@binkert.org
966657Snate@binkert.org        if self.ident == "Prefetcher":
976657Snate@binkert.org            self["prefetcher"] = "yes"
986657Snate@binkert.org
996657Snate@binkert.org        if self.ident == "DNUCA_Movement":
1006657Snate@binkert.org            self["mover"] = "yes"
1016657Snate@binkert.org
1026657Snate@binkert.org        self.isMachineType = (ident == "MachineType")
1036657Snate@binkert.org
1048086SBrad.Beckmann@amd.com        self.isStateDecl = ("state_decl" in self)
1058086SBrad.Beckmann@amd.com        self.statePermPairs = []
1068086SBrad.Beckmann@amd.com
1076657Snate@binkert.org        self.data_members = orderdict()
1086657Snate@binkert.org
1096657Snate@binkert.org        # Methods
1106657Snate@binkert.org        self.methods = {}
1119298Snilay@cs.wisc.edu        self.functions = {}
1126657Snate@binkert.org
1136657Snate@binkert.org        # Enums
1146657Snate@binkert.org        self.enums = orderdict()
1156657Snate@binkert.org
1166657Snate@binkert.org    @property
1176657Snate@binkert.org    def isPrimitive(self):
1186657Snate@binkert.org        return "primitive" in self
1196657Snate@binkert.org    @property
1206657Snate@binkert.org    def isNetworkMessage(self):
1216657Snate@binkert.org        return "networkmessage" in self
1226657Snate@binkert.org    @property
1236657Snate@binkert.org    def isMessage(self):
1246657Snate@binkert.org        return "message" in self
1256657Snate@binkert.org    @property
1266657Snate@binkert.org    def isBuffer(self):
1276657Snate@binkert.org        return "buffer" in self
1286657Snate@binkert.org    @property
1296657Snate@binkert.org    def isInPort(self):
1306657Snate@binkert.org        return "inport" in self
1316657Snate@binkert.org    @property
1326657Snate@binkert.org    def isOutPort(self):
1336657Snate@binkert.org        return "outport" in self
1346657Snate@binkert.org    @property
1356657Snate@binkert.org    def isEnumeration(self):
1366657Snate@binkert.org        return "enumeration" in self
1376657Snate@binkert.org    @property
1386657Snate@binkert.org    def isExternal(self):
1396657Snate@binkert.org        return "external" in self
1406657Snate@binkert.org    @property
1416657Snate@binkert.org    def isGlobal(self):
1426657Snate@binkert.org        return "global" in self
1436657Snate@binkert.org    @property
1446657Snate@binkert.org    def isInterface(self):
1456657Snate@binkert.org        return "interface" in self
1466657Snate@binkert.org
1476657Snate@binkert.org    # Return false on error
1489298Snilay@cs.wisc.edu    def addDataMember(self, ident, type, pairs, init_code):
1496657Snate@binkert.org        if ident in self.data_members:
1506657Snate@binkert.org            return False
1516657Snate@binkert.org
1526657Snate@binkert.org        member = DataMember(ident, type, pairs, init_code)
1536657Snate@binkert.org        self.data_members[ident] = member
1546657Snate@binkert.org
1559302Snilay@cs.wisc.edu        var = Var(self.symtab, ident, self.location, type,
1569302Snilay@cs.wisc.edu                "m_%s" % ident, {}, None)
1579302Snilay@cs.wisc.edu        self.symtab.registerSym(ident, var)
1586657Snate@binkert.org        return True
1596657Snate@binkert.org
1606657Snate@binkert.org    def dataMemberType(self, ident):
1616657Snate@binkert.org        return self.data_members[ident].type
1626657Snate@binkert.org
1636657Snate@binkert.org    def methodId(self, name, param_type_vec):
1646657Snate@binkert.org        return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
1656657Snate@binkert.org
1666882SBrad.Beckmann@amd.com    def methodIdAbstract(self, name, param_type_vec):
1676882SBrad.Beckmann@amd.com        return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
1686882SBrad.Beckmann@amd.com
1698086SBrad.Beckmann@amd.com    def statePermPairAdd(self, state_name, perm_name):
1708086SBrad.Beckmann@amd.com        self.statePermPairs.append([state_name, perm_name])
1718086SBrad.Beckmann@amd.com
1729298Snilay@cs.wisc.edu    def addMethod(self, name, return_type, param_type_vec):
1736657Snate@binkert.org        ident = self.methodId(name, param_type_vec)
1746657Snate@binkert.org        if ident in self.methods:
1756657Snate@binkert.org            return False
1766657Snate@binkert.org
1776657Snate@binkert.org        self.methods[ident] = Method(return_type, param_type_vec)
1786657Snate@binkert.org        return True
1796657Snate@binkert.org
1809298Snilay@cs.wisc.edu    # Ideally either this function or the one above should exist. But
1819298Snilay@cs.wisc.edu    # methods and functions have different structures right now.
1829298Snilay@cs.wisc.edu    # Hence, these are different, at least for the time being.
1839298Snilay@cs.wisc.edu    def addFunc(self, func):
1849298Snilay@cs.wisc.edu        ident = self.methodId(func.ident, func.param_types)
1859298Snilay@cs.wisc.edu        if ident in self.functions:
1869298Snilay@cs.wisc.edu            return False
1879298Snilay@cs.wisc.edu
1889298Snilay@cs.wisc.edu        self.functions[ident] = func
1899298Snilay@cs.wisc.edu        return True
1909298Snilay@cs.wisc.edu
1919298Snilay@cs.wisc.edu    def addEnum(self, ident, pairs):
1926657Snate@binkert.org        if ident in self.enums:
1936657Snate@binkert.org            return False
1946657Snate@binkert.org
1956657Snate@binkert.org        self.enums[ident] = Enumeration(ident, pairs)
1966657Snate@binkert.org
1976657Snate@binkert.org        # Add default
1986657Snate@binkert.org        if "default" not in self:
1996657Snate@binkert.org            self["default"] = "%s_NUM" % self.c_ident
2006657Snate@binkert.org
2016657Snate@binkert.org        return True
2026657Snate@binkert.org
2039219Spower.jg@gmail.com    def writeCodeFiles(self, path, includes):
2046657Snate@binkert.org        if self.isExternal:
2056657Snate@binkert.org            # Do nothing
2066657Snate@binkert.org            pass
2076657Snate@binkert.org        elif self.isEnumeration:
2086657Snate@binkert.org            self.printEnumHH(path)
2096657Snate@binkert.org            self.printEnumCC(path)
2106657Snate@binkert.org        else:
2116657Snate@binkert.org            # User defined structs and messages
2126657Snate@binkert.org            self.printTypeHH(path)
2136657Snate@binkert.org            self.printTypeCC(path)
2146657Snate@binkert.org
2156657Snate@binkert.org    def printTypeHH(self, path):
2166999Snate@binkert.org        code = self.symtab.codeFormatter()
2176657Snate@binkert.org        code('''
2186657Snate@binkert.org/** \\file ${{self.c_ident}}.hh
2196657Snate@binkert.org *
2206657Snate@binkert.org *
2216657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
2226657Snate@binkert.org */
2236657Snate@binkert.org
2247007Snate@binkert.org#ifndef __${{self.c_ident}}_HH__
2257007Snate@binkert.org#define __${{self.c_ident}}_HH__
2266657Snate@binkert.org
2277002Snate@binkert.org#include <iostream>
2287002Snate@binkert.org
2299466Snilay@cs.wisc.edu#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
2306657Snate@binkert.org''')
2316657Snate@binkert.org
2326657Snate@binkert.org        for dm in self.data_members.values():
2336657Snate@binkert.org            if not dm.type.isPrimitive:
2346657Snate@binkert.org                code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
2356657Snate@binkert.org
2366657Snate@binkert.org        parent = ""
2376657Snate@binkert.org        if "interface" in self:
2386657Snate@binkert.org            code('#include "mem/protocol/$0.hh"', self["interface"])
2396657Snate@binkert.org            parent = " :  public %s" % self["interface"]
2406657Snate@binkert.org
2416657Snate@binkert.org        code('''
2427007Snate@binkert.org$klass ${{self.c_ident}}$parent
2437007Snate@binkert.org{
2446657Snate@binkert.org  public:
2459466Snilay@cs.wisc.edu    ${{self.c_ident}}
2466657Snate@binkert.org''', klass="class")
2476657Snate@binkert.org
2489466Snilay@cs.wisc.edu        if self.isMessage:
2499508Snilay@cs.wisc.edu            code('(Tick curTime) : %s(curTime) {' % self["interface"])
2509466Snilay@cs.wisc.edu        else:
2519466Snilay@cs.wisc.edu            code('()\n\t\t{')
2529466Snilay@cs.wisc.edu
2536657Snate@binkert.org        code.indent()
2546657Snate@binkert.org        if not self.isGlobal:
2556657Snate@binkert.org            code.indent()
2566657Snate@binkert.org            for dm in self.data_members.values():
2576657Snate@binkert.org                ident = dm.ident
2586657Snate@binkert.org                if "default" in dm:
2596657Snate@binkert.org                    # look for default value
2606657Snate@binkert.org                    code('m_$ident = ${{dm["default"]}}; // default for this field')
2616657Snate@binkert.org                elif "default" in dm.type:
2626657Snate@binkert.org                    # Look for the type default
2636657Snate@binkert.org                    tid = dm.type.c_ident
2646657Snate@binkert.org                    code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
2656657Snate@binkert.org                else:
2666657Snate@binkert.org                    code('// m_$ident has no default')
2676657Snate@binkert.org            code.dedent()
2686657Snate@binkert.org        code('}')
2696657Snate@binkert.org
2707453Snate@binkert.org        # ******** Copy constructor ********
2717453Snate@binkert.org        if not self.isGlobal:
2727453Snate@binkert.org            code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
2737453Snate@binkert.org
2747453Snate@binkert.org            # Call superclass constructor
2757453Snate@binkert.org            if "interface" in self:
2767453Snate@binkert.org                code('    : ${{self["interface"]}}(other)')
2777453Snate@binkert.org
2787453Snate@binkert.org            code('{')
2797453Snate@binkert.org            code.indent()
2807453Snate@binkert.org
2817453Snate@binkert.org            for dm in self.data_members.values():
2827453Snate@binkert.org                code('m_${{dm.ident}} = other.m_${{dm.ident}};')
2837453Snate@binkert.org
2847453Snate@binkert.org            code.dedent()
2857453Snate@binkert.org            code('}')
2867453Snate@binkert.org
2876657Snate@binkert.org        # ******** Full init constructor ********
2886657Snate@binkert.org        if not self.isGlobal:
2896657Snate@binkert.org            params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
2906657Snate@binkert.org                       for dm in self.data_members.itervalues() ]
2919466Snilay@cs.wisc.edu            params = ', '.join(params)
2926657Snate@binkert.org
2939466Snilay@cs.wisc.edu            if self.isMessage:
2949508Snilay@cs.wisc.edu                params = "const Tick curTime, " + params
2959466Snilay@cs.wisc.edu
2966657Snate@binkert.org            code('${{self.c_ident}}($params)')
2976657Snate@binkert.org
2986657Snate@binkert.org            # Call superclass constructor
2996657Snate@binkert.org            if "interface" in self:
3009466Snilay@cs.wisc.edu                if self.isMessage:
3019466Snilay@cs.wisc.edu                    code('    : ${{self["interface"]}}(curTime)')
3029466Snilay@cs.wisc.edu                else:
3039466Snilay@cs.wisc.edu                    code('    : ${{self["interface"]}}()')
3046657Snate@binkert.org
3056657Snate@binkert.org            code('{')
3066657Snate@binkert.org            code.indent()
3076657Snate@binkert.org            for dm in self.data_members.values():
3086657Snate@binkert.org                code('m_${{dm.ident}} = local_${{dm.ident}};')
3096657Snate@binkert.org                if "nextLineCallHack" in dm:
3106657Snate@binkert.org                    code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
3116657Snate@binkert.org
3126657Snate@binkert.org            code.dedent()
3136657Snate@binkert.org            code('}')
3146657Snate@binkert.org
3159466Snilay@cs.wisc.edu        # create a clone member
3167453Snate@binkert.org        code('''
3177453Snate@binkert.org${{self.c_ident}}*
3187007Snate@binkert.orgclone() const
3197007Snate@binkert.org{
3207453Snate@binkert.org     return new ${{self.c_ident}}(*this);
3217007Snate@binkert.org}
3226657Snate@binkert.org''')
3236657Snate@binkert.org
3246657Snate@binkert.org        if not self.isGlobal:
3256657Snate@binkert.org            # const Get methods for each field
3266657Snate@binkert.org            code('// Const accessors methods for each field')
3276657Snate@binkert.org            for dm in self.data_members.values():
3286657Snate@binkert.org                code('''
3296657Snate@binkert.org/** \\brief Const accessor method for ${{dm.ident}} field.
3306657Snate@binkert.org *  \\return ${{dm.ident}} field
3316657Snate@binkert.org */
3327007Snate@binkert.orgconst ${{dm.type.c_ident}}&
3337007Snate@binkert.orgget${{dm.ident}}() const
3347007Snate@binkert.org{
3357007Snate@binkert.org    return m_${{dm.ident}};
3367007Snate@binkert.org}
3376657Snate@binkert.org''')
3386657Snate@binkert.org
3396657Snate@binkert.org            # Non-const Get methods for each field
3406657Snate@binkert.org            code('// Non const Accessors methods for each field')
3416657Snate@binkert.org            for dm in self.data_members.values():
3426657Snate@binkert.org                code('''
3436657Snate@binkert.org/** \\brief Non-const accessor method for ${{dm.ident}} field.
3446657Snate@binkert.org *  \\return ${{dm.ident}} field
3456657Snate@binkert.org */
3467007Snate@binkert.org${{dm.type.c_ident}}&
3477007Snate@binkert.orgget${{dm.ident}}()
3487007Snate@binkert.org{
3497007Snate@binkert.org    return m_${{dm.ident}};
3507007Snate@binkert.org}
3516657Snate@binkert.org''')
3526657Snate@binkert.org
3536657Snate@binkert.org            #Set methods for each field
3546657Snate@binkert.org            code('// Mutator methods for each field')
3556657Snate@binkert.org            for dm in self.data_members.values():
3566657Snate@binkert.org                code('''
3576657Snate@binkert.org/** \\brief Mutator method for ${{dm.ident}} field */
3587007Snate@binkert.orgvoid
3597007Snate@binkert.orgset${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
3607007Snate@binkert.org{
3617007Snate@binkert.org    m_${{dm.ident}} = local_${{dm.ident}};
3627007Snate@binkert.org}
3636657Snate@binkert.org''')
3646657Snate@binkert.org
3657002Snate@binkert.org        code('void print(std::ostream& out) const;')
3666657Snate@binkert.org        code.dedent()
3676657Snate@binkert.org        code('  //private:')
3686657Snate@binkert.org        code.indent()
3696657Snate@binkert.org
3706657Snate@binkert.org        # Data members for each field
3716657Snate@binkert.org        for dm in self.data_members.values():
3726657Snate@binkert.org            if "abstract" not in dm:
3736657Snate@binkert.org                const = ""
3746657Snate@binkert.org                init = ""
3756657Snate@binkert.org
3766657Snate@binkert.org                # global structure
3776657Snate@binkert.org                if self.isGlobal:
3786657Snate@binkert.org                    const = "static const "
3796657Snate@binkert.org
3806657Snate@binkert.org                # init value
3816657Snate@binkert.org                if dm.init_code:
3826657Snate@binkert.org                    # only global structure can have init value here
3836657Snate@binkert.org                    assert self.isGlobal
3846657Snate@binkert.org                    init = " = %s" % (dm.init_code)
3856657Snate@binkert.org
3866657Snate@binkert.org                if "desc" in dm:
3877007Snate@binkert.org                    code('/** ${{dm["desc"]}} */')
3886657Snate@binkert.org
3897007Snate@binkert.org                code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
3906657Snate@binkert.org
3919298Snilay@cs.wisc.edu        # Prototypes for functions defined for the Type
3929298Snilay@cs.wisc.edu        for item in self.functions:
3939298Snilay@cs.wisc.edu            proto = self.functions[item].prototype
3949298Snilay@cs.wisc.edu            if proto:
3959298Snilay@cs.wisc.edu                code('$proto')
3969298Snilay@cs.wisc.edu
3976657Snate@binkert.org        code.dedent()
3986657Snate@binkert.org        code('};')
3996657Snate@binkert.org
4006657Snate@binkert.org        code('''
4017055Snate@binkert.orginline std::ostream&
4027007Snate@binkert.orgoperator<<(std::ostream& out, const ${{self.c_ident}}& obj)
4036657Snate@binkert.org{
4046657Snate@binkert.org    obj.print(out);
4057002Snate@binkert.org    out << std::flush;
4066657Snate@binkert.org    return out;
4076657Snate@binkert.org}
4086657Snate@binkert.org
4097007Snate@binkert.org#endif // __${{self.c_ident}}_HH__
4106657Snate@binkert.org''')
4116657Snate@binkert.org
4126657Snate@binkert.org        code.write(path, "%s.hh" % self.c_ident)
4136657Snate@binkert.org
4146657Snate@binkert.org    def printTypeCC(self, path):
4156999Snate@binkert.org        code = self.symtab.codeFormatter()
4166657Snate@binkert.org
4176657Snate@binkert.org        code('''
4186657Snate@binkert.org/** \\file ${{self.c_ident}}.cc
4196657Snate@binkert.org *
4206657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
4216657Snate@binkert.org */
4226657Snate@binkert.org
4237002Snate@binkert.org#include <iostream>
4247002Snate@binkert.org
4256657Snate@binkert.org#include "mem/protocol/${{self.c_ident}}.hh"
4269499Snilay@cs.wisc.edu#include "mem/ruby/common/Global.hh"
4279499Snilay@cs.wisc.edu#include "mem/ruby/system/System.hh"
4287002Snate@binkert.org
4297002Snate@binkert.orgusing namespace std;
4306657Snate@binkert.org''')
4316657Snate@binkert.org
4326657Snate@binkert.org        code('''
4336657Snate@binkert.org/** \\brief Print the state of this object */
4347007Snate@binkert.orgvoid
4357007Snate@binkert.org${{self.c_ident}}::print(ostream& out) const
4366657Snate@binkert.org{
4376657Snate@binkert.org    out << "[${{self.c_ident}}: ";
4386657Snate@binkert.org''')
4396657Snate@binkert.org
4406657Snate@binkert.org        # For each field
4416657Snate@binkert.org        code.indent()
4426657Snate@binkert.org        for dm in self.data_members.values():
4436657Snate@binkert.org            code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
4446657Snate@binkert.org
4456657Snate@binkert.org        if self.isMessage:
4469206Snilay@cs.wisc.edu            code('out << "Time = " << g_system_ptr->clockPeriod() * getTime() << " ";')
4476657Snate@binkert.org        code.dedent()
4486657Snate@binkert.org
4496657Snate@binkert.org        # Trailer
4506657Snate@binkert.org        code('''
4516657Snate@binkert.org    out << "]";
4526657Snate@binkert.org}''')
4536657Snate@binkert.org
4549298Snilay@cs.wisc.edu        # print the code for the functions in the type
4559298Snilay@cs.wisc.edu        for item in self.functions:
4569298Snilay@cs.wisc.edu            code(self.functions[item].generateCode())
4579298Snilay@cs.wisc.edu
4586657Snate@binkert.org        code.write(path, "%s.cc" % self.c_ident)
4596657Snate@binkert.org
4606657Snate@binkert.org    def printEnumHH(self, path):
4616999Snate@binkert.org        code = self.symtab.codeFormatter()
4626657Snate@binkert.org        code('''
4636657Snate@binkert.org/** \\file ${{self.c_ident}}.hh
4646657Snate@binkert.org *
4656657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
4666657Snate@binkert.org */
4677007Snate@binkert.org
4687007Snate@binkert.org#ifndef __${{self.c_ident}}_HH__
4697007Snate@binkert.org#define __${{self.c_ident}}_HH__
4706657Snate@binkert.org
4717002Snate@binkert.org#include <iostream>
4727002Snate@binkert.org#include <string>
4737002Snate@binkert.org
4748086SBrad.Beckmann@amd.com''')
4758086SBrad.Beckmann@amd.com        if self.isStateDecl:
4768086SBrad.Beckmann@amd.com            code('#include "mem/protocol/AccessPermission.hh"')
4778086SBrad.Beckmann@amd.com
4788602Snilay@cs.wisc.edu        if self.isMachineType:
4798602Snilay@cs.wisc.edu            code('#include "base/misc.hh"')
4808602Snilay@cs.wisc.edu            code('#include "mem/protocol/GenericMachineType.hh"')
4818602Snilay@cs.wisc.edu            code('#include "mem/ruby/common/Address.hh"')
4828602Snilay@cs.wisc.edu            code('struct MachineID;')
4838602Snilay@cs.wisc.edu
4848086SBrad.Beckmann@amd.com        code('''
4856657Snate@binkert.org
4867007Snate@binkert.org// Class definition
4876657Snate@binkert.org/** \\enum ${{self.c_ident}}
4886657Snate@binkert.org *  \\brief ${{self.desc}}
4896657Snate@binkert.org */
4906657Snate@binkert.orgenum ${{self.c_ident}} {
4916657Snate@binkert.org    ${{self.c_ident}}_FIRST,
4926657Snate@binkert.org''')
4936657Snate@binkert.org
4946657Snate@binkert.org        code.indent()
4956657Snate@binkert.org        # For each field
4966657Snate@binkert.org        for i,(ident,enum) in enumerate(self.enums.iteritems()):
4976657Snate@binkert.org            desc = enum.get("desc", "No description avaliable")
4986862Sdrh5@cs.wisc.edu            if i == 0:
4996862Sdrh5@cs.wisc.edu                init = ' = %s_FIRST' % self.c_ident
5006862Sdrh5@cs.wisc.edu            else:
5016862Sdrh5@cs.wisc.edu                init = ''
5026657Snate@binkert.org            code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
5036657Snate@binkert.org        code.dedent()
5046657Snate@binkert.org        code('''
5056657Snate@binkert.org    ${{self.c_ident}}_NUM
5066657Snate@binkert.org};
5077007Snate@binkert.org
5087007Snate@binkert.org// Code to convert from a string to the enumeration
5097002Snate@binkert.org${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
5107007Snate@binkert.org
5117007Snate@binkert.org// Code to convert state to a string
5127002Snate@binkert.orgstd::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
5137007Snate@binkert.org
5147007Snate@binkert.org// Code to increment an enumeration type
5156657Snate@binkert.org${{self.c_ident}} &operator++(${{self.c_ident}} &e);
5166657Snate@binkert.org''')
5176657Snate@binkert.org
5186657Snate@binkert.org        # MachineType hack used to set the base component id for each Machine
5196657Snate@binkert.org        if self.isMachineType:
5206657Snate@binkert.org            code('''
5216657Snate@binkert.orgint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
5226657Snate@binkert.orgMachineType ${{self.c_ident}}_from_base_level(int);
5236657Snate@binkert.orgint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
5246657Snate@binkert.orgint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
5256657Snate@binkert.org''')
5266657Snate@binkert.org
5276657Snate@binkert.org            for enum in self.enums.itervalues():
5288602Snilay@cs.wisc.edu                if enum.ident == "DMA":
5298602Snilay@cs.wisc.edu                    code('''
5308602Snilay@cs.wisc.eduMachineID map_Address_to_DMA(const Address &addr);
5318602Snilay@cs.wisc.edu''')
5328602Snilay@cs.wisc.edu                code('''
5338602Snilay@cs.wisc.edu
5348602Snilay@cs.wisc.eduMachineID get${{enum.ident}}MachineID(NodeID RubyNode);
5358602Snilay@cs.wisc.edu''')
5368602Snilay@cs.wisc.edu
5378602Snilay@cs.wisc.edu            code('''
5388602Snilay@cs.wisc.eduinline GenericMachineType
5398602Snilay@cs.wisc.eduConvertMachToGenericMach(MachineType machType)
5408602Snilay@cs.wisc.edu{
5418602Snilay@cs.wisc.edu''')
5428602Snilay@cs.wisc.edu            for enum in self.enums.itervalues():
5438602Snilay@cs.wisc.edu                code('''
5448602Snilay@cs.wisc.edu      if (machType == MachineType_${{enum.ident}})
5458602Snilay@cs.wisc.edu          return GenericMachineType_${{enum.ident}};
5468602Snilay@cs.wisc.edu''')
5478602Snilay@cs.wisc.edu            code('''
5488602Snilay@cs.wisc.edu      panic("cannot convert to a GenericMachineType");
5498602Snilay@cs.wisc.edu}
5508602Snilay@cs.wisc.edu''')
5516657Snate@binkert.org
5528086SBrad.Beckmann@amd.com        if self.isStateDecl:
5538086SBrad.Beckmann@amd.com            code('''
5548086SBrad.Beckmann@amd.com
5558086SBrad.Beckmann@amd.com// Code to convert the current state to an access permission
5568086SBrad.Beckmann@amd.comAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
5578086SBrad.Beckmann@amd.com
5588086SBrad.Beckmann@amd.com''')
5598086SBrad.Beckmann@amd.com
5606657Snate@binkert.org        # Trailer
5616657Snate@binkert.org        code('''
5627002Snate@binkert.orgstd::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
5636657Snate@binkert.org
5647007Snate@binkert.org#endif // __${{self.c_ident}}_HH__
5656657Snate@binkert.org''')
5666657Snate@binkert.org
5676657Snate@binkert.org        code.write(path, "%s.hh" % self.c_ident)
5686657Snate@binkert.org
5696657Snate@binkert.org    def printEnumCC(self, path):
5706999Snate@binkert.org        code = self.symtab.codeFormatter()
5716657Snate@binkert.org        code('''
5726657Snate@binkert.org/** \\file ${{self.c_ident}}.hh
5736657Snate@binkert.org *
5746657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
5756657Snate@binkert.org */
5766657Snate@binkert.org
5777832Snate@binkert.org#include <cassert>
5787002Snate@binkert.org#include <iostream>
5797002Snate@binkert.org#include <string>
5807002Snate@binkert.org
5817805Snilay@cs.wisc.edu#include "base/misc.hh"
5826657Snate@binkert.org#include "mem/protocol/${{self.c_ident}}.hh"
5836657Snate@binkert.org
5847002Snate@binkert.orgusing namespace std;
5857002Snate@binkert.org
5866657Snate@binkert.org''')
5876657Snate@binkert.org
5888086SBrad.Beckmann@amd.com        if self.isStateDecl:
5898086SBrad.Beckmann@amd.com            code('''
5908086SBrad.Beckmann@amd.com// Code to convert the current state to an access permission
5918086SBrad.Beckmann@amd.comAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
5928086SBrad.Beckmann@amd.com{
5938086SBrad.Beckmann@amd.com    switch(obj) {
5948086SBrad.Beckmann@amd.com''')
5958086SBrad.Beckmann@amd.com            # For each case
5968086SBrad.Beckmann@amd.com            code.indent()
5978086SBrad.Beckmann@amd.com            for statePerm in self.statePermPairs:
5988086SBrad.Beckmann@amd.com                code('  case ${{self.c_ident}}_${{statePerm[0]}}:')
5998086SBrad.Beckmann@amd.com                code('    return AccessPermission_${{statePerm[1]}};')
6008086SBrad.Beckmann@amd.com            code.dedent()
6018086SBrad.Beckmann@amd.com            code ('''
6028086SBrad.Beckmann@amd.com      default:
6038086SBrad.Beckmann@amd.com        panic("Unknown state access permission converstion for ${{self.c_ident}}");
6048086SBrad.Beckmann@amd.com    }
6058086SBrad.Beckmann@amd.com}
6068086SBrad.Beckmann@amd.com
6078086SBrad.Beckmann@amd.com''')
6088086SBrad.Beckmann@amd.com
6096657Snate@binkert.org        if self.isMachineType:
6106657Snate@binkert.org            for enum in self.enums.itervalues():
6116657Snate@binkert.org                code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
6128602Snilay@cs.wisc.edu            code('#include "mem/ruby/system/MachineID.hh"')
6136657Snate@binkert.org
6146657Snate@binkert.org        code('''
6157007Snate@binkert.org// Code for output operator
6167007Snate@binkert.orgostream&
6177007Snate@binkert.orgoperator<<(ostream& out, const ${{self.c_ident}}& obj)
6186657Snate@binkert.org{
6196657Snate@binkert.org    out << ${{self.c_ident}}_to_string(obj);
6206657Snate@binkert.org    out << flush;
6216657Snate@binkert.org    return out;
6226657Snate@binkert.org}
6236657Snate@binkert.org
6247007Snate@binkert.org// Code to convert state to a string
6257007Snate@binkert.orgstring
6267007Snate@binkert.org${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
6276657Snate@binkert.org{
6286657Snate@binkert.org    switch(obj) {
6296657Snate@binkert.org''')
6306657Snate@binkert.org
6316657Snate@binkert.org        # For each field
6326657Snate@binkert.org        code.indent()
6336657Snate@binkert.org        for enum in self.enums.itervalues():
6346657Snate@binkert.org            code('  case ${{self.c_ident}}_${{enum.ident}}:')
6356657Snate@binkert.org            code('    return "${{enum.ident}}";')
6366657Snate@binkert.org        code.dedent()
6376657Snate@binkert.org
6386657Snate@binkert.org        # Trailer
6396657Snate@binkert.org        code('''
6406657Snate@binkert.org      default:
6417805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
6426657Snate@binkert.org    }
6436657Snate@binkert.org}
6446657Snate@binkert.org
6457007Snate@binkert.org// Code to convert from a string to the enumeration
6467007Snate@binkert.org${{self.c_ident}}
6477007Snate@binkert.orgstring_to_${{self.c_ident}}(const string& str)
6486657Snate@binkert.org{
6496657Snate@binkert.org''')
6506657Snate@binkert.org
6516657Snate@binkert.org        # For each field
6527007Snate@binkert.org        start = ""
6536657Snate@binkert.org        code.indent()
6546657Snate@binkert.org        for enum in self.enums.itervalues():
6556657Snate@binkert.org            code('${start}if (str == "${{enum.ident}}") {')
6566657Snate@binkert.org            code('    return ${{self.c_ident}}_${{enum.ident}};')
6577007Snate@binkert.org            start = "} else "
6586657Snate@binkert.org        code.dedent()
6596657Snate@binkert.org
6606657Snate@binkert.org        code('''
6616657Snate@binkert.org    } else {
6627805Snilay@cs.wisc.edu        panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
6636657Snate@binkert.org    }
6646657Snate@binkert.org}
6656657Snate@binkert.org
6667007Snate@binkert.org// Code to increment an enumeration type
6677007Snate@binkert.org${{self.c_ident}}&
6687007Snate@binkert.orgoperator++(${{self.c_ident}}& e)
6697007Snate@binkert.org{
6706657Snate@binkert.org    assert(e < ${{self.c_ident}}_NUM);
6716657Snate@binkert.org    return e = ${{self.c_ident}}(e+1);
6726657Snate@binkert.org}
6736657Snate@binkert.org''')
6746657Snate@binkert.org
6756657Snate@binkert.org        # MachineType hack used to set the base level and number of
6766657Snate@binkert.org        # components for each Machine
6776657Snate@binkert.org        if self.isMachineType:
6786657Snate@binkert.org            code('''
6797007Snate@binkert.org/** \\brief returns the base vector index for each machine type to be
6807007Snate@binkert.org  * used by NetDest
6816657Snate@binkert.org  *
6826657Snate@binkert.org  * \\return the base vector index for each machine type to be used by NetDest
6836657Snate@binkert.org  * \\see NetDest.hh
6846657Snate@binkert.org  */
6857007Snate@binkert.orgint
6867007Snate@binkert.org${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
6876657Snate@binkert.org{
6886657Snate@binkert.org    switch(obj) {
6896657Snate@binkert.org''')
6906657Snate@binkert.org
6916657Snate@binkert.org            # For each field
6926657Snate@binkert.org            code.indent()
6936657Snate@binkert.org            for i,enum in enumerate(self.enums.itervalues()):
6946657Snate@binkert.org                code('  case ${{self.c_ident}}_${{enum.ident}}:')
6956657Snate@binkert.org                code('    return $i;')
6966657Snate@binkert.org            code.dedent()
6976657Snate@binkert.org
6986657Snate@binkert.org            # total num
6996657Snate@binkert.org            code('''
7006657Snate@binkert.org      case ${{self.c_ident}}_NUM:
7016657Snate@binkert.org        return ${{len(self.enums)}};
7026657Snate@binkert.org
7036657Snate@binkert.org      default:
7047805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
7056657Snate@binkert.org    }
7066657Snate@binkert.org}
7076657Snate@binkert.org
7086657Snate@binkert.org/** \\brief returns the machine type for each base vector index used by NetDest
7096657Snate@binkert.org *
7107007Snate@binkert.org * \\return the MachineType
7116657Snate@binkert.org */
7127007Snate@binkert.orgMachineType
7137007Snate@binkert.org${{self.c_ident}}_from_base_level(int type)
7146657Snate@binkert.org{
7156657Snate@binkert.org    switch(type) {
7166657Snate@binkert.org''')
7176657Snate@binkert.org
7186657Snate@binkert.org            # For each field
7196657Snate@binkert.org            code.indent()
7206657Snate@binkert.org            for i,enum in enumerate(self.enums.itervalues()):
7216657Snate@binkert.org                code('  case $i:')
7226657Snate@binkert.org                code('    return ${{self.c_ident}}_${{enum.ident}};')
7236657Snate@binkert.org            code.dedent()
7246657Snate@binkert.org
7256657Snate@binkert.org            # Trailer
7266657Snate@binkert.org            code('''
7276657Snate@binkert.org      default:
7287805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
7296657Snate@binkert.org    }
7306657Snate@binkert.org}
7316657Snate@binkert.org
7326657Snate@binkert.org/** \\brief The return value indicates the number of components created
7336657Snate@binkert.org * before a particular machine\'s components
7346657Snate@binkert.org *
7356657Snate@binkert.org * \\return the base number of components for each machine
7366657Snate@binkert.org */
7377007Snate@binkert.orgint
7387007Snate@binkert.org${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
7396657Snate@binkert.org{
7406657Snate@binkert.org    int base = 0;
7416657Snate@binkert.org    switch(obj) {
7426657Snate@binkert.org''')
7436657Snate@binkert.org
7446657Snate@binkert.org            # For each field
7456657Snate@binkert.org            code.indent()
7466657Snate@binkert.org            code('  case ${{self.c_ident}}_NUM:')
7476657Snate@binkert.org            for enum in reversed(self.enums.values()):
7486657Snate@binkert.org                code('    base += ${{enum.ident}}_Controller::getNumControllers();')
7496657Snate@binkert.org                code('  case ${{self.c_ident}}_${{enum.ident}}:')
7506657Snate@binkert.org            code('    break;')
7516657Snate@binkert.org            code.dedent()
7526657Snate@binkert.org
7536657Snate@binkert.org            code('''
7546657Snate@binkert.org      default:
7557805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
7566657Snate@binkert.org    }
7576657Snate@binkert.org
7586657Snate@binkert.org    return base;
7596657Snate@binkert.org}
7606657Snate@binkert.org
7616657Snate@binkert.org/** \\brief returns the total number of components for each machine
7626657Snate@binkert.org * \\return the total number of components for each machine
7636657Snate@binkert.org */
7647007Snate@binkert.orgint
7657007Snate@binkert.org${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
7666657Snate@binkert.org{
7676657Snate@binkert.org    switch(obj) {
7686657Snate@binkert.org''')
7696657Snate@binkert.org
7706657Snate@binkert.org            # For each field
7716657Snate@binkert.org            for enum in self.enums.itervalues():
7726657Snate@binkert.org                code('''
7736657Snate@binkert.org      case ${{self.c_ident}}_${{enum.ident}}:
7746657Snate@binkert.org        return ${{enum.ident}}_Controller::getNumControllers();
7756657Snate@binkert.org''')
7766657Snate@binkert.org
7776657Snate@binkert.org            # total num
7786657Snate@binkert.org            code('''
7796657Snate@binkert.org      case ${{self.c_ident}}_NUM:
7806657Snate@binkert.org      default:
7817805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
7826657Snate@binkert.org    }
7836657Snate@binkert.org}
7846657Snate@binkert.org''')
7856657Snate@binkert.org
7868602Snilay@cs.wisc.edu            for enum in self.enums.itervalues():
7878602Snilay@cs.wisc.edu                if enum.ident == "DMA":
7888602Snilay@cs.wisc.edu                    code('''
7898602Snilay@cs.wisc.eduMachineID
7908602Snilay@cs.wisc.edumap_Address_to_DMA(const Address &addr)
7918602Snilay@cs.wisc.edu{
7928602Snilay@cs.wisc.edu      MachineID dma = {MachineType_DMA, 0};
7938602Snilay@cs.wisc.edu      return dma;
7948602Snilay@cs.wisc.edu}
7958602Snilay@cs.wisc.edu''')
7968602Snilay@cs.wisc.edu
7978602Snilay@cs.wisc.edu                code('''
7988602Snilay@cs.wisc.edu
7998602Snilay@cs.wisc.eduMachineID
8008602Snilay@cs.wisc.eduget${{enum.ident}}MachineID(NodeID RubyNode)
8018602Snilay@cs.wisc.edu{
8028602Snilay@cs.wisc.edu      MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
8038602Snilay@cs.wisc.edu      return mach;
8048602Snilay@cs.wisc.edu}
8058602Snilay@cs.wisc.edu''')
8068602Snilay@cs.wisc.edu
8076657Snate@binkert.org        # Write the file
8086657Snate@binkert.org        code.write(path, "%s.cc" % self.c_ident)
8096657Snate@binkert.org
8106657Snate@binkert.org__all__ = [ "Type" ]
811