Type.py revision 6657
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
286657Snate@binkert.orgfrom m5.util import code_formatter, orderdict
296657Snate@binkert.org
306657Snate@binkert.orgfrom slicc.util import PairContainer
316657Snate@binkert.orgfrom slicc.symbols.Symbol import Symbol
326657Snate@binkert.org
336657Snate@binkert.orgclass DataMember(PairContainer):
346657Snate@binkert.org    def __init__(self, ident, type, pairs, init_code):
356657Snate@binkert.org        super(DataMember, self).__init__(pairs)
366657Snate@binkert.org        self.ident = ident
376657Snate@binkert.org        self.type = type
386657Snate@binkert.org        self.init_code = init_code
396657Snate@binkert.org
406657Snate@binkert.orgclass Enumeration(PairContainer):
416657Snate@binkert.org    def __init__(self, ident, pairs):
426657Snate@binkert.org        super(Enumeration, self).__init__(pairs)
436657Snate@binkert.org        self.ident = ident
446657Snate@binkert.org
456657Snate@binkert.orgclass Method(object):
466657Snate@binkert.org    def __init__(self, return_type, param_types):
476657Snate@binkert.org        self.return_type = return_type
486657Snate@binkert.org        self.param_types = param_types
496657Snate@binkert.org
506657Snate@binkert.orgclass Type(Symbol):
516657Snate@binkert.org    def __init__(self, table, ident, location, pairs, machine=None):
526657Snate@binkert.org        super(Type, self).__init__(table, ident, location, pairs)
536657Snate@binkert.org        self.c_ident = ident
546657Snate@binkert.org        if machine:
556657Snate@binkert.org            if self.isExternal or self.isPrimitive:
566657Snate@binkert.org                if "external_name" in self:
576657Snate@binkert.org                    self.c_ident = self["external_name"]
586657Snate@binkert.org            else:
596657Snate@binkert.org                # Append with machine name
606657Snate@binkert.org                self.c_ident = "%s_%s" % (machine, ident)
616657Snate@binkert.org
626657Snate@binkert.org        self.pairs.setdefault("desc", "No description avaliable")
636657Snate@binkert.org
646657Snate@binkert.org        # check for interface that this Type implements
656657Snate@binkert.org        if "interface" in self:
666657Snate@binkert.org            interface = self["interface"]
676657Snate@binkert.org            if interface in ("Message", "NetworkMessage"):
686657Snate@binkert.org                self["message"] = "yes"
696657Snate@binkert.org            if interface == "NetworkMessage":
706657Snate@binkert.org                self["networkmessage"] = "yes"
716657Snate@binkert.org
726657Snate@binkert.org        # FIXME - all of the following id comparisons are fragile hacks
736657Snate@binkert.org        if self.ident in ("CacheMemory", "NewCacheMemory",
746657Snate@binkert.org                          "TLCCacheMemory", "DNUCACacheMemory",
756657Snate@binkert.org                          "DNUCABankCacheMemory", "L2BankCacheMemory",
766657Snate@binkert.org                          "CompressedCacheMemory", "PrefetchCacheMemory"):
776657Snate@binkert.org            self["cache"] = "yes"
786657Snate@binkert.org
796657Snate@binkert.org        if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
806657Snate@binkert.org            self["tbe"] = "yes"
816657Snate@binkert.org
826657Snate@binkert.org        if self.ident == "NewTBETable":
836657Snate@binkert.org            self["newtbe"] = "yes"
846657Snate@binkert.org
856657Snate@binkert.org        if self.ident == "TimerTable":
866657Snate@binkert.org            self["timer"] = "yes"
876657Snate@binkert.org
886657Snate@binkert.org        if self.ident == "DirectoryMemory":
896657Snate@binkert.org            self["dir"] = "yes"
906657Snate@binkert.org
916657Snate@binkert.org        if self.ident == "PersistentTable":
926657Snate@binkert.org            self["persistent"] = "yes"
936657Snate@binkert.org
946657Snate@binkert.org        if self.ident == "Prefetcher":
956657Snate@binkert.org            self["prefetcher"] = "yes"
966657Snate@binkert.org
976657Snate@binkert.org        if self.ident == "DNUCA_Movement":
986657Snate@binkert.org            self["mover"] = "yes"
996657Snate@binkert.org
1006657Snate@binkert.org        self.isMachineType = (ident == "MachineType")
1016657Snate@binkert.org
1026657Snate@binkert.org        self.data_members = orderdict()
1036657Snate@binkert.org
1046657Snate@binkert.org        # Methods
1056657Snate@binkert.org        self.methods = {}
1066657Snate@binkert.org
1076657Snate@binkert.org        # Enums
1086657Snate@binkert.org        self.enums = orderdict()
1096657Snate@binkert.org
1106657Snate@binkert.org    @property
1116657Snate@binkert.org    def isPrimitive(self):
1126657Snate@binkert.org        return "primitive" in self
1136657Snate@binkert.org    @property
1146657Snate@binkert.org    def isNetworkMessage(self):
1156657Snate@binkert.org        return "networkmessage" in self
1166657Snate@binkert.org    @property
1176657Snate@binkert.org    def isMessage(self):
1186657Snate@binkert.org        return "message" in self
1196657Snate@binkert.org    @property
1206657Snate@binkert.org    def isBuffer(self):
1216657Snate@binkert.org        return "buffer" in self
1226657Snate@binkert.org    @property
1236657Snate@binkert.org    def isInPort(self):
1246657Snate@binkert.org        return "inport" in self
1256657Snate@binkert.org    @property
1266657Snate@binkert.org    def isOutPort(self):
1276657Snate@binkert.org        return "outport" in self
1286657Snate@binkert.org    @property
1296657Snate@binkert.org    def isEnumeration(self):
1306657Snate@binkert.org        return "enumeration" in self
1316657Snate@binkert.org    @property
1326657Snate@binkert.org    def isExternal(self):
1336657Snate@binkert.org        return "external" in self
1346657Snate@binkert.org    @property
1356657Snate@binkert.org    def isGlobal(self):
1366657Snate@binkert.org        return "global" in self
1376657Snate@binkert.org    @property
1386657Snate@binkert.org    def isInterface(self):
1396657Snate@binkert.org        return "interface" in self
1406657Snate@binkert.org
1416657Snate@binkert.org    # Return false on error
1426657Snate@binkert.org    def dataMemberAdd(self, ident, type, pairs, init_code):
1436657Snate@binkert.org        if ident in self.data_members:
1446657Snate@binkert.org            return False
1456657Snate@binkert.org
1466657Snate@binkert.org        member = DataMember(ident, type, pairs, init_code)
1476657Snate@binkert.org        self.data_members[ident] = member
1486657Snate@binkert.org
1496657Snate@binkert.org        return True
1506657Snate@binkert.org
1516657Snate@binkert.org    def dataMemberType(self, ident):
1526657Snate@binkert.org        return self.data_members[ident].type
1536657Snate@binkert.org
1546657Snate@binkert.org    def methodId(self, name, param_type_vec):
1556657Snate@binkert.org        return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
1566657Snate@binkert.org
1576657Snate@binkert.org    def methodAdd(self, name, return_type, param_type_vec):
1586657Snate@binkert.org        ident = self.methodId(name, param_type_vec)
1596657Snate@binkert.org        if ident in self.methods:
1606657Snate@binkert.org            return False
1616657Snate@binkert.org
1626657Snate@binkert.org        self.methods[ident] = Method(return_type, param_type_vec)
1636657Snate@binkert.org        return True
1646657Snate@binkert.org
1656657Snate@binkert.org    def enumAdd(self, ident, pairs):
1666657Snate@binkert.org        if ident in self.enums:
1676657Snate@binkert.org            return False
1686657Snate@binkert.org
1696657Snate@binkert.org        self.enums[ident] = Enumeration(ident, pairs)
1706657Snate@binkert.org
1716657Snate@binkert.org        # Add default
1726657Snate@binkert.org        if "default" not in self:
1736657Snate@binkert.org            self["default"] = "%s_NUM" % self.c_ident
1746657Snate@binkert.org
1756657Snate@binkert.org        return True
1766657Snate@binkert.org
1776657Snate@binkert.org    def writeCodeFiles(self, path):
1786657Snate@binkert.org        if self.isExternal:
1796657Snate@binkert.org            # Do nothing
1806657Snate@binkert.org            pass
1816657Snate@binkert.org        elif self.isEnumeration:
1826657Snate@binkert.org            self.printEnumHH(path)
1836657Snate@binkert.org            self.printEnumCC(path)
1846657Snate@binkert.org        else:
1856657Snate@binkert.org            # User defined structs and messages
1866657Snate@binkert.org            self.printTypeHH(path)
1876657Snate@binkert.org            self.printTypeCC(path)
1886657Snate@binkert.org
1896657Snate@binkert.org    def printTypeHH(self, path):
1906657Snate@binkert.org        code = code_formatter()
1916657Snate@binkert.org        code('''
1926657Snate@binkert.org/** \\file ${{self.c_ident}}.hh
1936657Snate@binkert.org *
1946657Snate@binkert.org *
1956657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
1966657Snate@binkert.org */
1976657Snate@binkert.org
1986657Snate@binkert.org#ifndef ${{self.c_ident}}_H
1996657Snate@binkert.org#define ${{self.c_ident}}_H
2006657Snate@binkert.org
2016657Snate@binkert.org#include "mem/ruby/common/Global.hh"
2026657Snate@binkert.org#include "mem/gems_common/Allocator.hh"
2036657Snate@binkert.org''')
2046657Snate@binkert.org
2056657Snate@binkert.org        for dm in self.data_members.values():
2066657Snate@binkert.org            if not dm.type.isPrimitive:
2076657Snate@binkert.org                code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
2086657Snate@binkert.org
2096657Snate@binkert.org        parent = ""
2106657Snate@binkert.org        if "interface" in self:
2116657Snate@binkert.org            code('#include "mem/protocol/$0.hh"', self["interface"])
2126657Snate@binkert.org            parent = " :  public %s" % self["interface"]
2136657Snate@binkert.org
2146657Snate@binkert.org        code('''
2156657Snate@binkert.org$klass ${{self.c_ident}}$parent {
2166657Snate@binkert.org  public:
2176657Snate@binkert.org    ${{self.c_ident}}()
2186657Snate@binkert.org''', klass="class")
2196657Snate@binkert.org
2206657Snate@binkert.org        # Call superclass constructor
2216657Snate@binkert.org        if "interface" in self:
2226657Snate@binkert.org            code('        : ${{self["interface"]}}()')
2236657Snate@binkert.org
2246657Snate@binkert.org        code.indent()
2256657Snate@binkert.org        code("{")
2266657Snate@binkert.org        if not self.isGlobal:
2276657Snate@binkert.org            code.indent()
2286657Snate@binkert.org            for dm in self.data_members.values():
2296657Snate@binkert.org                ident = dm.ident
2306657Snate@binkert.org                if "default" in dm:
2316657Snate@binkert.org                    # look for default value
2326657Snate@binkert.org                    code('m_$ident = ${{dm["default"]}}; // default for this field')
2336657Snate@binkert.org                elif "default" in dm.type:
2346657Snate@binkert.org                    # Look for the type default
2356657Snate@binkert.org                    tid = dm.type.c_ident
2366657Snate@binkert.org                    code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
2376657Snate@binkert.org                else:
2386657Snate@binkert.org                    code('// m_$ident has no default')
2396657Snate@binkert.org            code.dedent()
2406657Snate@binkert.org        code('}')
2416657Snate@binkert.org
2426657Snate@binkert.org        # ******** Default destructor ********
2436657Snate@binkert.org        code('~${{self.c_ident}}() { };')
2446657Snate@binkert.org
2456657Snate@binkert.org        # ******** Full init constructor ********
2466657Snate@binkert.org        if not self.isGlobal:
2476657Snate@binkert.org            params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
2486657Snate@binkert.org                       for dm in self.data_members.itervalues() ]
2496657Snate@binkert.org
2506657Snate@binkert.org            if self.isMessage:
2516657Snate@binkert.org                params.append('const unsigned local_proc_id')
2526657Snate@binkert.org
2536657Snate@binkert.org            params = ', '.join(params)
2546657Snate@binkert.org            code('${{self.c_ident}}($params)')
2556657Snate@binkert.org
2566657Snate@binkert.org            # Call superclass constructor
2576657Snate@binkert.org            if "interface" in self:
2586657Snate@binkert.org                code('    : ${{self["interface"]}}()')
2596657Snate@binkert.org
2606657Snate@binkert.org            code('{')
2616657Snate@binkert.org            code.indent()
2626657Snate@binkert.org            for dm in self.data_members.values():
2636657Snate@binkert.org                code('m_${{dm.ident}} = local_${{dm.ident}};')
2646657Snate@binkert.org                if "nextLineCallHack" in dm:
2656657Snate@binkert.org                    code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
2666657Snate@binkert.org
2676657Snate@binkert.org            if self.isMessage:
2686657Snate@binkert.org                code('proc_id = local_proc_id;')
2696657Snate@binkert.org
2706657Snate@binkert.org            code.dedent()
2716657Snate@binkert.org            code('}')
2726657Snate@binkert.org
2736657Snate@binkert.org        # create a static factory method
2746657Snate@binkert.org        if "interface" in self:
2756657Snate@binkert.org            code('''
2766657Snate@binkert.orgstatic ${{self["interface"]}}* create() {
2776657Snate@binkert.org    return new ${{self.c_ident}}();
2786657Snate@binkert.org}
2796657Snate@binkert.org''')
2806657Snate@binkert.org
2816657Snate@binkert.org        # ******** Message member functions ********
2826657Snate@binkert.org        # FIXME: those should be moved into slicc file, slicc should
2836657Snate@binkert.org        # support more of the c++ class inheritance
2846657Snate@binkert.org
2856657Snate@binkert.org        if self.isMessage:
2866657Snate@binkert.org            code('''
2876657Snate@binkert.orgMessage* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }
2886657Snate@binkert.orgvoid destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }
2896657Snate@binkert.orgstatic Allocator<${{self.c_ident}}>* s_allocator_ptr;
2906657Snate@binkert.orgstatic void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }}
2916657Snate@binkert.org''')
2926657Snate@binkert.org
2936657Snate@binkert.org        if not self.isGlobal:
2946657Snate@binkert.org            # const Get methods for each field
2956657Snate@binkert.org            code('// Const accessors methods for each field')
2966657Snate@binkert.org            for dm in self.data_members.values():
2976657Snate@binkert.org                code('''
2986657Snate@binkert.org/** \\brief Const accessor method for ${{dm.ident}} field.
2996657Snate@binkert.org *  \\return ${{dm.ident}} field
3006657Snate@binkert.org */
3016657Snate@binkert.orgconst ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; }
3026657Snate@binkert.org''')
3036657Snate@binkert.org
3046657Snate@binkert.org            # Non-const Get methods for each field
3056657Snate@binkert.org            code('// Non const Accessors methods for each field')
3066657Snate@binkert.org            for dm in self.data_members.values():
3076657Snate@binkert.org                code('''
3086657Snate@binkert.org/** \\brief Non-const accessor method for ${{dm.ident}} field.
3096657Snate@binkert.org *  \\return ${{dm.ident}} field
3106657Snate@binkert.org */
3116657Snate@binkert.org${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; }
3126657Snate@binkert.org''')
3136657Snate@binkert.org
3146657Snate@binkert.org            #Set methods for each field
3156657Snate@binkert.org            code('// Mutator methods for each field')
3166657Snate@binkert.org            for dm in self.data_members.values():
3176657Snate@binkert.org                code('''
3186657Snate@binkert.org/** \\brief Mutator method for ${{dm.ident}} field */
3196657Snate@binkert.orgvoid set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; }
3206657Snate@binkert.org''')
3216657Snate@binkert.org
3226657Snate@binkert.org        code('void print(ostream& out) const;')
3236657Snate@binkert.org        code.dedent()
3246657Snate@binkert.org        code('  //private:')
3256657Snate@binkert.org        code.indent()
3266657Snate@binkert.org
3276657Snate@binkert.org        # Data members for each field
3286657Snate@binkert.org        for dm in self.data_members.values():
3296657Snate@binkert.org            if "abstract" not in dm:
3306657Snate@binkert.org                const = ""
3316657Snate@binkert.org                init = ""
3326657Snate@binkert.org
3336657Snate@binkert.org                # global structure
3346657Snate@binkert.org                if self.isGlobal:
3356657Snate@binkert.org                    const = "static const "
3366657Snate@binkert.org
3376657Snate@binkert.org                # init value
3386657Snate@binkert.org                if dm.init_code:
3396657Snate@binkert.org                    # only global structure can have init value here
3406657Snate@binkert.org                    assert self.isGlobal
3416657Snate@binkert.org                    init = " = %s" % (dm.init_code)
3426657Snate@binkert.org
3436657Snate@binkert.org                desc = ""
3446657Snate@binkert.org                if "desc" in dm:
3456657Snate@binkert.org                    desc = '/**< %s */' % dm["desc"]
3466657Snate@binkert.org
3476657Snate@binkert.org                code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc')
3486657Snate@binkert.org
3496657Snate@binkert.org        if self.isMessage:
3506657Snate@binkert.org            code('unsigned proc_id;')
3516657Snate@binkert.org
3526657Snate@binkert.org        code.dedent()
3536657Snate@binkert.org        code('};')
3546657Snate@binkert.org
3556657Snate@binkert.org        code('''
3566657Snate@binkert.org// Output operator declaration
3576657Snate@binkert.orgostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
3586657Snate@binkert.org
3596657Snate@binkert.org// Output operator definition
3606657Snate@binkert.orgextern inline
3616657Snate@binkert.orgostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
3626657Snate@binkert.org{
3636657Snate@binkert.org    obj.print(out);
3646657Snate@binkert.org    out << flush;
3656657Snate@binkert.org    return out;
3666657Snate@binkert.org}
3676657Snate@binkert.org
3686657Snate@binkert.org#endif // ${{self.c_ident}}_H
3696657Snate@binkert.org''')
3706657Snate@binkert.org
3716657Snate@binkert.org        code.write(path, "%s.hh" % self.c_ident)
3726657Snate@binkert.org
3736657Snate@binkert.org    def printTypeCC(self, path):
3746657Snate@binkert.org        code = code_formatter()
3756657Snate@binkert.org
3766657Snate@binkert.org        code('''
3776657Snate@binkert.org/** \\file ${{self.c_ident}}.cc
3786657Snate@binkert.org *
3796657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
3806657Snate@binkert.org */
3816657Snate@binkert.org
3826657Snate@binkert.org#include "mem/protocol/${{self.c_ident}}.hh"
3836657Snate@binkert.org''')
3846657Snate@binkert.org
3856657Snate@binkert.org        if self.isMessage:
3866657Snate@binkert.org            code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;')
3876657Snate@binkert.org        code('''
3886657Snate@binkert.org/** \\brief Print the state of this object */
3896657Snate@binkert.orgvoid ${{self.c_ident}}::print(ostream& out) const
3906657Snate@binkert.org{
3916657Snate@binkert.org    out << "[${{self.c_ident}}: ";
3926657Snate@binkert.org''')
3936657Snate@binkert.org
3946657Snate@binkert.org        # For each field
3956657Snate@binkert.org        code.indent()
3966657Snate@binkert.org        for dm in self.data_members.values():
3976657Snate@binkert.org            code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
3986657Snate@binkert.org
3996657Snate@binkert.org        if self.isMessage:
4006657Snate@binkert.org            code('out << "Time = " << getTime() << " ";')
4016657Snate@binkert.org        code.dedent()
4026657Snate@binkert.org
4036657Snate@binkert.org        # Trailer
4046657Snate@binkert.org        code('''
4056657Snate@binkert.org    out << "]";
4066657Snate@binkert.org}''')
4076657Snate@binkert.org
4086657Snate@binkert.org        code.write(path, "%s.cc" % self.c_ident)
4096657Snate@binkert.org
4106657Snate@binkert.org    def printEnumHH(self, path):
4116657Snate@binkert.org        code = code_formatter()
4126657Snate@binkert.org        code('''
4136657Snate@binkert.org/** \\file ${{self.c_ident}}.hh
4146657Snate@binkert.org *
4156657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
4166657Snate@binkert.org */
4176657Snate@binkert.org#ifndef ${{self.c_ident}}_H
4186657Snate@binkert.org#define ${{self.c_ident}}_H
4196657Snate@binkert.org
4206657Snate@binkert.org#include "mem/ruby/common/Global.hh"
4216657Snate@binkert.org
4226657Snate@binkert.org/** \\enum ${{self.c_ident}}
4236657Snate@binkert.org *  \\brief ${{self.desc}}
4246657Snate@binkert.org */
4256657Snate@binkert.orgenum ${{self.c_ident}} {
4266657Snate@binkert.org    ${{self.c_ident}}_FIRST,
4276657Snate@binkert.org''')
4286657Snate@binkert.org
4296657Snate@binkert.org        code.indent()
4306657Snate@binkert.org        # For each field
4316657Snate@binkert.org        for i,(ident,enum) in enumerate(self.enums.iteritems()):
4326657Snate@binkert.org            desc = enum.get("desc", "No description avaliable")
4336657Snate@binkert.org            init = ' = %s_FIRST' % self.c_ident if i == 0 else ''
4346657Snate@binkert.org
4356657Snate@binkert.org            code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
4366657Snate@binkert.org        code.dedent()
4376657Snate@binkert.org        code('''
4386657Snate@binkert.org    ${{self.c_ident}}_NUM
4396657Snate@binkert.org};
4406657Snate@binkert.org${{self.c_ident}} string_to_${{self.c_ident}}(const string& str);
4416657Snate@binkert.orgstring ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
4426657Snate@binkert.org${{self.c_ident}} &operator++(${{self.c_ident}} &e);
4436657Snate@binkert.org''')
4446657Snate@binkert.org
4456657Snate@binkert.org        # MachineType hack used to set the base component id for each Machine
4466657Snate@binkert.org        if self.isMachineType:
4476657Snate@binkert.org            code('''
4486657Snate@binkert.orgint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
4496657Snate@binkert.orgMachineType ${{self.c_ident}}_from_base_level(int);
4506657Snate@binkert.orgint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
4516657Snate@binkert.orgint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
4526657Snate@binkert.org''')
4536657Snate@binkert.org
4546657Snate@binkert.org            for enum in self.enums.itervalues():
4556657Snate@binkert.org                code('#define MACHINETYPE_${{enum.ident}} 1')
4566657Snate@binkert.org
4576657Snate@binkert.org        # Trailer
4586657Snate@binkert.org        code('''
4596657Snate@binkert.orgostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
4606657Snate@binkert.org
4616657Snate@binkert.org#endif // ${{self.c_ident}}_H
4626657Snate@binkert.org''')
4636657Snate@binkert.org
4646657Snate@binkert.org        code.write(path, "%s.hh" % self.c_ident)
4656657Snate@binkert.org
4666657Snate@binkert.org    def printEnumCC(self, path):
4676657Snate@binkert.org        code = code_formatter()
4686657Snate@binkert.org        code('''
4696657Snate@binkert.org/** \\file ${{self.c_ident}}.hh
4706657Snate@binkert.org *
4716657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
4726657Snate@binkert.org */
4736657Snate@binkert.org
4746657Snate@binkert.org#include "mem/protocol/${{self.c_ident}}.hh"
4756657Snate@binkert.org
4766657Snate@binkert.org''')
4776657Snate@binkert.org
4786657Snate@binkert.org        if self.isMachineType:
4796657Snate@binkert.org            code('#include "mem/protocol/ControllerFactory.hh"')
4806657Snate@binkert.org            for enum in self.enums.itervalues():
4816657Snate@binkert.org                code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
4826657Snate@binkert.org
4836657Snate@binkert.org        code('''
4846657Snate@binkert.orgostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
4856657Snate@binkert.org{
4866657Snate@binkert.org    out << ${{self.c_ident}}_to_string(obj);
4876657Snate@binkert.org    out << flush;
4886657Snate@binkert.org    return out;
4896657Snate@binkert.org}
4906657Snate@binkert.org
4916657Snate@binkert.orgstring ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
4926657Snate@binkert.org{
4936657Snate@binkert.org    switch(obj) {
4946657Snate@binkert.org''')
4956657Snate@binkert.org
4966657Snate@binkert.org        # For each field
4976657Snate@binkert.org        code.indent()
4986657Snate@binkert.org        for enum in self.enums.itervalues():
4996657Snate@binkert.org            code('  case ${{self.c_ident}}_${{enum.ident}}:')
5006657Snate@binkert.org            code('    return "${{enum.ident}}";')
5016657Snate@binkert.org        code.dedent()
5026657Snate@binkert.org
5036657Snate@binkert.org        # Trailer
5046657Snate@binkert.org        code('''
5056657Snate@binkert.org      default:
5066657Snate@binkert.org        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
5076657Snate@binkert.org        return "";
5086657Snate@binkert.org    }
5096657Snate@binkert.org}
5106657Snate@binkert.org
5116657Snate@binkert.org${{self.c_ident}} string_to_${{self.c_ident}}(const string& str)
5126657Snate@binkert.org{
5136657Snate@binkert.org''')
5146657Snate@binkert.org
5156657Snate@binkert.org        # For each field
5166657Snate@binkert.org        code.indent()
5176657Snate@binkert.org        code("if (false) {")
5186657Snate@binkert.org        start = "} else "
5196657Snate@binkert.org        for enum in self.enums.itervalues():
5206657Snate@binkert.org            code('${start}if (str == "${{enum.ident}}") {')
5216657Snate@binkert.org            code('    return ${{self.c_ident}}_${{enum.ident}};')
5226657Snate@binkert.org        code.dedent()
5236657Snate@binkert.org
5246657Snate@binkert.org        code('''
5256657Snate@binkert.org    } else {
5266657Snate@binkert.org        WARN_EXPR(str);
5276657Snate@binkert.org        ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}");
5286657Snate@binkert.org    }
5296657Snate@binkert.org}
5306657Snate@binkert.org
5316657Snate@binkert.org${{self.c_ident}}& operator++(${{self.c_ident}}& e) {
5326657Snate@binkert.org    assert(e < ${{self.c_ident}}_NUM);
5336657Snate@binkert.org    return e = ${{self.c_ident}}(e+1);
5346657Snate@binkert.org}
5356657Snate@binkert.org''')
5366657Snate@binkert.org
5376657Snate@binkert.org        # MachineType hack used to set the base level and number of
5386657Snate@binkert.org        # components for each Machine
5396657Snate@binkert.org        if self.isMachineType:
5406657Snate@binkert.org            code('''
5416657Snate@binkert.org/** \\brief returns the base vector index for each machine type to be used by NetDest
5426657Snate@binkert.org  *
5436657Snate@binkert.org  * \\return the base vector index for each machine type to be used by NetDest
5446657Snate@binkert.org  * \\see NetDest.hh
5456657Snate@binkert.org  */
5466657Snate@binkert.orgint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
5476657Snate@binkert.org{
5486657Snate@binkert.org    switch(obj) {
5496657Snate@binkert.org''')
5506657Snate@binkert.org
5516657Snate@binkert.org            # For each field
5526657Snate@binkert.org            code.indent()
5536657Snate@binkert.org            for i,enum in enumerate(self.enums.itervalues()):
5546657Snate@binkert.org                code('  case ${{self.c_ident}}_${{enum.ident}}:')
5556657Snate@binkert.org                code('    return $i;')
5566657Snate@binkert.org            code.dedent()
5576657Snate@binkert.org
5586657Snate@binkert.org            # total num
5596657Snate@binkert.org            code('''
5606657Snate@binkert.org      case ${{self.c_ident}}_NUM:
5616657Snate@binkert.org        return ${{len(self.enums)}};
5626657Snate@binkert.org
5636657Snate@binkert.org      default:
5646657Snate@binkert.org        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
5656657Snate@binkert.org        return -1;
5666657Snate@binkert.org    }
5676657Snate@binkert.org}
5686657Snate@binkert.org
5696657Snate@binkert.org/** \\brief returns the machine type for each base vector index used by NetDest
5706657Snate@binkert.org *
5716657Snate@binkert.org * \\return the MachineTYpe
5726657Snate@binkert.org */
5736657Snate@binkert.orgMachineType ${{self.c_ident}}_from_base_level(int type)
5746657Snate@binkert.org{
5756657Snate@binkert.org    switch(type) {
5766657Snate@binkert.org''')
5776657Snate@binkert.org
5786657Snate@binkert.org            # For each field
5796657Snate@binkert.org            code.indent()
5806657Snate@binkert.org            for i,enum in enumerate(self.enums.itervalues()):
5816657Snate@binkert.org                code('  case $i:')
5826657Snate@binkert.org                code('    return ${{self.c_ident}}_${{enum.ident}};')
5836657Snate@binkert.org            code.dedent()
5846657Snate@binkert.org
5856657Snate@binkert.org            # Trailer
5866657Snate@binkert.org            code('''
5876657Snate@binkert.org      default:
5886657Snate@binkert.org        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
5896657Snate@binkert.org        return MachineType_NUM;
5906657Snate@binkert.org    }
5916657Snate@binkert.org}
5926657Snate@binkert.org
5936657Snate@binkert.org/** \\brief The return value indicates the number of components created
5946657Snate@binkert.org * before a particular machine\'s components
5956657Snate@binkert.org *
5966657Snate@binkert.org * \\return the base number of components for each machine
5976657Snate@binkert.org */
5986657Snate@binkert.orgint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
5996657Snate@binkert.org{
6006657Snate@binkert.org    int base = 0;
6016657Snate@binkert.org    switch(obj) {
6026657Snate@binkert.org''')
6036657Snate@binkert.org
6046657Snate@binkert.org            # For each field
6056657Snate@binkert.org            code.indent()
6066657Snate@binkert.org            code('  case ${{self.c_ident}}_NUM:')
6076657Snate@binkert.org            for enum in reversed(self.enums.values()):
6086657Snate@binkert.org                code('    base += ${{enum.ident}}_Controller::getNumControllers();')
6096657Snate@binkert.org                code('  case ${{self.c_ident}}_${{enum.ident}}:')
6106657Snate@binkert.org            code('    break;')
6116657Snate@binkert.org            code.dedent()
6126657Snate@binkert.org
6136657Snate@binkert.org            code('''
6146657Snate@binkert.org      default:
6156657Snate@binkert.org        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
6166657Snate@binkert.org        return -1;
6176657Snate@binkert.org    }
6186657Snate@binkert.org
6196657Snate@binkert.org    return base;
6206657Snate@binkert.org}
6216657Snate@binkert.org
6226657Snate@binkert.org/** \\brief returns the total number of components for each machine
6236657Snate@binkert.org * \\return the total number of components for each machine
6246657Snate@binkert.org */
6256657Snate@binkert.orgint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
6266657Snate@binkert.org{
6276657Snate@binkert.org    switch(obj) {
6286657Snate@binkert.org''')
6296657Snate@binkert.org
6306657Snate@binkert.org            # For each field
6316657Snate@binkert.org            for enum in self.enums.itervalues():
6326657Snate@binkert.org                code('''
6336657Snate@binkert.org      case ${{self.c_ident}}_${{enum.ident}}:
6346657Snate@binkert.org        return ${{enum.ident}}_Controller::getNumControllers();
6356657Snate@binkert.org''')
6366657Snate@binkert.org
6376657Snate@binkert.org            # total num
6386657Snate@binkert.org            code('''
6396657Snate@binkert.org      case ${{self.c_ident}}_NUM:
6406657Snate@binkert.org      default:
6416657Snate@binkert.org        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
6426657Snate@binkert.org        return -1;
6436657Snate@binkert.org    }
6446657Snate@binkert.org}
6456657Snate@binkert.org''')
6466657Snate@binkert.org
6476657Snate@binkert.org        # Write the file
6486657Snate@binkert.org        code.write(path, "%s.cc" % self.c_ident)
6496657Snate@binkert.org
6506657Snate@binkert.org__all__ = [ "Type" ]
651