Type.py revision 6862:3d308cbd1657
14403Srdreslin@umich.edu# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
21693Sstever@eecs.umich.edu# Copyright (c) 2009 The Hewlett-Packard Development Company
31693Sstever@eecs.umich.edu# All rights reserved.
41693Sstever@eecs.umich.edu#
51693Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
61693Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are
71693Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright
81693Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
91693Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
101693Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
111693Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution;
121693Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its
131693Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from
141693Sstever@eecs.umich.edu# this software without specific prior written permission.
151693Sstever@eecs.umich.edu#
161693Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171693Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181693Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191693Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201693Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211693Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221693Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231693Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241693Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251693Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261693Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271693Sstever@eecs.umich.edu
281693Sstever@eecs.umich.edufrom m5.util import code_formatter, orderdict
293358Srdreslin@umich.edu
303358Srdreslin@umich.edufrom slicc.util import PairContainer
311516SN/Afrom slicc.symbols.Symbol import Symbol
326654Snate@binkert.org
336654Snate@binkert.orgclass DataMember(PairContainer):
346654Snate@binkert.org    def __init__(self, ident, type, pairs, init_code):
356654Snate@binkert.org        super(DataMember, self).__init__(pairs)
363358Srdreslin@umich.edu        self.ident = ident
373358Srdreslin@umich.edu        self.type = type
386654Snate@binkert.org        self.init_code = init_code
396654Snate@binkert.org
401516SN/Aclass Enumeration(PairContainer):
413358Srdreslin@umich.edu    def __init__(self, ident, pairs):
423358Srdreslin@umich.edu        super(Enumeration, self).__init__(pairs)
433358Srdreslin@umich.edu        self.ident = ident
443358Srdreslin@umich.edu
453358Srdreslin@umich.educlass Method(object):
463358Srdreslin@umich.edu    def __init__(self, return_type, param_types):
473358Srdreslin@umich.edu        self.return_type = return_type
483358Srdreslin@umich.edu        self.param_types = param_types
493358Srdreslin@umich.edu
503358Srdreslin@umich.educlass Type(Symbol):
513358Srdreslin@umich.edu    def __init__(self, table, ident, location, pairs, machine=None):
523358Srdreslin@umich.edu        super(Type, self).__init__(table, ident, location, pairs)
533360Srdreslin@umich.edu        self.c_ident = ident
543358Srdreslin@umich.edu        if machine:
553360Srdreslin@umich.edu            if self.isExternal or self.isPrimitive:
563360Srdreslin@umich.edu                if "external_name" in self:
573360Srdreslin@umich.edu                    self.c_ident = self["external_name"]
585255Ssaidi@eecs.umich.edu            else:
593360Srdreslin@umich.edu                # Append with machine name
603360Srdreslin@umich.edu                self.c_ident = "%s_%s" % (machine, ident)
613360Srdreslin@umich.edu
625255Ssaidi@eecs.umich.edu        self.pairs.setdefault("desc", "No description avaliable")
633358Srdreslin@umich.edu
644403Srdreslin@umich.edu        # check for interface that this Type implements
653360Srdreslin@umich.edu        if "interface" in self:
663358Srdreslin@umich.edu            interface = self["interface"]
673358Srdreslin@umich.edu            if interface in ("Message", "NetworkMessage"):
683358Srdreslin@umich.edu                self["message"] = "yes"
693358Srdreslin@umich.edu            if interface == "NetworkMessage":
703358Srdreslin@umich.edu                self["networkmessage"] = "yes"
713358Srdreslin@umich.edu
723358Srdreslin@umich.edu        # FIXME - all of the following id comparisons are fragile hacks
733358Srdreslin@umich.edu        if self.ident in ("CacheMemory", "NewCacheMemory",
743358Srdreslin@umich.edu                          "TLCCacheMemory", "DNUCACacheMemory",
753360Srdreslin@umich.edu                          "DNUCABankCacheMemory", "L2BankCacheMemory",
763360Srdreslin@umich.edu                          "CompressedCacheMemory", "PrefetchCacheMemory"):
773360Srdreslin@umich.edu            self["cache"] = "yes"
783360Srdreslin@umich.edu
793358Srdreslin@umich.edu        if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
803358Srdreslin@umich.edu            self["tbe"] = "yes"
813358Srdreslin@umich.edu
823358Srdreslin@umich.edu        if self.ident == "NewTBETable":
834403Srdreslin@umich.edu            self["newtbe"] = "yes"
844403Srdreslin@umich.edu
855256Ssaidi@eecs.umich.edu        if self.ident == "TimerTable":
865255Ssaidi@eecs.umich.edu            self["timer"] = "yes"
873358Srdreslin@umich.edu
883358Srdreslin@umich.edu        if self.ident == "DirectoryMemory":
894403Srdreslin@umich.edu            self["dir"] = "yes"
904403Srdreslin@umich.edu
915255Ssaidi@eecs.umich.edu        if self.ident == "PersistentTable":
923358Srdreslin@umich.edu            self["persistent"] = "yes"
933358Srdreslin@umich.edu
944403Srdreslin@umich.edu        if self.ident == "Prefetcher":
955255Ssaidi@eecs.umich.edu            self["prefetcher"] = "yes"
964403Srdreslin@umich.edu
973358Srdreslin@umich.edu        if self.ident == "DNUCA_Movement":
983358Srdreslin@umich.edu            self["mover"] = "yes"
994403Srdreslin@umich.edu
1005255Ssaidi@eecs.umich.edu        self.isMachineType = (ident == "MachineType")
1014403Srdreslin@umich.edu
1023358Srdreslin@umich.edu        self.data_members = orderdict()
1033358Srdreslin@umich.edu
1044403Srdreslin@umich.edu        # Methods
1055255Ssaidi@eecs.umich.edu        self.methods = {}
1064403Srdreslin@umich.edu
1073358Srdreslin@umich.edu        # Enums
1083358Srdreslin@umich.edu        self.enums = orderdict()
1094403Srdreslin@umich.edu
1105255Ssaidi@eecs.umich.edu    @property
1114403Srdreslin@umich.edu    def isPrimitive(self):
1124403Srdreslin@umich.edu        return "primitive" in self
1133358Srdreslin@umich.edu    @property
1143358Srdreslin@umich.edu    def isNetworkMessage(self):
1154403Srdreslin@umich.edu        return "networkmessage" in self
1165255Ssaidi@eecs.umich.edu    @property
1174403Srdreslin@umich.edu    def isMessage(self):
1184403Srdreslin@umich.edu        return "message" in self
1194403Srdreslin@umich.edu    @property
1203360Srdreslin@umich.edu    def isBuffer(self):
1214403Srdreslin@umich.edu        return "buffer" in self
1223358Srdreslin@umich.edu    @property
1233358Srdreslin@umich.edu    def isInPort(self):
1244403Srdreslin@umich.edu        return "inport" in self
1255255Ssaidi@eecs.umich.edu    @property
1264403Srdreslin@umich.edu    def isOutPort(self):
1273358Srdreslin@umich.edu        return "outport" in self
1283358Srdreslin@umich.edu    @property
1294403Srdreslin@umich.edu    def isEnumeration(self):
1305255Ssaidi@eecs.umich.edu        return "enumeration" in self
1314403Srdreslin@umich.edu    @property
1323358Srdreslin@umich.edu    def isExternal(self):
1333358Srdreslin@umich.edu        return "external" in self
1344403Srdreslin@umich.edu    @property
1355256Ssaidi@eecs.umich.edu    def isGlobal(self):
1365255Ssaidi@eecs.umich.edu        return "global" in self
1374403Srdreslin@umich.edu    @property
1383358Srdreslin@umich.edu    def isInterface(self):
1393358Srdreslin@umich.edu        return "interface" in self
1404403Srdreslin@umich.edu
1415255Ssaidi@eecs.umich.edu    # Return false on error
1424403Srdreslin@umich.edu    def dataMemberAdd(self, ident, type, pairs, init_code):
1434403Srdreslin@umich.edu        if ident in self.data_members:
1444403Srdreslin@umich.edu            return False
1453360Srdreslin@umich.edu
1464403Srdreslin@umich.edu        member = DataMember(ident, type, pairs, init_code)
1473358Srdreslin@umich.edu        self.data_members[ident] = member
1483358Srdreslin@umich.edu
1494403Srdreslin@umich.edu        return True
1505255Ssaidi@eecs.umich.edu
1514403Srdreslin@umich.edu    def dataMemberType(self, ident):
1524403Srdreslin@umich.edu        return self.data_members[ident].type
1534403Srdreslin@umich.edu
1543360Srdreslin@umich.edu    def methodId(self, name, param_type_vec):
1554403Srdreslin@umich.edu        return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
1563358Srdreslin@umich.edu
1573358Srdreslin@umich.edu    def methodAdd(self, name, return_type, param_type_vec):
1583358Srdreslin@umich.edu        ident = self.methodId(name, param_type_vec)
1593358Srdreslin@umich.edu        if ident in self.methods:
1603358Srdreslin@umich.edu            return False
1613358Srdreslin@umich.edu
1623358Srdreslin@umich.edu        self.methods[ident] = Method(return_type, param_type_vec)
1633358Srdreslin@umich.edu        return True
1643358Srdreslin@umich.edu
1653358Srdreslin@umich.edu    def enumAdd(self, ident, pairs):
1663358Srdreslin@umich.edu        if ident in self.enums:
1673358Srdreslin@umich.edu            return False
1683358Srdreslin@umich.edu
1693358Srdreslin@umich.edu        self.enums[ident] = Enumeration(ident, pairs)
1703358Srdreslin@umich.edu
1713358Srdreslin@umich.edu        # Add default
1723358Srdreslin@umich.edu        if "default" not in self:
1733358Srdreslin@umich.edu            self["default"] = "%s_NUM" % self.c_ident
1743358Srdreslin@umich.edu
1753358Srdreslin@umich.edu        return True
1763358Srdreslin@umich.edu
1773358Srdreslin@umich.edu    def writeCodeFiles(self, path):
1783358Srdreslin@umich.edu        if self.isExternal:
1793358Srdreslin@umich.edu            # Do nothing
1803358Srdreslin@umich.edu            pass
1813358Srdreslin@umich.edu        elif self.isEnumeration:
1823358Srdreslin@umich.edu            self.printEnumHH(path)
1833358Srdreslin@umich.edu            self.printEnumCC(path)
1843358Srdreslin@umich.edu        else:
1853358Srdreslin@umich.edu            # User defined structs and messages
1863358Srdreslin@umich.edu            self.printTypeHH(path)
1873358Srdreslin@umich.edu            self.printTypeCC(path)
1883358Srdreslin@umich.edu
1893358Srdreslin@umich.edu    def printTypeHH(self, path):
1903358Srdreslin@umich.edu        code = code_formatter()
1913358Srdreslin@umich.edu        code('''
1921516SN/A/** \\file ${{self.c_ident}}.hh
1933358Srdreslin@umich.edu *
1943358Srdreslin@umich.edu *
1953358Srdreslin@umich.edu * Auto generated C++ code started by $__file__:$__line__
1961516SN/A */
1973358Srdreslin@umich.edu
1983358Srdreslin@umich.edu#ifndef ${{self.c_ident}}_H
1993358Srdreslin@umich.edu#define ${{self.c_ident}}_H
2003358Srdreslin@umich.edu
2013358Srdreslin@umich.edu#include "mem/ruby/common/Global.hh"
2021516SN/A#include "mem/gems_common/Allocator.hh"
2033358Srdreslin@umich.edu''')
2043358Srdreslin@umich.edu
2053358Srdreslin@umich.edu        for dm in self.data_members.values():
2063358Srdreslin@umich.edu            if not dm.type.isPrimitive:
2073358Srdreslin@umich.edu                code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
2083358Srdreslin@umich.edu
2093358Srdreslin@umich.edu        parent = ""
2103358Srdreslin@umich.edu        if "interface" in self:
2113358Srdreslin@umich.edu            code('#include "mem/protocol/$0.hh"', self["interface"])
2123358Srdreslin@umich.edu            parent = " :  public %s" % self["interface"]
2133358Srdreslin@umich.edu
2143358Srdreslin@umich.edu        code('''
2153358Srdreslin@umich.edu$klass ${{self.c_ident}}$parent {
2163358Srdreslin@umich.edu  public:
2173358Srdreslin@umich.edu    ${{self.c_ident}}()
2183358Srdreslin@umich.edu''', klass="class")
2193358Srdreslin@umich.edu
2203358Srdreslin@umich.edu        # Call superclass constructor
2217876Sgblack@eecs.umich.edu        if "interface" in self:
2223358Srdreslin@umich.edu            code('        : ${{self["interface"]}}()')
2233358Srdreslin@umich.edu
2243358Srdreslin@umich.edu        code.indent()
2253358Srdreslin@umich.edu        code("{")
2263358Srdreslin@umich.edu        if not self.isGlobal:
2273358Srdreslin@umich.edu            code.indent()
2283358Srdreslin@umich.edu            for dm in self.data_members.values():
2293358Srdreslin@umich.edu                ident = dm.ident
2303358Srdreslin@umich.edu                if "default" in dm:
2313358Srdreslin@umich.edu                    # look for default value
2323358Srdreslin@umich.edu                    code('m_$ident = ${{dm["default"]}}; // default for this field')
2333358Srdreslin@umich.edu                elif "default" in dm.type:
2343358Srdreslin@umich.edu                    # Look for the type default
2353358Srdreslin@umich.edu                    tid = dm.type.c_ident
2363358Srdreslin@umich.edu                    code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
2373358Srdreslin@umich.edu                else:
2383358Srdreslin@umich.edu                    code('// m_$ident has no default')
2393358Srdreslin@umich.edu            code.dedent()
2403358Srdreslin@umich.edu        code('}')
2413358Srdreslin@umich.edu
2423358Srdreslin@umich.edu        # ******** Default destructor ********
2433358Srdreslin@umich.edu        code('~${{self.c_ident}}() { };')
2443358Srdreslin@umich.edu
2453358Srdreslin@umich.edu        # ******** Full init constructor ********
2463358Srdreslin@umich.edu        if not self.isGlobal:
2473358Srdreslin@umich.edu            params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
2483358Srdreslin@umich.edu                       for dm in self.data_members.itervalues() ]
2493358Srdreslin@umich.edu
2503358Srdreslin@umich.edu            if self.isMessage:
2513358Srdreslin@umich.edu                params.append('const unsigned local_proc_id')
2523358Srdreslin@umich.edu
2533358Srdreslin@umich.edu            params = ', '.join(params)
2543358Srdreslin@umich.edu            code('${{self.c_ident}}($params)')
2553358Srdreslin@umich.edu
2563358Srdreslin@umich.edu            # Call superclass constructor
2571516SN/A            if "interface" in self:
2585256Ssaidi@eecs.umich.edu                code('    : ${{self["interface"]}}()')
2595256Ssaidi@eecs.umich.edu
2605256Ssaidi@eecs.umich.edu            code('{')
2615256Ssaidi@eecs.umich.edu            code.indent()
2623358Srdreslin@umich.edu            for dm in self.data_members.values():
2633358Srdreslin@umich.edu                code('m_${{dm.ident}} = local_${{dm.ident}};')
2643358Srdreslin@umich.edu                if "nextLineCallHack" in dm:
2653358Srdreslin@umich.edu                    code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
2663358Srdreslin@umich.edu
2673358Srdreslin@umich.edu            if self.isMessage:
2683358Srdreslin@umich.edu                code('proc_id = local_proc_id;')
2693358Srdreslin@umich.edu
2703358Srdreslin@umich.edu            code.dedent()
2713358Srdreslin@umich.edu            code('}')
2723358Srdreslin@umich.edu
2733358Srdreslin@umich.edu        # create a static factory method
2743358Srdreslin@umich.edu        if "interface" in self:
2753358Srdreslin@umich.edu            code('''
2763358Srdreslin@umich.edustatic ${{self["interface"]}}* create() {
2773358Srdreslin@umich.edu    return new ${{self.c_ident}}();
2787525Ssteve.reinhardt@amd.com}
2793358Srdreslin@umich.edu''')
2803358Srdreslin@umich.edu
2813358Srdreslin@umich.edu        # ******** Message member functions ********
2823358Srdreslin@umich.edu        # FIXME: those should be moved into slicc file, slicc should
2833358Srdreslin@umich.edu        # support more of the c++ class inheritance
2843646Srdreslin@umich.edu
2853358Srdreslin@umich.edu        if self.isMessage:
2863358Srdreslin@umich.edu            code('''
2873358Srdreslin@umich.eduMessage* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }
288void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }
289static Allocator<${{self.c_ident}}>* s_allocator_ptr;
290static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }}
291''')
292
293        if not self.isGlobal:
294            # const Get methods for each field
295            code('// Const accessors methods for each field')
296            for dm in self.data_members.values():
297                code('''
298/** \\brief Const accessor method for ${{dm.ident}} field.
299 *  \\return ${{dm.ident}} field
300 */
301const ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; }
302''')
303
304            # Non-const Get methods for each field
305            code('// Non const Accessors methods for each field')
306            for dm in self.data_members.values():
307                code('''
308/** \\brief Non-const accessor method for ${{dm.ident}} field.
309 *  \\return ${{dm.ident}} field
310 */
311${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; }
312''')
313
314            #Set methods for each field
315            code('// Mutator methods for each field')
316            for dm in self.data_members.values():
317                code('''
318/** \\brief Mutator method for ${{dm.ident}} field */
319void set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; }
320''')
321
322        code('void print(ostream& out) const;')
323        code.dedent()
324        code('  //private:')
325        code.indent()
326
327        # Data members for each field
328        for dm in self.data_members.values():
329            if "abstract" not in dm:
330                const = ""
331                init = ""
332
333                # global structure
334                if self.isGlobal:
335                    const = "static const "
336
337                # init value
338                if dm.init_code:
339                    # only global structure can have init value here
340                    assert self.isGlobal
341                    init = " = %s" % (dm.init_code)
342
343                desc = ""
344                if "desc" in dm:
345                    desc = '/**< %s */' % dm["desc"]
346
347                code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc')
348
349        if self.isMessage:
350            code('unsigned proc_id;')
351
352        code.dedent()
353        code('};')
354
355        code('''
356// Output operator declaration
357ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
358
359// Output operator definition
360extern inline
361ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
362{
363    obj.print(out);
364    out << flush;
365    return out;
366}
367
368#endif // ${{self.c_ident}}_H
369''')
370
371        code.write(path, "%s.hh" % self.c_ident)
372
373    def printTypeCC(self, path):
374        code = code_formatter()
375
376        code('''
377/** \\file ${{self.c_ident}}.cc
378 *
379 * Auto generated C++ code started by $__file__:$__line__
380 */
381
382#include "mem/protocol/${{self.c_ident}}.hh"
383''')
384
385        if self.isMessage:
386            code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;')
387        code('''
388/** \\brief Print the state of this object */
389void ${{self.c_ident}}::print(ostream& out) const
390{
391    out << "[${{self.c_ident}}: ";
392''')
393
394        # For each field
395        code.indent()
396        for dm in self.data_members.values():
397            code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
398
399        if self.isMessage:
400            code('out << "Time = " << getTime() << " ";')
401        code.dedent()
402
403        # Trailer
404        code('''
405    out << "]";
406}''')
407
408        code.write(path, "%s.cc" % self.c_ident)
409
410    def printEnumHH(self, path):
411        code = code_formatter()
412        code('''
413/** \\file ${{self.c_ident}}.hh
414 *
415 * Auto generated C++ code started by $__file__:$__line__
416 */
417#ifndef ${{self.c_ident}}_H
418#define ${{self.c_ident}}_H
419
420#include "mem/ruby/common/Global.hh"
421
422/** \\enum ${{self.c_ident}}
423 *  \\brief ${{self.desc}}
424 */
425enum ${{self.c_ident}} {
426    ${{self.c_ident}}_FIRST,
427''')
428
429        code.indent()
430        # For each field
431        for i,(ident,enum) in enumerate(self.enums.iteritems()):
432            desc = enum.get("desc", "No description avaliable")
433            if i == 0:
434                init = ' = %s_FIRST' % self.c_ident
435            else:
436                init = ''
437            code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
438        code.dedent()
439        code('''
440    ${{self.c_ident}}_NUM
441};
442${{self.c_ident}} string_to_${{self.c_ident}}(const string& str);
443string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
444${{self.c_ident}} &operator++(${{self.c_ident}} &e);
445''')
446
447        # MachineType hack used to set the base component id for each Machine
448        if self.isMachineType:
449            code('''
450int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
451MachineType ${{self.c_ident}}_from_base_level(int);
452int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
453int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
454''')
455
456            for enum in self.enums.itervalues():
457                code('#define MACHINETYPE_${{enum.ident}} 1')
458
459        # Trailer
460        code('''
461ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj);
462
463#endif // ${{self.c_ident}}_H
464''')
465
466        code.write(path, "%s.hh" % self.c_ident)
467
468    def printEnumCC(self, path):
469        code = code_formatter()
470        code('''
471/** \\file ${{self.c_ident}}.hh
472 *
473 * Auto generated C++ code started by $__file__:$__line__
474 */
475
476#include "mem/protocol/${{self.c_ident}}.hh"
477
478''')
479
480        if self.isMachineType:
481            code('#include "mem/protocol/ControllerFactory.hh"')
482            for enum in self.enums.itervalues():
483                code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
484
485        code('''
486ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj)
487{
488    out << ${{self.c_ident}}_to_string(obj);
489    out << flush;
490    return out;
491}
492
493string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
494{
495    switch(obj) {
496''')
497
498        # For each field
499        code.indent()
500        for enum in self.enums.itervalues():
501            code('  case ${{self.c_ident}}_${{enum.ident}}:')
502            code('    return "${{enum.ident}}";')
503        code.dedent()
504
505        # Trailer
506        code('''
507      default:
508        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
509        return "";
510    }
511}
512
513${{self.c_ident}} string_to_${{self.c_ident}}(const string& str)
514{
515''')
516
517        # For each field
518        code.indent()
519        code("if (false) {")
520        start = "} else "
521        for enum in self.enums.itervalues():
522            code('${start}if (str == "${{enum.ident}}") {')
523            code('    return ${{self.c_ident}}_${{enum.ident}};')
524        code.dedent()
525
526        code('''
527    } else {
528        WARN_EXPR(str);
529        ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}");
530    }
531}
532
533${{self.c_ident}}& operator++(${{self.c_ident}}& e) {
534    assert(e < ${{self.c_ident}}_NUM);
535    return e = ${{self.c_ident}}(e+1);
536}
537''')
538
539        # MachineType hack used to set the base level and number of
540        # components for each Machine
541        if self.isMachineType:
542            code('''
543/** \\brief returns the base vector index for each machine type to be used by NetDest
544  *
545  * \\return the base vector index for each machine type to be used by NetDest
546  * \\see NetDest.hh
547  */
548int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
549{
550    switch(obj) {
551''')
552
553            # For each field
554            code.indent()
555            for i,enum in enumerate(self.enums.itervalues()):
556                code('  case ${{self.c_ident}}_${{enum.ident}}:')
557                code('    return $i;')
558            code.dedent()
559
560            # total num
561            code('''
562      case ${{self.c_ident}}_NUM:
563        return ${{len(self.enums)}};
564
565      default:
566        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
567        return -1;
568    }
569}
570
571/** \\brief returns the machine type for each base vector index used by NetDest
572 *
573 * \\return the MachineTYpe
574 */
575MachineType ${{self.c_ident}}_from_base_level(int type)
576{
577    switch(type) {
578''')
579
580            # For each field
581            code.indent()
582            for i,enum in enumerate(self.enums.itervalues()):
583                code('  case $i:')
584                code('    return ${{self.c_ident}}_${{enum.ident}};')
585            code.dedent()
586
587            # Trailer
588            code('''
589      default:
590        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
591        return MachineType_NUM;
592    }
593}
594
595/** \\brief The return value indicates the number of components created
596 * before a particular machine\'s components
597 *
598 * \\return the base number of components for each machine
599 */
600int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
601{
602    int base = 0;
603    switch(obj) {
604''')
605
606            # For each field
607            code.indent()
608            code('  case ${{self.c_ident}}_NUM:')
609            for enum in reversed(self.enums.values()):
610                code('    base += ${{enum.ident}}_Controller::getNumControllers();')
611                code('  case ${{self.c_ident}}_${{enum.ident}}:')
612            code('    break;')
613            code.dedent()
614
615            code('''
616      default:
617        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
618        return -1;
619    }
620
621    return base;
622}
623
624/** \\brief returns the total number of components for each machine
625 * \\return the total number of components for each machine
626 */
627int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
628{
629    switch(obj) {
630''')
631
632            # For each field
633            for enum in self.enums.itervalues():
634                code('''
635      case ${{self.c_ident}}_${{enum.ident}}:
636        return ${{enum.ident}}_Controller::getNumControllers();
637''')
638
639            # total num
640            code('''
641      case ${{self.c_ident}}_NUM:
642      default:
643        ERROR_MSG("Invalid range for type ${{self.c_ident}}");
644        return -1;
645    }
646}
647''')
648
649        # Write the file
650        code.write(path, "%s.cc" % self.c_ident)
651
652__all__ = [ "Type" ]
653