Type.py revision 7002
19814Sandreas.hansson@arm.com# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
22292SN/A# Copyright (c) 2009 The Hewlett-Packard Development Company
310333Smitch.hayenga@arm.com# All rights reserved.
410239Sbinhpham@cs.rutgers.edu#
57597Sminkyu.jeong@arm.com# Redistribution and use in source and binary forms, with or without
67597Sminkyu.jeong@arm.com# modification, are permitted provided that the following conditions are
77597Sminkyu.jeong@arm.com# met: redistributions of source code must retain the above copyright
87597Sminkyu.jeong@arm.com# notice, this list of conditions and the following disclaimer;
97597Sminkyu.jeong@arm.com# redistributions in binary form must reproduce the above copyright
107597Sminkyu.jeong@arm.com# notice, this list of conditions and the following disclaimer in the
117597Sminkyu.jeong@arm.com# documentation and/or other materials provided with the distribution;
127597Sminkyu.jeong@arm.com# neither the name of the copyright holders nor the names of its
137597Sminkyu.jeong@arm.com# contributors may be used to endorse or promote products derived from
147597Sminkyu.jeong@arm.com# this software without specific prior written permission.
157597Sminkyu.jeong@arm.com#
162292SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172292SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182292SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192292SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202292SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212292SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222292SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232292SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242292SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252292SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262292SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272292SN/A
282292SN/Afrom m5.util import orderdict
292292SN/A
302292SN/Afrom slicc.util import PairContainer
312292SN/Afrom slicc.symbols.Symbol import Symbol
322292SN/A
332292SN/Aclass DataMember(PairContainer):
342292SN/A    def __init__(self, ident, type, pairs, init_code):
352292SN/A        super(DataMember, self).__init__(pairs)
362292SN/A        self.ident = ident
372292SN/A        self.type = type
382292SN/A        self.init_code = init_code
392292SN/A
402292SN/Aclass Enumeration(PairContainer):
412689Sktlim@umich.edu    def __init__(self, ident, pairs):
422689Sktlim@umich.edu        super(Enumeration, self).__init__(pairs)
432689Sktlim@umich.edu        self.ident = ident
442292SN/A
452292SN/Aclass Method(object):
469944Smatt.horsnell@ARM.com    def __init__(self, return_type, param_types):
479944Smatt.horsnell@ARM.com        self.return_type = return_type
489944Smatt.horsnell@ARM.com        self.param_types = param_types
498591Sgblack@eecs.umich.edu
503326Sktlim@umich.educlass Type(Symbol):
518229Snate@binkert.org    def __init__(self, table, ident, location, pairs, machine=None):
526658Snate@binkert.org        super(Type, self).__init__(table, ident, location, pairs)
538887Sgeoffrey.blake@arm.com        self.c_ident = ident
542907Sktlim@umich.edu        self.abstract_ident = ""
552292SN/A        if machine:
568232Snate@binkert.org            if self.isExternal or self.isPrimitive:
578232Snate@binkert.org                if "external_name" in self:
588232Snate@binkert.org                    self.c_ident = self["external_name"]
599527SMatt.Horsnell@arm.com            else:
602722Sktlim@umich.edu                # Append with machine name
612669Sktlim@umich.edu                self.c_ident = "%s_%s" % (machine, ident)
622292SN/A
632669Sktlim@umich.edu        self.pairs.setdefault("desc", "No description avaliable")
642678Sktlim@umich.edu
652678Sktlim@umich.edu        # check for interface that this Type implements
668581Ssteve.reinhardt@amd.com        if "interface" in self:
678581Ssteve.reinhardt@amd.com            interface = self["interface"]
682292SN/A            if interface in ("Message", "NetworkMessage"):
692292SN/A                self["message"] = "yes"
702292SN/A            if interface == "NetworkMessage":
712669Sktlim@umich.edu                self["networkmessage"] = "yes"
722292SN/A
732678Sktlim@umich.edu        # FIXME - all of the following id comparisons are fragile hacks
742292SN/A        if self.ident in ("CacheMemory", "NewCacheMemory",
759444SAndreas.Sandberg@ARM.com                          "TLCCacheMemory", "DNUCACacheMemory",
769444SAndreas.Sandberg@ARM.com                          "DNUCABankCacheMemory", "L2BankCacheMemory",
779444SAndreas.Sandberg@ARM.com                          "CompressedCacheMemory", "PrefetchCacheMemory"):
784319Sktlim@umich.edu            self["cache"] = "yes"
794319Sktlim@umich.edu
804319Sktlim@umich.edu        if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
814319Sktlim@umich.edu            self["tbe"] = "yes"
824319Sktlim@umich.edu
832678Sktlim@umich.edu        if self.ident == "NewTBETable":
842678Sktlim@umich.edu            self["newtbe"] = "yes"
852292SN/A
862678Sktlim@umich.edu        if self.ident == "TimerTable":
872678Sktlim@umich.edu            self["timer"] = "yes"
885336Shines@cs.fsu.edu
892678Sktlim@umich.edu        if self.ident == "DirectoryMemory":
904873Sstever@eecs.umich.edu            self["dir"] = "yes"
912678Sktlim@umich.edu
922292SN/A        if self.ident == "PersistentTable":
932678Sktlim@umich.edu            self["persistent"] = "yes"
942678Sktlim@umich.edu
952678Sktlim@umich.edu        if self.ident == "Prefetcher":
962678Sktlim@umich.edu            self["prefetcher"] = "yes"
972678Sktlim@umich.edu
982678Sktlim@umich.edu        if self.ident == "DNUCA_Movement":
997852SMatt.Horsnell@arm.com            self["mover"] = "yes"
1007852SMatt.Horsnell@arm.com
1012344SN/A        self.isMachineType = (ident == "MachineType")
10210333Smitch.hayenga@arm.com
10310333Smitch.hayenga@arm.com        self.data_members = orderdict()
10410333Smitch.hayenga@arm.com
10510333Smitch.hayenga@arm.com        # Methods
10610333Smitch.hayenga@arm.com        self.methods = {}
10710333Smitch.hayenga@arm.com
10810333Smitch.hayenga@arm.com        # Enums
10910333Smitch.hayenga@arm.com        self.enums = orderdict()
11010333Smitch.hayenga@arm.com
11110333Smitch.hayenga@arm.com    @property
1122678Sktlim@umich.edu    def isPrimitive(self):
1136974Stjones1@inf.ed.ac.uk        return "primitive" in self
1146974Stjones1@inf.ed.ac.uk    @property
1156974Stjones1@inf.ed.ac.uk    def isNetworkMessage(self):
1166974Stjones1@inf.ed.ac.uk        return "networkmessage" in self
1176974Stjones1@inf.ed.ac.uk    @property
1186974Stjones1@inf.ed.ac.uk    def isMessage(self):
1196974Stjones1@inf.ed.ac.uk        return "message" in self
1209444SAndreas.Sandberg@ARM.com    @property
12110327Smitch.hayenga@arm.com    def isBuffer(self):
1222678Sktlim@umich.edu        return "buffer" in self
1236974Stjones1@inf.ed.ac.uk    @property
1246974Stjones1@inf.ed.ac.uk    def isInPort(self):
1256974Stjones1@inf.ed.ac.uk        return "inport" in self
1266974Stjones1@inf.ed.ac.uk    @property
1276974Stjones1@inf.ed.ac.uk    def isOutPort(self):
1286974Stjones1@inf.ed.ac.uk        return "outport" in self
1292678Sktlim@umich.edu    @property
1302678Sktlim@umich.edu    def isEnumeration(self):
1312678Sktlim@umich.edu        return "enumeration" in self
1322678Sktlim@umich.edu    @property
1332678Sktlim@umich.edu    def isExternal(self):
1342344SN/A        return "external" in self
1352307SN/A    @property
1366974Stjones1@inf.ed.ac.uk    def isGlobal(self):
1376974Stjones1@inf.ed.ac.uk        return "global" in self
1386974Stjones1@inf.ed.ac.uk    @property
1396974Stjones1@inf.ed.ac.uk    def isInterface(self):
14010020Smatt.horsnell@ARM.com        return "interface" in self
14110020Smatt.horsnell@ARM.com
14210023Smatt.horsnell@ARM.com    # Return false on error
14310023Smatt.horsnell@ARM.com    def dataMemberAdd(self, ident, type, pairs, init_code):
1442678Sktlim@umich.edu        if ident in self.data_members:
1454032Sktlim@umich.edu            return False
1462678Sktlim@umich.edu
1472292SN/A        member = DataMember(ident, type, pairs, init_code)
1482292SN/A        self.data_members[ident] = member
1492292SN/A
1502292SN/A        return True
1518545Ssaidi@eecs.umich.edu
15210333Smitch.hayenga@arm.com    def dataMemberType(self, ident):
1532292SN/A        return self.data_members[ident].type
1542292SN/A
1552292SN/A    def methodId(self, name, param_type_vec):
1562292SN/A        return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
1572292SN/A
1585529Snate@binkert.org    def methodIdAbstract(self, name, param_type_vec):
1595529Snate@binkert.org        return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
1605529Snate@binkert.org
1612292SN/A    def methodAdd(self, name, return_type, param_type_vec):
1624329Sktlim@umich.edu        ident = self.methodId(name, param_type_vec)
1634329Sktlim@umich.edu        if ident in self.methods:
1644329Sktlim@umich.edu            return False
1652907Sktlim@umich.edu
1662907Sktlim@umich.edu        self.methods[ident] = Method(return_type, param_type_vec)
1672292SN/A        return True
1682292SN/A
16910175SMitch.Hayenga@ARM.com    def enumAdd(self, ident, pairs):
17010175SMitch.Hayenga@ARM.com        if ident in self.enums:
1712329SN/A            return False
1722329SN/A
1732329SN/A        self.enums[ident] = Enumeration(ident, pairs)
1742292SN/A
1759936SFaissal.Sleiman@arm.com        # Add default
1769936SFaissal.Sleiman@arm.com        if "default" not in self:
1779936SFaissal.Sleiman@arm.com            self["default"] = "%s_NUM" % self.c_ident
1789936SFaissal.Sleiman@arm.com
1792292SN/A        return True
1802292SN/A
1812292SN/A    def writeCodeFiles(self, path):
1828199SAli.Saidi@ARM.com        if self.isExternal:
1838199SAli.Saidi@ARM.com            # Do nothing
1849444SAndreas.Sandberg@ARM.com            pass
1859444SAndreas.Sandberg@ARM.com        elif self.isEnumeration:
1869444SAndreas.Sandberg@ARM.com            self.printEnumHH(path)
1879444SAndreas.Sandberg@ARM.com            self.printEnumCC(path)
1889444SAndreas.Sandberg@ARM.com        else:
1899444SAndreas.Sandberg@ARM.com            # User defined structs and messages
1909444SAndreas.Sandberg@ARM.com            self.printTypeHH(path)
1919444SAndreas.Sandberg@ARM.com            self.printTypeCC(path)
1929444SAndreas.Sandberg@ARM.com
1939444SAndreas.Sandberg@ARM.com    def printTypeHH(self, path):
1949444SAndreas.Sandberg@ARM.com        code = self.symtab.codeFormatter()
1959444SAndreas.Sandberg@ARM.com        code('''
1968199SAli.Saidi@ARM.com/** \\file ${{self.c_ident}}.hh
1972292SN/A *
1982292SN/A *
1992292SN/A * Auto generated C++ code started by $__file__:$__line__
2002292SN/A */
2012292SN/A
2022292SN/A#ifndef ${{self.c_ident}}_H
2033492Sktlim@umich.edu#define ${{self.c_ident}}_H
2042329SN/A
2052292SN/A#include <iostream>
2069444SAndreas.Sandberg@ARM.com
2079444SAndreas.Sandberg@ARM.com#include "mem/ruby/common/Global.hh"
2089814Sandreas.hansson@arm.com#include "mem/gems_common/Allocator.hh"
2092292SN/A''')
2102292SN/A
2112292SN/A        for dm in self.data_members.values():
2122292SN/A            if not dm.type.isPrimitive:
2132292SN/A                code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
2142292SN/A
2152292SN/A        parent = ""
2162292SN/A        if "interface" in self:
2172292SN/A            code('#include "mem/protocol/$0.hh"', self["interface"])
2188247Snate@binkert.org            parent = " :  public %s" % self["interface"]
2192292SN/A
2202292SN/A        code('''
2212292SN/A$klass ${{self.c_ident}}$parent {
2222292SN/A  public:
2232292SN/A    ${{self.c_ident}}()
2242727Sktlim@umich.edu''', klass="class")
2252727Sktlim@umich.edu
2262727Sktlim@umich.edu        # Call superclass constructor
2272727Sktlim@umich.edu        if "interface" in self:
2282727Sktlim@umich.edu            code('        : ${{self["interface"]}}()')
2292727Sktlim@umich.edu
2302727Sktlim@umich.edu        code.indent()
2312727Sktlim@umich.edu        code("{")
2322727Sktlim@umich.edu        if not self.isGlobal:
2332727Sktlim@umich.edu            code.indent()
2342727Sktlim@umich.edu            for dm in self.data_members.values():
2352727Sktlim@umich.edu                ident = dm.ident
2362727Sktlim@umich.edu                if "default" in dm:
2372727Sktlim@umich.edu                    # look for default value
2382727Sktlim@umich.edu                    code('m_$ident = ${{dm["default"]}}; // default for this field')
2392727Sktlim@umich.edu                elif "default" in dm.type:
2402727Sktlim@umich.edu                    # Look for the type default
2412727Sktlim@umich.edu                    tid = dm.type.c_ident
2422361SN/A                    code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
2432361SN/A                else:
2442361SN/A                    code('// m_$ident has no default')
2452361SN/A            code.dedent()
2462727Sktlim@umich.edu        code('}')
2472727Sktlim@umich.edu
2482727Sktlim@umich.edu        # ******** Default destructor ********
2492727Sktlim@umich.edu        code('~${{self.c_ident}}() { };')
2502727Sktlim@umich.edu
2512727Sktlim@umich.edu        # ******** Full init constructor ********
2522727Sktlim@umich.edu        if not self.isGlobal:
2532727Sktlim@umich.edu            params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
2542727Sktlim@umich.edu                       for dm in self.data_members.itervalues() ]
2552727Sktlim@umich.edu
2562727Sktlim@umich.edu            if self.isMessage:
2572727Sktlim@umich.edu                params.append('const unsigned local_proc_id')
2582727Sktlim@umich.edu
2592727Sktlim@umich.edu            params = ', '.join(params)
2602727Sktlim@umich.edu            code('${{self.c_ident}}($params)')
2612727Sktlim@umich.edu
2622727Sktlim@umich.edu            # Call superclass constructor
2632727Sktlim@umich.edu            if "interface" in self:
2642727Sktlim@umich.edu                code('    : ${{self["interface"]}}()')
2652727Sktlim@umich.edu
2662727Sktlim@umich.edu            code('{')
2672727Sktlim@umich.edu            code.indent()
2682727Sktlim@umich.edu            for dm in self.data_members.values():
2698922Swilliam.wang@arm.com                code('m_${{dm.ident}} = local_${{dm.ident}};')
2704329Sktlim@umich.edu                if "nextLineCallHack" in dm:
2714329Sktlim@umich.edu                    code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
2724329Sktlim@umich.edu
2734329Sktlim@umich.edu            if self.isMessage:
2744329Sktlim@umich.edu                code('proc_id = local_proc_id;')
2754329Sktlim@umich.edu
2762292SN/A            code.dedent()
2772292SN/A            code('}')
2782292SN/A
2792292SN/A        # create a static factory method
2802292SN/A        if "interface" in self:
2812292SN/A            code('''
2822292SN/Astatic ${{self["interface"]}}* create() {
2832292SN/A    return new ${{self.c_ident}}();
2842292SN/A}
2852292SN/A''')
2862292SN/A
2872292SN/A        # ******** Message member functions ********
2882292SN/A        # FIXME: those should be moved into slicc file, slicc should
2892292SN/A        # support more of the c++ class inheritance
2909444SAndreas.Sandberg@ARM.com
2912307SN/A        if self.isMessage:
2929444SAndreas.Sandberg@ARM.com            code('''
2932367SN/AMessage* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }
2942307SN/Avoid destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }
2952329SN/Astatic Allocator<${{self.c_ident}}>* s_allocator_ptr;
2969444SAndreas.Sandberg@ARM.comstatic void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }}
2972307SN/A''')
2982307SN/A
2992307SN/A        if not self.isGlobal:
3002307SN/A            # const Get methods for each field
3012307SN/A            code('// Const accessors methods for each field')
3022307SN/A            for dm in self.data_members.values():
3039444SAndreas.Sandberg@ARM.com                code('''
3042307SN/A/** \\brief Const accessor method for ${{dm.ident}} field.
3052307SN/A *  \\return ${{dm.ident}} field
3062307SN/A */
3072307SN/Aconst ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; }
3082292SN/A''')
3092292SN/A
3102329SN/A            # Non-const Get methods for each field
3112329SN/A            code('// Non const Accessors methods for each field')
3122292SN/A            for dm in self.data_members.values():
3132329SN/A                code('''
3142329SN/A/** \\brief Non-const accessor method for ${{dm.ident}} field.
3152292SN/A *  \\return ${{dm.ident}} field
3162292SN/A */
3172292SN/A${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; }
3182292SN/A''')
3192292SN/A
3202329SN/A            #Set methods for each field
3212292SN/A            code('// Mutator methods for each field')
3222292SN/A            for dm in self.data_members.values():
3239936SFaissal.Sleiman@arm.com                code('''
3242292SN/A/** \\brief Mutator method for ${{dm.ident}} field */
3252292SN/Avoid set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; }
3262292SN/A''')
3272292SN/A
3282292SN/A        code('void print(std::ostream& out) const;')
3292292SN/A        code.dedent()
3302329SN/A        code('  //private:')
3312329SN/A        code.indent()
3322329SN/A
3332292SN/A        # Data members for each field
3342292SN/A        for dm in self.data_members.values():
3352292SN/A            if "abstract" not in dm:
3362292SN/A                const = ""
3372292SN/A                init = ""
3382329SN/A
3392292SN/A                # global structure
3409936SFaissal.Sleiman@arm.com                if self.isGlobal:
3419936SFaissal.Sleiman@arm.com                    const = "static const "
3422292SN/A
3432292SN/A                # init value
3442292SN/A                if dm.init_code:
3452292SN/A                    # only global structure can have init value here
3462292SN/A                    assert self.isGlobal
3472292SN/A                    init = " = %s" % (dm.init_code)
3482292SN/A
3492292SN/A                desc = ""
3502292SN/A                if "desc" in dm:
3512292SN/A                    desc = '/**< %s */' % dm["desc"]
3522292SN/A
3532292SN/A                code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc')
3542292SN/A
3552292SN/A        if self.isMessage:
3562292SN/A            code('unsigned proc_id;')
3572292SN/A
3582292SN/A        code.dedent()
3592292SN/A        code('};')
3602292SN/A
3612292SN/A        code('''
3622292SN/A// Output operator declaration
3632292SN/Astd::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
3642292SN/A
3652329SN/A// Output operator definition
3662329SN/Aextern inline
3672292SN/Astd::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
3687720Sgblack@eecs.umich.edu{
3697720Sgblack@eecs.umich.edu    obj.print(out);
3702292SN/A    out << std::flush;
3712292SN/A    return out;
3722292SN/A}
3732292SN/A
3742292SN/A#endif // ${{self.c_ident}}_H
3752292SN/A''')
3762292SN/A
3772292SN/A        code.write(path, "%s.hh" % self.c_ident)
3782292SN/A
3792292SN/A    def printTypeCC(self, path):
3802292SN/A        code = self.symtab.codeFormatter()
3812292SN/A
3822292SN/A        code('''
3832292SN/A/** \\file ${{self.c_ident}}.cc
3842292SN/A *
3852292SN/A * Auto generated C++ code started by $__file__:$__line__
3862292SN/A */
3872292SN/A
3882292SN/A#include <iostream>
3892292SN/A
3902292SN/A#include "mem/protocol/${{self.c_ident}}.hh"
3912292SN/A
3922292SN/Ausing namespace std;
3932292SN/A''')
3947720Sgblack@eecs.umich.edu
3957720Sgblack@eecs.umich.edu        if self.isMessage:
3962292SN/A            code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;')
3972292SN/A        code('''
3982292SN/A/** \\brief Print the state of this object */
3992292SN/Avoid ${{self.c_ident}}::print(ostream& out) const
4002292SN/A{
4012292SN/A    out << "[${{self.c_ident}}: ";
4022292SN/A''')
4032292SN/A
4042292SN/A        # For each field
4052292SN/A        code.indent()
4062292SN/A        for dm in self.data_members.values():
4072292SN/A            code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
4082292SN/A
4092292SN/A        if self.isMessage:
4102292SN/A            code('out << "Time = " << getTime() << " ";')
4112292SN/A        code.dedent()
4122292SN/A
4132292SN/A        # Trailer
4142292SN/A        code('''
4152292SN/A    out << "]";
4162292SN/A}''')
4172292SN/A
4182292SN/A        code.write(path, "%s.cc" % self.c_ident)
4192292SN/A
42010239Sbinhpham@cs.rutgers.edu    def printEnumHH(self, path):
4212292SN/A        code = self.symtab.codeFormatter()
42210239Sbinhpham@cs.rutgers.edu        code('''
42310239Sbinhpham@cs.rutgers.edu/** \\file ${{self.c_ident}}.hh
42410239Sbinhpham@cs.rutgers.edu *
42510239Sbinhpham@cs.rutgers.edu * Auto generated C++ code started by $__file__:$__line__
42610239Sbinhpham@cs.rutgers.edu */
4272292SN/A#ifndef ${{self.c_ident}}_H
42810239Sbinhpham@cs.rutgers.edu#define ${{self.c_ident}}_H
42910239Sbinhpham@cs.rutgers.edu
43010239Sbinhpham@cs.rutgers.edu#include <iostream>
43110239Sbinhpham@cs.rutgers.edu#include <string>
43210239Sbinhpham@cs.rutgers.edu
43310239Sbinhpham@cs.rutgers.edu#include "mem/ruby/common/Global.hh"
43410239Sbinhpham@cs.rutgers.edu
43510239Sbinhpham@cs.rutgers.edu/** \\enum ${{self.c_ident}}
43610239Sbinhpham@cs.rutgers.edu *  \\brief ${{self.desc}}
43710239Sbinhpham@cs.rutgers.edu */
4382292SN/Aenum ${{self.c_ident}} {
4392292SN/A    ${{self.c_ident}}_FIRST,
4408545Ssaidi@eecs.umich.edu''')
4418545Ssaidi@eecs.umich.edu
4428545Ssaidi@eecs.umich.edu        code.indent()
4438545Ssaidi@eecs.umich.edu        # For each field
44410030SAli.Saidi@ARM.com        for i,(ident,enum) in enumerate(self.enums.iteritems()):
4458545Ssaidi@eecs.umich.edu            desc = enum.get("desc", "No description avaliable")
4469383SAli.Saidi@ARM.com            if i == 0:
4479383SAli.Saidi@ARM.com                init = ' = %s_FIRST' % self.c_ident
4489383SAli.Saidi@ARM.com            else:
4499383SAli.Saidi@ARM.com                init = ''
45010030SAli.Saidi@ARM.com            code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
4519383SAli.Saidi@ARM.com        code.dedent()
4529383SAli.Saidi@ARM.com        code('''
4539383SAli.Saidi@ARM.com    ${{self.c_ident}}_NUM
4549383SAli.Saidi@ARM.com};
4559383SAli.Saidi@ARM.com${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
4569383SAli.Saidi@ARM.comstd::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
4579383SAli.Saidi@ARM.com${{self.c_ident}} &operator++(${{self.c_ident}} &e);
45810030SAli.Saidi@ARM.com''')
45910030SAli.Saidi@ARM.com
46010030SAli.Saidi@ARM.com        # MachineType hack used to set the base component id for each Machine
46110030SAli.Saidi@ARM.com        if self.isMachineType:
46210030SAli.Saidi@ARM.com            code('''
46310030SAli.Saidi@ARM.comint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
46410030SAli.Saidi@ARM.comMachineType ${{self.c_ident}}_from_base_level(int);
46510030SAli.Saidi@ARM.comint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
46610030SAli.Saidi@ARM.comint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
46710030SAli.Saidi@ARM.com''')
46810030SAli.Saidi@ARM.com
4698545Ssaidi@eecs.umich.edu            for enum in self.enums.itervalues():
4708545Ssaidi@eecs.umich.edu                code('#define MACHINETYPE_${{enum.ident}} 1')
4718545Ssaidi@eecs.umich.edu
47210030SAli.Saidi@ARM.com        # Trailer
4738545Ssaidi@eecs.umich.edu        code('''
4748545Ssaidi@eecs.umich.edustd::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
47510149Smarco.elver@ed.ac.uk
47610149Smarco.elver@ed.ac.uk#endif // ${{self.c_ident}}_H
4778545Ssaidi@eecs.umich.edu''')
4788545Ssaidi@eecs.umich.edu
4798545Ssaidi@eecs.umich.edu        code.write(path, "%s.hh" % self.c_ident)
4809046SAli.Saidi@ARM.com
4818545Ssaidi@eecs.umich.edu    def printEnumCC(self, path):
4828545Ssaidi@eecs.umich.edu        code = self.symtab.codeFormatter()
4838545Ssaidi@eecs.umich.edu        code('''
4848545Ssaidi@eecs.umich.edu/** \\file ${{self.c_ident}}.hh
4858545Ssaidi@eecs.umich.edu *
4868545Ssaidi@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__
4878545Ssaidi@eecs.umich.edu */
4888545Ssaidi@eecs.umich.edu
48910149Smarco.elver@ed.ac.uk#include <iostream>
49010149Smarco.elver@ed.ac.uk#include <string>
49110149Smarco.elver@ed.ac.uk
49210149Smarco.elver@ed.ac.uk#include "mem/protocol/${{self.c_ident}}.hh"
49310149Smarco.elver@ed.ac.uk
49410149Smarco.elver@ed.ac.ukusing namespace std;
49510149Smarco.elver@ed.ac.uk
49610149Smarco.elver@ed.ac.uk''')
4978545Ssaidi@eecs.umich.edu
49810030SAli.Saidi@ARM.com        if self.isMachineType:
4998545Ssaidi@eecs.umich.edu            for enum in self.enums.itervalues():
5008545Ssaidi@eecs.umich.edu                code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
5018545Ssaidi@eecs.umich.edu
5028545Ssaidi@eecs.umich.edu        code('''
50310030SAli.Saidi@ARM.comostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
50410030SAli.Saidi@ARM.com{
50510030SAli.Saidi@ARM.com    out << ${{self.c_ident}}_to_string(obj);
50610030SAli.Saidi@ARM.com    out << flush;
50710030SAli.Saidi@ARM.com    return out;
50810030SAli.Saidi@ARM.com}
50910030SAli.Saidi@ARM.com
51010030SAli.Saidi@ARM.comstring ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
51110030SAli.Saidi@ARM.com{
5128545Ssaidi@eecs.umich.edu    switch(obj) {
5138545Ssaidi@eecs.umich.edu''')
5148545Ssaidi@eecs.umich.edu
5159046SAli.Saidi@ARM.com        # For each field
5168545Ssaidi@eecs.umich.edu        code.indent()
5178545Ssaidi@eecs.umich.edu        for enum in self.enums.itervalues():
5188545Ssaidi@eecs.umich.edu            code('  case ${{self.c_ident}}_${{enum.ident}}:')
5198545Ssaidi@eecs.umich.edu            code('    return "${{enum.ident}}";')
5208545Ssaidi@eecs.umich.edu        code.dedent()
5218545Ssaidi@eecs.umich.edu
5228545Ssaidi@eecs.umich.edu        # Trailer
5238545Ssaidi@eecs.umich.edu        code('''
5242292SN/A      default:
5258199SAli.Saidi@ARM.com        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
5268199SAli.Saidi@ARM.com        return "";
5278199SAli.Saidi@ARM.com    }
5288199SAli.Saidi@ARM.com}
5298199SAli.Saidi@ARM.com
5308199SAli.Saidi@ARM.com${{self.c_ident}} string_to_${{self.c_ident}}(const string& str)
5318199SAli.Saidi@ARM.com{
5328199SAli.Saidi@ARM.com''')
5338199SAli.Saidi@ARM.com
5348199SAli.Saidi@ARM.com        # For each field
5358199SAli.Saidi@ARM.com        code.indent()
5368199SAli.Saidi@ARM.com        code("if (false) {")
5379046SAli.Saidi@ARM.com        start = "} else "
5388199SAli.Saidi@ARM.com        for enum in self.enums.itervalues():
5398199SAli.Saidi@ARM.com            code('${start}if (str == "${{enum.ident}}") {')
5408199SAli.Saidi@ARM.com            code('    return ${{self.c_ident}}_${{enum.ident}};')
5418199SAli.Saidi@ARM.com        code.dedent()
5428199SAli.Saidi@ARM.com
5438199SAli.Saidi@ARM.com        code('''
5448199SAli.Saidi@ARM.com    } else {
5458199SAli.Saidi@ARM.com        WARN_EXPR(str);
5468272SAli.Saidi@ARM.com        ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}");
5478545Ssaidi@eecs.umich.edu    }
5488545Ssaidi@eecs.umich.edu}
5498545Ssaidi@eecs.umich.edu
5508545Ssaidi@eecs.umich.edu${{self.c_ident}}& operator++(${{self.c_ident}}& e) {
5519046SAli.Saidi@ARM.com    assert(e < ${{self.c_ident}}_NUM);
5528545Ssaidi@eecs.umich.edu    return e = ${{self.c_ident}}(e+1);
5538545Ssaidi@eecs.umich.edu}
5548545Ssaidi@eecs.umich.edu''')
5558592Sgblack@eecs.umich.edu
5568592Sgblack@eecs.umich.edu        # MachineType hack used to set the base level and number of
5578545Ssaidi@eecs.umich.edu        # components for each Machine
5588199SAli.Saidi@ARM.com        if self.isMachineType:
5598545Ssaidi@eecs.umich.edu            code('''
5608199SAli.Saidi@ARM.com/** \\brief returns the base vector index for each machine type to be used by NetDest
5618591Sgblack@eecs.umich.edu  *
5628591Sgblack@eecs.umich.edu  * \\return the base vector index for each machine type to be used by NetDest
5638591Sgblack@eecs.umich.edu  * \\see NetDest.hh
5648591Sgblack@eecs.umich.edu  */
5658545Ssaidi@eecs.umich.eduint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
5668545Ssaidi@eecs.umich.edu{
5678199SAli.Saidi@ARM.com    switch(obj) {
5688545Ssaidi@eecs.umich.edu''')
5698545Ssaidi@eecs.umich.edu
5709046SAli.Saidi@ARM.com            # For each field
5718545Ssaidi@eecs.umich.edu            code.indent()
5728545Ssaidi@eecs.umich.edu            for i,enum in enumerate(self.enums.itervalues()):
5738545Ssaidi@eecs.umich.edu                code('  case ${{self.c_ident}}_${{enum.ident}}:')
5748545Ssaidi@eecs.umich.edu                code('    return $i;')
5758545Ssaidi@eecs.umich.edu            code.dedent()
5768545Ssaidi@eecs.umich.edu
5778545Ssaidi@eecs.umich.edu            # total num
5788545Ssaidi@eecs.umich.edu            code('''
5798545Ssaidi@eecs.umich.edu      case ${{self.c_ident}}_NUM:
5808545Ssaidi@eecs.umich.edu        return ${{len(self.enums)}};
5818592Sgblack@eecs.umich.edu
5828592Sgblack@eecs.umich.edu      default:
5838592Sgblack@eecs.umich.edu        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
5848545Ssaidi@eecs.umich.edu        return -1;
5858545Ssaidi@eecs.umich.edu    }
5868545Ssaidi@eecs.umich.edu}
5878545Ssaidi@eecs.umich.edu
5888591Sgblack@eecs.umich.edu/** \\brief returns the machine type for each base vector index used by NetDest
5898591Sgblack@eecs.umich.edu *
5908591Sgblack@eecs.umich.edu * \\return the MachineTYpe
5918545Ssaidi@eecs.umich.edu */
5928199SAli.Saidi@ARM.comMachineType ${{self.c_ident}}_from_base_level(int type)
5938199SAli.Saidi@ARM.com{
5948199SAli.Saidi@ARM.com    switch(type) {
5958199SAli.Saidi@ARM.com''')
5968199SAli.Saidi@ARM.com
5978199SAli.Saidi@ARM.com            # For each field
5988199SAli.Saidi@ARM.com            code.indent()
5998199SAli.Saidi@ARM.com            for i,enum in enumerate(self.enums.itervalues()):
6008199SAli.Saidi@ARM.com                code('  case $i:')
6018199SAli.Saidi@ARM.com                code('    return ${{self.c_ident}}_${{enum.ident}};')
6028199SAli.Saidi@ARM.com            code.dedent()
6038199SAli.Saidi@ARM.com
6042292SN/A            # Trailer
6052292SN/A            code('''
6064032Sktlim@umich.edu      default:
6072292SN/A        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
6082292SN/A        return MachineType_NUM;
6092292SN/A    }
6107720Sgblack@eecs.umich.edu}
6117944SGiacomo.Gabrielli@arm.com
6122292SN/A/** \\brief The return value indicates the number of components created
6134032Sktlim@umich.edu * before a particular machine\'s components
6144032Sktlim@umich.edu *
6152669Sktlim@umich.edu * \\return the base number of components for each machine
6162292SN/A */
6177944SGiacomo.Gabrielli@arm.comint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
6187944SGiacomo.Gabrielli@arm.com{
6197944SGiacomo.Gabrielli@arm.com    int base = 0;
6207944SGiacomo.Gabrielli@arm.com    switch(obj) {
6217597Sminkyu.jeong@arm.com''')
6227597Sminkyu.jeong@arm.com
62310231Ssteve.reinhardt@amd.com            # For each field
6242329SN/A            code.indent()
6252329SN/A            code('  case ${{self.c_ident}}_NUM:')
6262367SN/A            for enum in reversed(self.enums.values()):
6272367SN/A                code('    base += ${{enum.ident}}_Controller::getNumControllers();')
62810231Ssteve.reinhardt@amd.com                code('  case ${{self.c_ident}}_${{enum.ident}}:')
6297848SAli.Saidi@ARM.com            code('    break;')
6307600Sminkyu.jeong@arm.com            code.dedent()
6317600Sminkyu.jeong@arm.com
6327600Sminkyu.jeong@arm.com            code('''
6334032Sktlim@umich.edu      default:
6343731Sktlim@umich.edu        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
6352367SN/A        return -1;
6362367SN/A    }
6372292SN/A
6382292SN/A    return base;
63910333Smitch.hayenga@arm.com}
6409046SAli.Saidi@ARM.com
6414032Sktlim@umich.edu/** \\brief returns the total number of components for each machine
6424032Sktlim@umich.edu * \\return the total number of components for each machine
6434032Sktlim@umich.edu */
6448199SAli.Saidi@ARM.comint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
6458199SAli.Saidi@ARM.com{
6462292SN/A    switch(obj) {
6472292SN/A''')
6482292SN/A
6492292SN/A            # For each field
6502292SN/A            for enum in self.enums.itervalues():
6512292SN/A                code('''
6522292SN/A      case ${{self.c_ident}}_${{enum.ident}}:
6532292SN/A        return ${{enum.ident}}_Controller::getNumControllers();
6542292SN/A''')
6552292SN/A
6562292SN/A            # total num
6572292SN/A            code('''
6582292SN/A      case ${{self.c_ident}}_NUM:
6592292SN/A      default:
6602292SN/A        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
6617720Sgblack@eecs.umich.edu        return -1;
6627720Sgblack@eecs.umich.edu    }
6632292SN/A}
6644032Sktlim@umich.edu''')
6654032Sktlim@umich.edu
6662292SN/A        # Write the file
6672292SN/A        code.write(path, "%s.cc" % self.c_ident)
6682292SN/A
6692292SN/A__all__ = [ "Type" ]
6702292SN/A