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
2813672Sandreas.sandberg@arm.comfrom collections import OrderedDict
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
3411117Snilay@cs.wisc.educlass DataMember(Var):
3511117Snilay@cs.wisc.edu    def __init__(self, symtab, ident, location, type, code, pairs,
3611117Snilay@cs.wisc.edu                 machine, init_code):
3711117Snilay@cs.wisc.edu        super(DataMember, self).__init__(symtab, ident, location, type,
3811117Snilay@cs.wisc.edu                                         code, pairs, machine)
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
4511283Santhony.gutierrez@amd.com        self.primary = False
466657Snate@binkert.org
476657Snate@binkert.orgclass Type(Symbol):
486657Snate@binkert.org    def __init__(self, table, ident, location, pairs, machine=None):
496657Snate@binkert.org        super(Type, self).__init__(table, ident, location, pairs)
506657Snate@binkert.org        self.c_ident = ident
516882SBrad.Beckmann@amd.com        self.abstract_ident = ""
526657Snate@binkert.org        if machine:
536657Snate@binkert.org            if self.isExternal or self.isPrimitive:
546657Snate@binkert.org                if "external_name" in self:
556657Snate@binkert.org                    self.c_ident = self["external_name"]
566657Snate@binkert.org            else:
576657Snate@binkert.org                # Append with machine name
586657Snate@binkert.org                self.c_ident = "%s_%s" % (machine, ident)
596657Snate@binkert.org
606657Snate@binkert.org        self.pairs.setdefault("desc", "No description avaliable")
616657Snate@binkert.org
626657Snate@binkert.org        # check for interface that this Type implements
636657Snate@binkert.org        if "interface" in self:
646657Snate@binkert.org            interface = self["interface"]
6510895Snilay@cs.wisc.edu            if interface in ("Message"):
666657Snate@binkert.org                self["message"] = "yes"
676657Snate@binkert.org
686657Snate@binkert.org        # FIXME - all of the following id comparisons are fragile hacks
6910228Snilay@cs.wisc.edu        if self.ident in ("CacheMemory"):
706657Snate@binkert.org            self["cache"] = "yes"
716657Snate@binkert.org
7210228Snilay@cs.wisc.edu        if self.ident in ("TBETable"):
736657Snate@binkert.org            self["tbe"] = "yes"
746657Snate@binkert.org
756657Snate@binkert.org        if self.ident == "TimerTable":
766657Snate@binkert.org            self["timer"] = "yes"
776657Snate@binkert.org
786657Snate@binkert.org        if self.ident == "DirectoryMemory":
796657Snate@binkert.org            self["dir"] = "yes"
806657Snate@binkert.org
816657Snate@binkert.org        if self.ident == "PersistentTable":
826657Snate@binkert.org            self["persistent"] = "yes"
836657Snate@binkert.org
846657Snate@binkert.org        if self.ident == "Prefetcher":
856657Snate@binkert.org            self["prefetcher"] = "yes"
866657Snate@binkert.org
876657Snate@binkert.org        self.isMachineType = (ident == "MachineType")
886657Snate@binkert.org
898086SBrad.Beckmann@amd.com        self.isStateDecl = ("state_decl" in self)
908086SBrad.Beckmann@amd.com        self.statePermPairs = []
918086SBrad.Beckmann@amd.com
9213672Sandreas.sandberg@arm.com        self.data_members = OrderedDict()
936657Snate@binkert.org        self.methods = {}
9413672Sandreas.sandberg@arm.com        self.enums = OrderedDict()
956657Snate@binkert.org
966657Snate@binkert.org    @property
976657Snate@binkert.org    def isPrimitive(self):
986657Snate@binkert.org        return "primitive" in self
9910895Snilay@cs.wisc.edu
1006657Snate@binkert.org    @property
1016657Snate@binkert.org    def isMessage(self):
1026657Snate@binkert.org        return "message" in self
1036657Snate@binkert.org    @property
1046657Snate@binkert.org    def isBuffer(self):
1056657Snate@binkert.org        return "buffer" in self
1066657Snate@binkert.org    @property
1076657Snate@binkert.org    def isInPort(self):
1086657Snate@binkert.org        return "inport" in self
1096657Snate@binkert.org    @property
1106657Snate@binkert.org    def isOutPort(self):
1116657Snate@binkert.org        return "outport" in self
1126657Snate@binkert.org    @property
1136657Snate@binkert.org    def isEnumeration(self):
1146657Snate@binkert.org        return "enumeration" in self
1156657Snate@binkert.org    @property
1166657Snate@binkert.org    def isExternal(self):
1176657Snate@binkert.org        return "external" in self
1186657Snate@binkert.org    @property
1196657Snate@binkert.org    def isGlobal(self):
1206657Snate@binkert.org        return "global" in self
1216657Snate@binkert.org    @property
1226657Snate@binkert.org    def isInterface(self):
1236657Snate@binkert.org        return "interface" in self
1246657Snate@binkert.org
1256657Snate@binkert.org    # Return false on error
1269298Snilay@cs.wisc.edu    def addDataMember(self, ident, type, pairs, init_code):
1276657Snate@binkert.org        if ident in self.data_members:
1286657Snate@binkert.org            return False
1296657Snate@binkert.org
13011117Snilay@cs.wisc.edu        member = DataMember(self.symtab, ident, self.location, type,
13111117Snilay@cs.wisc.edu                            "m_%s" % ident, pairs, None, init_code)
13211117Snilay@cs.wisc.edu
1336657Snate@binkert.org        self.data_members[ident] = member
13411117Snilay@cs.wisc.edu        self.symtab.registerSym(ident, member)
1356657Snate@binkert.org        return True
1366657Snate@binkert.org
1376657Snate@binkert.org    def dataMemberType(self, ident):
1386657Snate@binkert.org        return self.data_members[ident].type
1396657Snate@binkert.org
1406657Snate@binkert.org    def methodId(self, name, param_type_vec):
1416657Snate@binkert.org        return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
1426657Snate@binkert.org
1436882SBrad.Beckmann@amd.com    def methodIdAbstract(self, name, param_type_vec):
1446882SBrad.Beckmann@amd.com        return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
1456882SBrad.Beckmann@amd.com
1468086SBrad.Beckmann@amd.com    def statePermPairAdd(self, state_name, perm_name):
1478086SBrad.Beckmann@amd.com        self.statePermPairs.append([state_name, perm_name])
1488086SBrad.Beckmann@amd.com
14910307Snilay@cs.wisc.edu    def addFunc(self, func):
15010307Snilay@cs.wisc.edu        ident = self.methodId(func.ident, func.param_types)
1516657Snate@binkert.org        if ident in self.methods:
1526657Snate@binkert.org            return False
1536657Snate@binkert.org
15410307Snilay@cs.wisc.edu        self.methods[ident] = func
1559298Snilay@cs.wisc.edu        return True
1569298Snilay@cs.wisc.edu
1579298Snilay@cs.wisc.edu    def addEnum(self, ident, pairs):
1586657Snate@binkert.org        if ident in self.enums:
1596657Snate@binkert.org            return False
1606657Snate@binkert.org
1616657Snate@binkert.org        self.enums[ident] = Enumeration(ident, pairs)
1626657Snate@binkert.org
1636657Snate@binkert.org        # Add default
1646657Snate@binkert.org        if "default" not in self:
1656657Snate@binkert.org            self["default"] = "%s_NUM" % self.c_ident
1666657Snate@binkert.org
1676657Snate@binkert.org        return True
1686657Snate@binkert.org
16911283Santhony.gutierrez@amd.com    ## Used to check if an enum has been already used and therefore
17011283Santhony.gutierrez@amd.com    ## should not be used again.
17111283Santhony.gutierrez@amd.com    def checkEnum(self, ident):
17211283Santhony.gutierrez@amd.com        if ident in self.enums and not self.enums[ident].primary:
17311283Santhony.gutierrez@amd.com            self.enums[ident].primary = True
17411283Santhony.gutierrez@amd.com            return True
17511283Santhony.gutierrez@amd.com        return False
17611283Santhony.gutierrez@amd.com
1779219Spower.jg@gmail.com    def writeCodeFiles(self, path, includes):
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):
1906999Snate@binkert.org        code = self.symtab.codeFormatter()
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
1987007Snate@binkert.org#ifndef __${{self.c_ident}}_HH__
1997007Snate@binkert.org#define __${{self.c_ident}}_HH__
2006657Snate@binkert.org
2017002Snate@binkert.org#include <iostream>
2027002Snate@binkert.org
2039466Snilay@cs.wisc.edu#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
20414184Sgabeblack@google.com
2056657Snate@binkert.org''')
2066657Snate@binkert.org
2076657Snate@binkert.org        for dm in self.data_members.values():
2086657Snate@binkert.org            if not dm.type.isPrimitive:
20914184Sgabeblack@google.com                code('#include "mem/ruby/protocol/$0.hh"', dm.type.c_ident)
2106657Snate@binkert.org
2116657Snate@binkert.org        parent = ""
2126657Snate@binkert.org        if "interface" in self:
21314184Sgabeblack@google.com            code('#include "mem/ruby/protocol/$0.hh"', self["interface"])
2146657Snate@binkert.org            parent = " :  public %s" % self["interface"]
2156657Snate@binkert.org
2166657Snate@binkert.org        code('''
2177007Snate@binkert.org$klass ${{self.c_ident}}$parent
2187007Snate@binkert.org{
2196657Snate@binkert.org  public:
2209466Snilay@cs.wisc.edu    ${{self.c_ident}}
2216657Snate@binkert.org''', klass="class")
2226657Snate@binkert.org
2239466Snilay@cs.wisc.edu        if self.isMessage:
2249508Snilay@cs.wisc.edu            code('(Tick curTime) : %s(curTime) {' % self["interface"])
2259466Snilay@cs.wisc.edu        else:
2269466Snilay@cs.wisc.edu            code('()\n\t\t{')
2279466Snilay@cs.wisc.edu
2286657Snate@binkert.org        code.indent()
2296657Snate@binkert.org        if not self.isGlobal:
2306657Snate@binkert.org            code.indent()
2316657Snate@binkert.org            for dm in self.data_members.values():
2326657Snate@binkert.org                ident = dm.ident
2336657Snate@binkert.org                if "default" in dm:
2346657Snate@binkert.org                    # look for default value
2356657Snate@binkert.org                    code('m_$ident = ${{dm["default"]}}; // default for this field')
2366657Snate@binkert.org                elif "default" in dm.type:
2376657Snate@binkert.org                    # Look for the type default
2386657Snate@binkert.org                    tid = dm.type.c_ident
2396657Snate@binkert.org                    code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
2406657Snate@binkert.org                else:
2416657Snate@binkert.org                    code('// m_$ident has no default')
2426657Snate@binkert.org            code.dedent()
2436657Snate@binkert.org        code('}')
2446657Snate@binkert.org
2457453Snate@binkert.org        # ******** Copy constructor ********
2467453Snate@binkert.org        if not self.isGlobal:
2477453Snate@binkert.org            code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
2487453Snate@binkert.org
2497453Snate@binkert.org            # Call superclass constructor
2507453Snate@binkert.org            if "interface" in self:
2517453Snate@binkert.org                code('    : ${{self["interface"]}}(other)')
2527453Snate@binkert.org
2537453Snate@binkert.org            code('{')
2547453Snate@binkert.org            code.indent()
2557453Snate@binkert.org
2567453Snate@binkert.org            for dm in self.data_members.values():
2577453Snate@binkert.org                code('m_${{dm.ident}} = other.m_${{dm.ident}};')
2587453Snate@binkert.org
2597453Snate@binkert.org            code.dedent()
2607453Snate@binkert.org            code('}')
2617453Snate@binkert.org
2626657Snate@binkert.org        # ******** Full init constructor ********
2636657Snate@binkert.org        if not self.isGlobal:
2646657Snate@binkert.org            params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
2656657Snate@binkert.org                       for dm in self.data_members.itervalues() ]
2669466Snilay@cs.wisc.edu            params = ', '.join(params)
2676657Snate@binkert.org
2689466Snilay@cs.wisc.edu            if self.isMessage:
2699508Snilay@cs.wisc.edu                params = "const Tick curTime, " + params
2709466Snilay@cs.wisc.edu
2716657Snate@binkert.org            code('${{self.c_ident}}($params)')
2726657Snate@binkert.org
2736657Snate@binkert.org            # Call superclass constructor
2746657Snate@binkert.org            if "interface" in self:
2759466Snilay@cs.wisc.edu                if self.isMessage:
2769466Snilay@cs.wisc.edu                    code('    : ${{self["interface"]}}(curTime)')
2779466Snilay@cs.wisc.edu                else:
2789466Snilay@cs.wisc.edu                    code('    : ${{self["interface"]}}()')
2796657Snate@binkert.org
2806657Snate@binkert.org            code('{')
2816657Snate@binkert.org            code.indent()
2826657Snate@binkert.org            for dm in self.data_members.values():
2836657Snate@binkert.org                code('m_${{dm.ident}} = local_${{dm.ident}};')
2846657Snate@binkert.org
2856657Snate@binkert.org            code.dedent()
2866657Snate@binkert.org            code('}')
2876657Snate@binkert.org
2889466Snilay@cs.wisc.edu        # create a clone member
28910472Sandreas.hansson@arm.com        if self.isMessage:
29010472Sandreas.hansson@arm.com            code('''
29110472Sandreas.hansson@arm.comMsgPtr
29210472Sandreas.hansson@arm.comclone() const
29310472Sandreas.hansson@arm.com{
29410472Sandreas.hansson@arm.com     return std::shared_ptr<Message>(new ${{self.c_ident}}(*this));
29510472Sandreas.hansson@arm.com}
29610472Sandreas.hansson@arm.com''')
29710472Sandreas.hansson@arm.com        else:
29810472Sandreas.hansson@arm.com            code('''
2997453Snate@binkert.org${{self.c_ident}}*
3007007Snate@binkert.orgclone() const
3017007Snate@binkert.org{
3027453Snate@binkert.org     return new ${{self.c_ident}}(*this);
3037007Snate@binkert.org}
3046657Snate@binkert.org''')
3056657Snate@binkert.org
3066657Snate@binkert.org        if not self.isGlobal:
3076657Snate@binkert.org            # const Get methods for each field
3086657Snate@binkert.org            code('// Const accessors methods for each field')
3096657Snate@binkert.org            for dm in self.data_members.values():
3106657Snate@binkert.org                code('''
3116657Snate@binkert.org/** \\brief Const accessor method for ${{dm.ident}} field.
3126657Snate@binkert.org *  \\return ${{dm.ident}} field
3136657Snate@binkert.org */
3147007Snate@binkert.orgconst ${{dm.type.c_ident}}&
3157007Snate@binkert.orgget${{dm.ident}}() const
3167007Snate@binkert.org{
3177007Snate@binkert.org    return m_${{dm.ident}};
3187007Snate@binkert.org}
3196657Snate@binkert.org''')
3206657Snate@binkert.org
3216657Snate@binkert.org            # Non-const Get methods for each field
3226657Snate@binkert.org            code('// Non const Accessors methods for each field')
3236657Snate@binkert.org            for dm in self.data_members.values():
3246657Snate@binkert.org                code('''
3256657Snate@binkert.org/** \\brief Non-const accessor method for ${{dm.ident}} field.
3266657Snate@binkert.org *  \\return ${{dm.ident}} field
3276657Snate@binkert.org */
3287007Snate@binkert.org${{dm.type.c_ident}}&
3297007Snate@binkert.orgget${{dm.ident}}()
3307007Snate@binkert.org{
3317007Snate@binkert.org    return m_${{dm.ident}};
3327007Snate@binkert.org}
3336657Snate@binkert.org''')
3346657Snate@binkert.org
3356657Snate@binkert.org            #Set methods for each field
3366657Snate@binkert.org            code('// Mutator methods for each field')
3376657Snate@binkert.org            for dm in self.data_members.values():
3386657Snate@binkert.org                code('''
3396657Snate@binkert.org/** \\brief Mutator method for ${{dm.ident}} field */
3407007Snate@binkert.orgvoid
3417007Snate@binkert.orgset${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
3427007Snate@binkert.org{
3437007Snate@binkert.org    m_${{dm.ident}} = local_${{dm.ident}};
3447007Snate@binkert.org}
3456657Snate@binkert.org''')
3466657Snate@binkert.org
3477002Snate@binkert.org        code('void print(std::ostream& out) const;')
3486657Snate@binkert.org        code.dedent()
3496657Snate@binkert.org        code('  //private:')
3506657Snate@binkert.org        code.indent()
3516657Snate@binkert.org
3526657Snate@binkert.org        # Data members for each field
3536657Snate@binkert.org        for dm in self.data_members.values():
3546657Snate@binkert.org            if "abstract" not in dm:
3556657Snate@binkert.org                const = ""
3566657Snate@binkert.org                init = ""
3576657Snate@binkert.org
3586657Snate@binkert.org                # global structure
3596657Snate@binkert.org                if self.isGlobal:
3606657Snate@binkert.org                    const = "static const "
3616657Snate@binkert.org
3626657Snate@binkert.org                # init value
3636657Snate@binkert.org                if dm.init_code:
3646657Snate@binkert.org                    # only global structure can have init value here
3656657Snate@binkert.org                    assert self.isGlobal
3666657Snate@binkert.org                    init = " = %s" % (dm.init_code)
3676657Snate@binkert.org
3686657Snate@binkert.org                if "desc" in dm:
3697007Snate@binkert.org                    code('/** ${{dm["desc"]}} */')
3706657Snate@binkert.org
3717007Snate@binkert.org                code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
3726657Snate@binkert.org
37310307Snilay@cs.wisc.edu        # Prototypes for methods defined for the Type
37410307Snilay@cs.wisc.edu        for item in self.methods:
37510307Snilay@cs.wisc.edu            proto = self.methods[item].prototype
3769298Snilay@cs.wisc.edu            if proto:
3779298Snilay@cs.wisc.edu                code('$proto')
3789298Snilay@cs.wisc.edu
3796657Snate@binkert.org        code.dedent()
3806657Snate@binkert.org        code('};')
3816657Snate@binkert.org
3826657Snate@binkert.org        code('''
3837055Snate@binkert.orginline std::ostream&
3847007Snate@binkert.orgoperator<<(std::ostream& out, const ${{self.c_ident}}& obj)
3856657Snate@binkert.org{
3866657Snate@binkert.org    obj.print(out);
3877002Snate@binkert.org    out << std::flush;
3886657Snate@binkert.org    return out;
3896657Snate@binkert.org}
3906657Snate@binkert.org
3917007Snate@binkert.org#endif // __${{self.c_ident}}_HH__
3926657Snate@binkert.org''')
3936657Snate@binkert.org
3946657Snate@binkert.org        code.write(path, "%s.hh" % self.c_ident)
3956657Snate@binkert.org
3966657Snate@binkert.org    def printTypeCC(self, path):
3976999Snate@binkert.org        code = self.symtab.codeFormatter()
3986657Snate@binkert.org
3996657Snate@binkert.org        code('''
4006657Snate@binkert.org/** \\file ${{self.c_ident}}.cc
4016657Snate@binkert.org *
4026657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
4036657Snate@binkert.org */
4046657Snate@binkert.org
4057002Snate@binkert.org#include <iostream>
40610472Sandreas.hansson@arm.com#include <memory>
4077002Snate@binkert.org
40814184Sgabeblack@google.com#include "mem/ruby/protocol/${{self.c_ident}}.hh"
40911108Sdavid.hashe@amd.com#include "mem/ruby/system/RubySystem.hh"
4107002Snate@binkert.org
4117002Snate@binkert.orgusing namespace std;
4126657Snate@binkert.org''')
4136657Snate@binkert.org
4146657Snate@binkert.org        code('''
4156657Snate@binkert.org/** \\brief Print the state of this object */
4167007Snate@binkert.orgvoid
4177007Snate@binkert.org${{self.c_ident}}::print(ostream& out) const
4186657Snate@binkert.org{
4196657Snate@binkert.org    out << "[${{self.c_ident}}: ";
4206657Snate@binkert.org''')
4216657Snate@binkert.org
4226657Snate@binkert.org        # For each field
4236657Snate@binkert.org        code.indent()
4246657Snate@binkert.org        for dm in self.data_members.values():
42511118Snilay@cs.wisc.edu            if dm.type.c_ident == "Addr":
42611118Snilay@cs.wisc.edu                code('''
42711118Snilay@cs.wisc.eduout << "${{dm.ident}} = " << printAddress(m_${{dm.ident}}) << " ";''')
42811118Snilay@cs.wisc.edu            else:
42911118Snilay@cs.wisc.edu                code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
4306657Snate@binkert.org
4316657Snate@binkert.org        code.dedent()
4326657Snate@binkert.org
4336657Snate@binkert.org        # Trailer
4346657Snate@binkert.org        code('''
4356657Snate@binkert.org    out << "]";
4366657Snate@binkert.org}''')
4376657Snate@binkert.org
43810307Snilay@cs.wisc.edu        # print the code for the methods in the type
43910307Snilay@cs.wisc.edu        for item in self.methods:
44010307Snilay@cs.wisc.edu            code(self.methods[item].generateCode())
4419298Snilay@cs.wisc.edu
4426657Snate@binkert.org        code.write(path, "%s.cc" % self.c_ident)
4436657Snate@binkert.org
4446657Snate@binkert.org    def printEnumHH(self, path):
4456999Snate@binkert.org        code = self.symtab.codeFormatter()
4466657Snate@binkert.org        code('''
4476657Snate@binkert.org/** \\file ${{self.c_ident}}.hh
4486657Snate@binkert.org *
4496657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
4506657Snate@binkert.org */
4517007Snate@binkert.org
4527007Snate@binkert.org#ifndef __${{self.c_ident}}_HH__
4537007Snate@binkert.org#define __${{self.c_ident}}_HH__
4546657Snate@binkert.org
4557002Snate@binkert.org#include <iostream>
4567002Snate@binkert.org#include <string>
4577002Snate@binkert.org
4588086SBrad.Beckmann@amd.com''')
4598086SBrad.Beckmann@amd.com        if self.isStateDecl:
46014184Sgabeblack@google.com            code('#include "mem/ruby/protocol/AccessPermission.hh"')
4618086SBrad.Beckmann@amd.com
4628602Snilay@cs.wisc.edu        if self.isMachineType:
46312065Snikos.nikoleris@arm.com            code('#include <functional>')
46412334Sgabeblack@google.com            code('#include "base/logging.hh"')
4658602Snilay@cs.wisc.edu            code('#include "mem/ruby/common/Address.hh"')
46611025Snilay@cs.wisc.edu            code('#include "mem/ruby/common/TypeDefines.hh"')
4678602Snilay@cs.wisc.edu            code('struct MachineID;')
4688602Snilay@cs.wisc.edu
4698086SBrad.Beckmann@amd.com        code('''
4706657Snate@binkert.org
4717007Snate@binkert.org// Class definition
4726657Snate@binkert.org/** \\enum ${{self.c_ident}}
4736657Snate@binkert.org *  \\brief ${{self.desc}}
4746657Snate@binkert.org */
4756657Snate@binkert.orgenum ${{self.c_ident}} {
4766657Snate@binkert.org    ${{self.c_ident}}_FIRST,
4776657Snate@binkert.org''')
4786657Snate@binkert.org
4796657Snate@binkert.org        code.indent()
4806657Snate@binkert.org        # For each field
4816657Snate@binkert.org        for i,(ident,enum) in enumerate(self.enums.iteritems()):
4826657Snate@binkert.org            desc = enum.get("desc", "No description avaliable")
48310917Sbrandon.potter@amd.com            if i == 0:
48410917Sbrandon.potter@amd.com                init = ' = %s_FIRST' % self.c_ident
4856862Sdrh5@cs.wisc.edu            else:
4866862Sdrh5@cs.wisc.edu                init = ''
4876657Snate@binkert.org            code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
4886657Snate@binkert.org        code.dedent()
4896657Snate@binkert.org        code('''
4906657Snate@binkert.org    ${{self.c_ident}}_NUM
4916657Snate@binkert.org};
4927007Snate@binkert.org
4937007Snate@binkert.org// Code to convert from a string to the enumeration
4947002Snate@binkert.org${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
4957007Snate@binkert.org
4967007Snate@binkert.org// Code to convert state to a string
4977002Snate@binkert.orgstd::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
4987007Snate@binkert.org
4997007Snate@binkert.org// Code to increment an enumeration type
5006657Snate@binkert.org${{self.c_ident}} &operator++(${{self.c_ident}} &e);
5016657Snate@binkert.org''')
5026657Snate@binkert.org
50312065Snikos.nikoleris@arm.com        if self.isMachineType:
50412065Snikos.nikoleris@arm.com            code('''
50512065Snikos.nikoleris@arm.com
50612065Snikos.nikoleris@arm.com// define a hash function for the MachineType class
50712065Snikos.nikoleris@arm.comnamespace std {
50812065Snikos.nikoleris@arm.comtemplate<>
50912065Snikos.nikoleris@arm.comstruct hash<MachineType> {
51012065Snikos.nikoleris@arm.com    std::size_t operator()(const MachineType &mtype) const {
51112065Snikos.nikoleris@arm.com        return hash<size_t>()(static_cast<size_t>(mtype));
51212065Snikos.nikoleris@arm.com    }
51312065Snikos.nikoleris@arm.com};
51412065Snikos.nikoleris@arm.com}
51512065Snikos.nikoleris@arm.com
51612065Snikos.nikoleris@arm.com''')
5176657Snate@binkert.org        # MachineType hack used to set the base component id for each Machine
5186657Snate@binkert.org        if self.isMachineType:
5196657Snate@binkert.org            code('''
5206657Snate@binkert.orgint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
5216657Snate@binkert.orgMachineType ${{self.c_ident}}_from_base_level(int);
5226657Snate@binkert.orgint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
5236657Snate@binkert.orgint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
5246657Snate@binkert.org''')
5256657Snate@binkert.org
5266657Snate@binkert.org            for enum in self.enums.itervalues():
5278602Snilay@cs.wisc.edu                code('''
5288602Snilay@cs.wisc.edu
5298602Snilay@cs.wisc.eduMachineID get${{enum.ident}}MachineID(NodeID RubyNode);
5308602Snilay@cs.wisc.edu''')
5318602Snilay@cs.wisc.edu
5328086SBrad.Beckmann@amd.com        if self.isStateDecl:
5338086SBrad.Beckmann@amd.com            code('''
5348086SBrad.Beckmann@amd.com
5358086SBrad.Beckmann@amd.com// Code to convert the current state to an access permission
5368086SBrad.Beckmann@amd.comAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
5378086SBrad.Beckmann@amd.com
5388086SBrad.Beckmann@amd.com''')
5398086SBrad.Beckmann@amd.com
5406657Snate@binkert.org        # Trailer
5416657Snate@binkert.org        code('''
5427002Snate@binkert.orgstd::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
5436657Snate@binkert.org
5447007Snate@binkert.org#endif // __${{self.c_ident}}_HH__
5456657Snate@binkert.org''')
5466657Snate@binkert.org
5476657Snate@binkert.org        code.write(path, "%s.hh" % self.c_ident)
5486657Snate@binkert.org
5496657Snate@binkert.org    def printEnumCC(self, path):
5506999Snate@binkert.org        code = self.symtab.codeFormatter()
5516657Snate@binkert.org        code('''
5526657Snate@binkert.org/** \\file ${{self.c_ident}}.hh
5536657Snate@binkert.org *
5546657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__
5556657Snate@binkert.org */
5566657Snate@binkert.org
5577832Snate@binkert.org#include <cassert>
5587002Snate@binkert.org#include <iostream>
5597002Snate@binkert.org#include <string>
5607002Snate@binkert.org
56112334Sgabeblack@google.com#include "base/logging.hh"
56214184Sgabeblack@google.com#include "mem/ruby/protocol/${{self.c_ident}}.hh"
5636657Snate@binkert.org
5647002Snate@binkert.orgusing namespace std;
5657002Snate@binkert.org
5666657Snate@binkert.org''')
5676657Snate@binkert.org
5688086SBrad.Beckmann@amd.com        if self.isStateDecl:
5698086SBrad.Beckmann@amd.com            code('''
5708086SBrad.Beckmann@amd.com// Code to convert the current state to an access permission
5718086SBrad.Beckmann@amd.comAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
5728086SBrad.Beckmann@amd.com{
5738086SBrad.Beckmann@amd.com    switch(obj) {
5748086SBrad.Beckmann@amd.com''')
5758086SBrad.Beckmann@amd.com            # For each case
5768086SBrad.Beckmann@amd.com            code.indent()
5778086SBrad.Beckmann@amd.com            for statePerm in self.statePermPairs:
5788086SBrad.Beckmann@amd.com                code('  case ${{self.c_ident}}_${{statePerm[0]}}:')
5798086SBrad.Beckmann@amd.com                code('    return AccessPermission_${{statePerm[1]}};')
5808086SBrad.Beckmann@amd.com            code.dedent()
5818086SBrad.Beckmann@amd.com            code ('''
5828086SBrad.Beckmann@amd.com      default:
5838086SBrad.Beckmann@amd.com        panic("Unknown state access permission converstion for ${{self.c_ident}}");
5848086SBrad.Beckmann@amd.com    }
5858086SBrad.Beckmann@amd.com}
5868086SBrad.Beckmann@amd.com
5878086SBrad.Beckmann@amd.com''')
5888086SBrad.Beckmann@amd.com
5896657Snate@binkert.org        if self.isMachineType:
5906657Snate@binkert.org            for enum in self.enums.itervalues():
59111283Santhony.gutierrez@amd.com                if enum.primary:
59214184Sgabeblack@google.com                    code('#include "mem/ruby/protocol/${{enum.ident}}'
59314184Sgabeblack@google.com                            '_Controller.hh"')
59410301Snilay@cs.wisc.edu            code('#include "mem/ruby/common/MachineID.hh"')
5956657Snate@binkert.org
5966657Snate@binkert.org        code('''
5977007Snate@binkert.org// Code for output operator
5987007Snate@binkert.orgostream&
5997007Snate@binkert.orgoperator<<(ostream& out, const ${{self.c_ident}}& obj)
6006657Snate@binkert.org{
6016657Snate@binkert.org    out << ${{self.c_ident}}_to_string(obj);
6026657Snate@binkert.org    out << flush;
6036657Snate@binkert.org    return out;
6046657Snate@binkert.org}
6056657Snate@binkert.org
6067007Snate@binkert.org// Code to convert state to a string
6077007Snate@binkert.orgstring
6087007Snate@binkert.org${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
6096657Snate@binkert.org{
6106657Snate@binkert.org    switch(obj) {
6116657Snate@binkert.org''')
6126657Snate@binkert.org
6136657Snate@binkert.org        # For each field
6146657Snate@binkert.org        code.indent()
6156657Snate@binkert.org        for enum in self.enums.itervalues():
6166657Snate@binkert.org            code('  case ${{self.c_ident}}_${{enum.ident}}:')
6176657Snate@binkert.org            code('    return "${{enum.ident}}";')
6186657Snate@binkert.org        code.dedent()
6196657Snate@binkert.org
6206657Snate@binkert.org        # Trailer
6216657Snate@binkert.org        code('''
6226657Snate@binkert.org      default:
6237805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
6246657Snate@binkert.org    }
6256657Snate@binkert.org}
6266657Snate@binkert.org
6277007Snate@binkert.org// Code to convert from a string to the enumeration
6287007Snate@binkert.org${{self.c_ident}}
6297007Snate@binkert.orgstring_to_${{self.c_ident}}(const string& str)
6306657Snate@binkert.org{
6316657Snate@binkert.org''')
6326657Snate@binkert.org
6336657Snate@binkert.org        # For each field
6347007Snate@binkert.org        start = ""
6356657Snate@binkert.org        code.indent()
6366657Snate@binkert.org        for enum in self.enums.itervalues():
6376657Snate@binkert.org            code('${start}if (str == "${{enum.ident}}") {')
6386657Snate@binkert.org            code('    return ${{self.c_ident}}_${{enum.ident}};')
6397007Snate@binkert.org            start = "} else "
6406657Snate@binkert.org        code.dedent()
6416657Snate@binkert.org
6426657Snate@binkert.org        code('''
6436657Snate@binkert.org    } else {
6447805Snilay@cs.wisc.edu        panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
6456657Snate@binkert.org    }
6466657Snate@binkert.org}
6476657Snate@binkert.org
6487007Snate@binkert.org// Code to increment an enumeration type
6497007Snate@binkert.org${{self.c_ident}}&
6507007Snate@binkert.orgoperator++(${{self.c_ident}}& e)
6517007Snate@binkert.org{
6526657Snate@binkert.org    assert(e < ${{self.c_ident}}_NUM);
6536657Snate@binkert.org    return e = ${{self.c_ident}}(e+1);
6546657Snate@binkert.org}
6556657Snate@binkert.org''')
6566657Snate@binkert.org
6576657Snate@binkert.org        # MachineType hack used to set the base level and number of
6586657Snate@binkert.org        # components for each Machine
6596657Snate@binkert.org        if self.isMachineType:
6606657Snate@binkert.org            code('''
6617007Snate@binkert.org/** \\brief returns the base vector index for each machine type to be
6627007Snate@binkert.org  * used by NetDest
6636657Snate@binkert.org  *
6646657Snate@binkert.org  * \\return the base vector index for each machine type to be used by NetDest
6656657Snate@binkert.org  * \\see NetDest.hh
6666657Snate@binkert.org  */
6677007Snate@binkert.orgint
6687007Snate@binkert.org${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
6696657Snate@binkert.org{
6706657Snate@binkert.org    switch(obj) {
6716657Snate@binkert.org''')
6726657Snate@binkert.org
6736657Snate@binkert.org            # For each field
6746657Snate@binkert.org            code.indent()
6756657Snate@binkert.org            for i,enum in enumerate(self.enums.itervalues()):
6766657Snate@binkert.org                code('  case ${{self.c_ident}}_${{enum.ident}}:')
6776657Snate@binkert.org                code('    return $i;')
6786657Snate@binkert.org            code.dedent()
6796657Snate@binkert.org
6806657Snate@binkert.org            # total num
6816657Snate@binkert.org            code('''
6826657Snate@binkert.org      case ${{self.c_ident}}_NUM:
6836657Snate@binkert.org        return ${{len(self.enums)}};
6846657Snate@binkert.org
6856657Snate@binkert.org      default:
6867805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
6876657Snate@binkert.org    }
6886657Snate@binkert.org}
6896657Snate@binkert.org
6906657Snate@binkert.org/** \\brief returns the machine type for each base vector index used by NetDest
6916657Snate@binkert.org *
6927007Snate@binkert.org * \\return the MachineType
6936657Snate@binkert.org */
6947007Snate@binkert.orgMachineType
6957007Snate@binkert.org${{self.c_ident}}_from_base_level(int type)
6966657Snate@binkert.org{
6976657Snate@binkert.org    switch(type) {
6986657Snate@binkert.org''')
6996657Snate@binkert.org
7006657Snate@binkert.org            # For each field
7016657Snate@binkert.org            code.indent()
7026657Snate@binkert.org            for i,enum in enumerate(self.enums.itervalues()):
7036657Snate@binkert.org                code('  case $i:')
7046657Snate@binkert.org                code('    return ${{self.c_ident}}_${{enum.ident}};')
7056657Snate@binkert.org            code.dedent()
7066657Snate@binkert.org
7076657Snate@binkert.org            # Trailer
7086657Snate@binkert.org            code('''
7096657Snate@binkert.org      default:
7107805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
7116657Snate@binkert.org    }
7126657Snate@binkert.org}
7136657Snate@binkert.org
7146657Snate@binkert.org/** \\brief The return value indicates the number of components created
7156657Snate@binkert.org * before a particular machine\'s components
7166657Snate@binkert.org *
7176657Snate@binkert.org * \\return the base number of components for each machine
7186657Snate@binkert.org */
7197007Snate@binkert.orgint
7207007Snate@binkert.org${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
7216657Snate@binkert.org{
7226657Snate@binkert.org    int base = 0;
7236657Snate@binkert.org    switch(obj) {
7246657Snate@binkert.org''')
7256657Snate@binkert.org
7266657Snate@binkert.org            # For each field
7276657Snate@binkert.org            code.indent()
7286657Snate@binkert.org            code('  case ${{self.c_ident}}_NUM:')
72913709Sandreas.sandberg@arm.com            for enum in reversed(list(self.enums.values())):
7309773Snilay@cs.wisc.edu                # Check if there is a defined machine with this type
73111283Santhony.gutierrez@amd.com                if enum.primary:
7329773Snilay@cs.wisc.edu                    code('    base += ${{enum.ident}}_Controller::getNumControllers();')
7339773Snilay@cs.wisc.edu                else:
7349773Snilay@cs.wisc.edu                    code('    base += 0;')
73512392Sjason@lowepower.com                code('    M5_FALLTHROUGH;')
7366657Snate@binkert.org                code('  case ${{self.c_ident}}_${{enum.ident}}:')
7376657Snate@binkert.org            code('    break;')
7386657Snate@binkert.org            code.dedent()
7396657Snate@binkert.org
7406657Snate@binkert.org            code('''
7416657Snate@binkert.org      default:
7427805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
7436657Snate@binkert.org    }
7446657Snate@binkert.org
7456657Snate@binkert.org    return base;
7466657Snate@binkert.org}
7476657Snate@binkert.org
7486657Snate@binkert.org/** \\brief returns the total number of components for each machine
7496657Snate@binkert.org * \\return the total number of components for each machine
7506657Snate@binkert.org */
7517007Snate@binkert.orgint
7527007Snate@binkert.org${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
7536657Snate@binkert.org{
7546657Snate@binkert.org    switch(obj) {
7556657Snate@binkert.org''')
7566657Snate@binkert.org
7576657Snate@binkert.org            # For each field
7586657Snate@binkert.org            for enum in self.enums.itervalues():
7599773Snilay@cs.wisc.edu                code('case ${{self.c_ident}}_${{enum.ident}}:')
76011283Santhony.gutierrez@amd.com                if enum.primary:
7619773Snilay@cs.wisc.edu                    code('return ${{enum.ident}}_Controller::getNumControllers();')
7629773Snilay@cs.wisc.edu                else:
7639773Snilay@cs.wisc.edu                    code('return 0;')
7646657Snate@binkert.org
7656657Snate@binkert.org            # total num
7666657Snate@binkert.org            code('''
7676657Snate@binkert.org      case ${{self.c_ident}}_NUM:
7686657Snate@binkert.org      default:
7697805Snilay@cs.wisc.edu        panic("Invalid range for type ${{self.c_ident}}");
7706657Snate@binkert.org    }
7716657Snate@binkert.org}
7726657Snate@binkert.org''')
7736657Snate@binkert.org
7748602Snilay@cs.wisc.edu            for enum in self.enums.itervalues():
7758602Snilay@cs.wisc.edu                code('''
7768602Snilay@cs.wisc.edu
7778602Snilay@cs.wisc.eduMachineID
7788602Snilay@cs.wisc.eduget${{enum.ident}}MachineID(NodeID RubyNode)
7798602Snilay@cs.wisc.edu{
7808602Snilay@cs.wisc.edu      MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
7818602Snilay@cs.wisc.edu      return mach;
7828602Snilay@cs.wisc.edu}
7838602Snilay@cs.wisc.edu''')
7848602Snilay@cs.wisc.edu
7856657Snate@binkert.org        # Write the file
7866657Snate@binkert.org        code.write(path, "%s.cc" % self.c_ident)
7876657Snate@binkert.org
7886657Snate@binkert.org__all__ = [ "Type" ]
789