Type.py revision 7832:de7601e6e19d
15353Svilas.sridharan@gmail.com# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
23395Shsul@eecs.umich.edu# Copyright (c) 2009 The Hewlett-Packard Development Company
33395Shsul@eecs.umich.edu# All rights reserved.
43395Shsul@eecs.umich.edu#
53395Shsul@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
63395Shsul@eecs.umich.edu# modification, are permitted provided that the following conditions are
73395Shsul@eecs.umich.edu# met: redistributions of source code must retain the above copyright
83395Shsul@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
93395Shsul@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
103395Shsul@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
113395Shsul@eecs.umich.edu# documentation and/or other materials provided with the distribution;
123395Shsul@eecs.umich.edu# neither the name of the copyright holders nor the names of its
133395Shsul@eecs.umich.edu# contributors may be used to endorse or promote products derived from
143395Shsul@eecs.umich.edu# this software without specific prior written permission.
153395Shsul@eecs.umich.edu#
163395Shsul@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173395Shsul@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183395Shsul@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193395Shsul@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203395Shsul@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213395Shsul@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223395Shsul@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233395Shsul@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243395Shsul@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253395Shsul@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263395Shsul@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273395Shsul@eecs.umich.edu
283395Shsul@eecs.umich.edufrom m5.util import orderdict
298920Snilay@cs.wisc.edu
308920Snilay@cs.wisc.edufrom slicc.util import PairContainer
318920Snilay@cs.wisc.edufrom slicc.symbols.Symbol import Symbol
328920Snilay@cs.wisc.edu
337025SBrad.Beckmann@amd.comclass DataMember(PairContainer):
348920Snilay@cs.wisc.edu    def __init__(self, ident, type, pairs, init_code):
358920Snilay@cs.wisc.edu        super(DataMember, self).__init__(pairs)
368920Snilay@cs.wisc.edu        self.ident = ident
378920Snilay@cs.wisc.edu        self.type = type
388920Snilay@cs.wisc.edu        self.init_code = init_code
398920Snilay@cs.wisc.edu
408920Snilay@cs.wisc.educlass Enumeration(PairContainer):
418920Snilay@cs.wisc.edu    def __init__(self, ident, pairs):
428920Snilay@cs.wisc.edu        super(Enumeration, self).__init__(pairs)
438920Snilay@cs.wisc.edu        self.ident = ident
448920Snilay@cs.wisc.edu
458920Snilay@cs.wisc.educlass Method(object):
468920Snilay@cs.wisc.edu    def __init__(self, return_type, param_types):
478920Snilay@cs.wisc.edu        self.return_type = return_type
488920Snilay@cs.wisc.edu        self.param_types = param_types
498920Snilay@cs.wisc.edu
508920Snilay@cs.wisc.educlass Type(Symbol):
518920Snilay@cs.wisc.edu    def __init__(self, table, ident, location, pairs, machine=None):
528920Snilay@cs.wisc.edu        super(Type, self).__init__(table, ident, location, pairs)
538920Snilay@cs.wisc.edu        self.c_ident = ident
548920Snilay@cs.wisc.edu        self.abstract_ident = ""
558920Snilay@cs.wisc.edu        if machine:
568920Snilay@cs.wisc.edu            if self.isExternal or self.isPrimitive:
578920Snilay@cs.wisc.edu                if "external_name" in self:
588920Snilay@cs.wisc.edu                    self.c_ident = self["external_name"]
593395Shsul@eecs.umich.edu            else:
608920Snilay@cs.wisc.edu                # Append with machine name
618920Snilay@cs.wisc.edu                self.c_ident = "%s_%s" % (machine, ident)
628920Snilay@cs.wisc.edu
638920Snilay@cs.wisc.edu        self.pairs.setdefault("desc", "No description avaliable")
648920Snilay@cs.wisc.edu
658920Snilay@cs.wisc.edu        # check for interface that this Type implements
668920Snilay@cs.wisc.edu        if "interface" in self:
678920Snilay@cs.wisc.edu            interface = self["interface"]
688920Snilay@cs.wisc.edu            if interface in ("Message", "NetworkMessage"):
698920Snilay@cs.wisc.edu                self["message"] = "yes"
708920Snilay@cs.wisc.edu            if interface == "NetworkMessage":
718920Snilay@cs.wisc.edu                self["networkmessage"] = "yes"
728920Snilay@cs.wisc.edu
738920Snilay@cs.wisc.edu        # FIXME - all of the following id comparisons are fragile hacks
748920Snilay@cs.wisc.edu        if self.ident in ("CacheMemory", "NewCacheMemory",
758920Snilay@cs.wisc.edu                          "TLCCacheMemory", "DNUCACacheMemory",
768920Snilay@cs.wisc.edu                          "DNUCABankCacheMemory", "L2BankCacheMemory",
778920Snilay@cs.wisc.edu                          "CompressedCacheMemory", "PrefetchCacheMemory"):
786776SBrad.Beckmann@amd.com            self["cache"] = "yes"
798920Snilay@cs.wisc.edu
808920Snilay@cs.wisc.edu        if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
818920Snilay@cs.wisc.edu            self["tbe"] = "yes"
828920Snilay@cs.wisc.edu
838920Snilay@cs.wisc.edu        if self.ident == "NewTBETable":
848920Snilay@cs.wisc.edu            self["newtbe"] = "yes"
858920Snilay@cs.wisc.edu
868920Snilay@cs.wisc.edu        if self.ident == "TimerTable":
878920Snilay@cs.wisc.edu            self["timer"] = "yes"
888920Snilay@cs.wisc.edu
898920Snilay@cs.wisc.edu        if self.ident == "DirectoryMemory":
908920Snilay@cs.wisc.edu            self["dir"] = "yes"
918920Snilay@cs.wisc.edu
928920Snilay@cs.wisc.edu        if self.ident == "PersistentTable":
938920Snilay@cs.wisc.edu            self["persistent"] = "yes"
948920Snilay@cs.wisc.edu
958920Snilay@cs.wisc.edu        if self.ident == "Prefetcher":
968920Snilay@cs.wisc.edu            self["prefetcher"] = "yes"
978920Snilay@cs.wisc.edu
988920Snilay@cs.wisc.edu        if self.ident == "DNUCA_Movement":
998920Snilay@cs.wisc.edu            self["mover"] = "yes"
1008920Snilay@cs.wisc.edu
1018920Snilay@cs.wisc.edu        self.isMachineType = (ident == "MachineType")
1023395Shsul@eecs.umich.edu
1035361Srstrong@cs.ucsd.edu        self.data_members = orderdict()
1048920Snilay@cs.wisc.edu
1058920Snilay@cs.wisc.edu        # Methods
1068920Snilay@cs.wisc.edu        self.methods = {}
1079151Satgutier@umich.edu
1089151Satgutier@umich.edu        # Enums
1099151Satgutier@umich.edu        self.enums = orderdict()
1109151Satgutier@umich.edu
1119151Satgutier@umich.edu    @property
1129151Satgutier@umich.edu    def isPrimitive(self):
1138920Snilay@cs.wisc.edu        return "primitive" in self
1148920Snilay@cs.wisc.edu    @property
1158920Snilay@cs.wisc.edu    def isNetworkMessage(self):
1168920Snilay@cs.wisc.edu        return "networkmessage" in self
1178920Snilay@cs.wisc.edu    @property
1188920Snilay@cs.wisc.edu    def isMessage(self):
1198920Snilay@cs.wisc.edu        return "message" in self
1208920Snilay@cs.wisc.edu    @property
1218920Snilay@cs.wisc.edu    def isBuffer(self):
1228920Snilay@cs.wisc.edu        return "buffer" in self
1238920Snilay@cs.wisc.edu    @property
1248920Snilay@cs.wisc.edu    def isInPort(self):
1258920Snilay@cs.wisc.edu        return "inport" in self
1268920Snilay@cs.wisc.edu    @property
1278920Snilay@cs.wisc.edu    def isOutPort(self):
1288920Snilay@cs.wisc.edu        return "outport" in self
1298920Snilay@cs.wisc.edu    @property
1308920Snilay@cs.wisc.edu    def isEnumeration(self):
1318920Snilay@cs.wisc.edu        return "enumeration" in self
1328920Snilay@cs.wisc.edu    @property
1338920Snilay@cs.wisc.edu    def isExternal(self):
1348920Snilay@cs.wisc.edu        return "external" in self
1358920Snilay@cs.wisc.edu    @property
1368920Snilay@cs.wisc.edu    def isGlobal(self):
1378920Snilay@cs.wisc.edu        return "global" in self
1388920Snilay@cs.wisc.edu    @property
1398920Snilay@cs.wisc.edu    def isInterface(self):
1408920Snilay@cs.wisc.edu        return "interface" in self
1418920Snilay@cs.wisc.edu
1428920Snilay@cs.wisc.edu    # Return false on error
1438920Snilay@cs.wisc.edu    def dataMemberAdd(self, ident, type, pairs, init_code):
1448920Snilay@cs.wisc.edu        if ident in self.data_members:
1458920Snilay@cs.wisc.edu            return False
1468920Snilay@cs.wisc.edu
1478920Snilay@cs.wisc.edu        member = DataMember(ident, type, pairs, init_code)
1488920Snilay@cs.wisc.edu        self.data_members[ident] = member
1498920Snilay@cs.wisc.edu
1508920Snilay@cs.wisc.edu        return True
1518920Snilay@cs.wisc.edu
1528920Snilay@cs.wisc.edu    def dataMemberType(self, ident):
1538920Snilay@cs.wisc.edu        return self.data_members[ident].type
1548920Snilay@cs.wisc.edu
1558920Snilay@cs.wisc.edu    def methodId(self, name, param_type_vec):
1568920Snilay@cs.wisc.edu        return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
1578920Snilay@cs.wisc.edu
1588920Snilay@cs.wisc.edu    def methodIdAbstract(self, name, param_type_vec):
1598920Snilay@cs.wisc.edu        return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
1608920Snilay@cs.wisc.edu
1618920Snilay@cs.wisc.edu    def methodAdd(self, name, return_type, param_type_vec):
1628920Snilay@cs.wisc.edu        ident = self.methodId(name, param_type_vec)
1638920Snilay@cs.wisc.edu        if ident in self.methods:
1648920Snilay@cs.wisc.edu            return False
1658920Snilay@cs.wisc.edu
1668920Snilay@cs.wisc.edu        self.methods[ident] = Method(return_type, param_type_vec)
1678920Snilay@cs.wisc.edu        return True
1688920Snilay@cs.wisc.edu
1698920Snilay@cs.wisc.edu    def enumAdd(self, ident, pairs):
1708920Snilay@cs.wisc.edu        if ident in self.enums:
1718920Snilay@cs.wisc.edu            return False
1728920Snilay@cs.wisc.edu
1738920Snilay@cs.wisc.edu        self.enums[ident] = Enumeration(ident, pairs)
1748920Snilay@cs.wisc.edu
1758956Sjayneel@cs.wisc.edu        # Add default
1768956Sjayneel@cs.wisc.edu        if "default" not in self:
1778956Sjayneel@cs.wisc.edu            self["default"] = "%s_NUM" % self.c_ident
1788956Sjayneel@cs.wisc.edu
1798956Sjayneel@cs.wisc.edu        return True
1808956Sjayneel@cs.wisc.edu
1818956Sjayneel@cs.wisc.edu    def writeCodeFiles(self, path):
1828976Sjayneel@cs.wisc.edu        if self.isExternal:
183            # Do nothing
184            pass
185        elif self.isEnumeration:
186            self.printEnumHH(path)
187            self.printEnumCC(path)
188        else:
189            # User defined structs and messages
190            self.printTypeHH(path)
191            self.printTypeCC(path)
192
193    def printTypeHH(self, path):
194        code = self.symtab.codeFormatter()
195        code('''
196/** \\file ${{self.c_ident}}.hh
197 *
198 *
199 * Auto generated C++ code started by $__file__:$__line__
200 */
201
202#ifndef __${{self.c_ident}}_HH__
203#define __${{self.c_ident}}_HH__
204
205#include <iostream>
206
207#include "mem/ruby/common/Global.hh"
208''')
209
210        for dm in self.data_members.values():
211            if not dm.type.isPrimitive:
212                code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
213
214        parent = ""
215        if "interface" in self:
216            code('#include "mem/protocol/$0.hh"', self["interface"])
217            parent = " :  public %s" % self["interface"]
218
219        code('''
220$klass ${{self.c_ident}}$parent
221{
222  public:
223    ${{self.c_ident}}()
224    {
225''', klass="class")
226
227        code.indent()
228        if not self.isGlobal:
229            code.indent()
230            for dm in self.data_members.values():
231                ident = dm.ident
232                if "default" in dm:
233                    # look for default value
234                    code('m_$ident = ${{dm["default"]}}; // default for this field')
235                elif "default" in dm.type:
236                    # Look for the type default
237                    tid = dm.type.c_ident
238                    code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
239                else:
240                    code('// m_$ident has no default')
241            code.dedent()
242        code('}')
243
244        # ******** Copy constructor ********
245        if not self.isGlobal:
246            code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
247
248            # Call superclass constructor
249            if "interface" in self:
250                code('    : ${{self["interface"]}}(other)')
251
252            code('{')
253            code.indent()
254
255            for dm in self.data_members.values():
256                code('m_${{dm.ident}} = other.m_${{dm.ident}};')
257
258            if self.isMessage:
259                code('proc_id = other.proc_id;')
260
261            code.dedent()
262            code('}')
263
264        # ******** Full init constructor ********
265        if not self.isGlobal:
266            params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
267                       for dm in self.data_members.itervalues() ]
268
269            if self.isMessage:
270                params.append('const unsigned local_proc_id')
271
272            params = ', '.join(params)
273            code('${{self.c_ident}}($params)')
274
275            # Call superclass constructor
276            if "interface" in self:
277                code('    : ${{self["interface"]}}()')
278
279            code('{')
280            code.indent()
281            for dm in self.data_members.values():
282                code('m_${{dm.ident}} = local_${{dm.ident}};')
283                if "nextLineCallHack" in dm:
284                    code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};')
285
286            if self.isMessage:
287                code('proc_id = local_proc_id;')
288
289            code.dedent()
290            code('}')
291
292        # create a static factory method and a clone member
293        code('''
294static ${{self.c_ident}}*
295create()
296{
297    return new ${{self.c_ident}}();
298}
299
300${{self.c_ident}}*
301clone() const
302{
303     return new ${{self.c_ident}}(*this);
304}
305''')
306
307        if not self.isGlobal:
308            # const Get methods for each field
309            code('// Const accessors methods for each field')
310            for dm in self.data_members.values():
311                code('''
312/** \\brief Const accessor method for ${{dm.ident}} field.
313 *  \\return ${{dm.ident}} field
314 */
315const ${{dm.type.c_ident}}&
316get${{dm.ident}}() const
317{
318    return m_${{dm.ident}};
319}
320''')
321
322            # Non-const Get methods for each field
323            code('// Non const Accessors methods for each field')
324            for dm in self.data_members.values():
325                code('''
326/** \\brief Non-const accessor method for ${{dm.ident}} field.
327 *  \\return ${{dm.ident}} field
328 */
329${{dm.type.c_ident}}&
330get${{dm.ident}}()
331{
332    return m_${{dm.ident}};
333}
334''')
335
336            #Set methods for each field
337            code('// Mutator methods for each field')
338            for dm in self.data_members.values():
339                code('''
340/** \\brief Mutator method for ${{dm.ident}} field */
341void
342set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
343{
344    m_${{dm.ident}} = local_${{dm.ident}};
345}
346''')
347
348        code('void print(std::ostream& out) const;')
349        code.dedent()
350        code('  //private:')
351        code.indent()
352
353        # Data members for each field
354        for dm in self.data_members.values():
355            if "abstract" not in dm:
356                const = ""
357                init = ""
358
359                # global structure
360                if self.isGlobal:
361                    const = "static const "
362
363                # init value
364                if dm.init_code:
365                    # only global structure can have init value here
366                    assert self.isGlobal
367                    init = " = %s" % (dm.init_code)
368
369                if "desc" in dm:
370                    code('/** ${{dm["desc"]}} */')
371
372                code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
373
374        if self.isMessage:
375            code('unsigned proc_id;')
376
377        code.dedent()
378        code('};')
379
380        code('''
381inline std::ostream&
382operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
383{
384    obj.print(out);
385    out << std::flush;
386    return out;
387}
388
389#endif // __${{self.c_ident}}_HH__
390''')
391
392        code.write(path, "%s.hh" % self.c_ident)
393
394    def printTypeCC(self, path):
395        code = self.symtab.codeFormatter()
396
397        code('''
398/** \\file ${{self.c_ident}}.cc
399 *
400 * Auto generated C++ code started by $__file__:$__line__
401 */
402
403#include <iostream>
404
405#include "mem/protocol/${{self.c_ident}}.hh"
406
407using namespace std;
408''')
409
410        code('''
411/** \\brief Print the state of this object */
412void
413${{self.c_ident}}::print(ostream& out) const
414{
415    out << "[${{self.c_ident}}: ";
416''')
417
418        # For each field
419        code.indent()
420        for dm in self.data_members.values():
421            code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
422
423        if self.isMessage:
424            code('out << "Time = " << getTime() << " ";')
425        code.dedent()
426
427        # Trailer
428        code('''
429    out << "]";
430}''')
431
432        code.write(path, "%s.cc" % self.c_ident)
433
434    def printEnumHH(self, path):
435        code = self.symtab.codeFormatter()
436        code('''
437/** \\file ${{self.c_ident}}.hh
438 *
439 * Auto generated C++ code started by $__file__:$__line__
440 */
441
442#ifndef __${{self.c_ident}}_HH__
443#define __${{self.c_ident}}_HH__
444
445#include <iostream>
446#include <string>
447
448#include "mem/ruby/common/Global.hh"
449
450// Class definition
451/** \\enum ${{self.c_ident}}
452 *  \\brief ${{self.desc}}
453 */
454enum ${{self.c_ident}} {
455    ${{self.c_ident}}_FIRST,
456''')
457
458        code.indent()
459        # For each field
460        for i,(ident,enum) in enumerate(self.enums.iteritems()):
461            desc = enum.get("desc", "No description avaliable")
462            if i == 0:
463                init = ' = %s_FIRST' % self.c_ident
464            else:
465                init = ''
466            code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
467        code.dedent()
468        code('''
469    ${{self.c_ident}}_NUM
470};
471
472// Code to convert from a string to the enumeration
473${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
474
475// Code to convert state to a string
476std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
477
478// Code to increment an enumeration type
479${{self.c_ident}} &operator++(${{self.c_ident}} &e);
480''')
481
482        # MachineType hack used to set the base component id for each Machine
483        if self.isMachineType:
484            code('''
485int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
486MachineType ${{self.c_ident}}_from_base_level(int);
487int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
488int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
489''')
490
491            for enum in self.enums.itervalues():
492                code('#define MACHINETYPE_${{enum.ident}} 1')
493
494        # Trailer
495        code('''
496std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
497
498#endif // __${{self.c_ident}}_HH__
499''')
500
501        code.write(path, "%s.hh" % self.c_ident)
502
503    def printEnumCC(self, path):
504        code = self.symtab.codeFormatter()
505        code('''
506/** \\file ${{self.c_ident}}.hh
507 *
508 * Auto generated C++ code started by $__file__:$__line__
509 */
510
511#include <cassert>
512#include <iostream>
513#include <string>
514
515#include "base/misc.hh"
516#include "mem/protocol/${{self.c_ident}}.hh"
517
518using namespace std;
519
520''')
521
522        if self.isMachineType:
523            for enum in self.enums.itervalues():
524                code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
525
526        code('''
527// Code for output operator
528ostream&
529operator<<(ostream& out, const ${{self.c_ident}}& obj)
530{
531    out << ${{self.c_ident}}_to_string(obj);
532    out << flush;
533    return out;
534}
535
536// Code to convert state to a string
537string
538${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
539{
540    switch(obj) {
541''')
542
543        # For each field
544        code.indent()
545        for enum in self.enums.itervalues():
546            code('  case ${{self.c_ident}}_${{enum.ident}}:')
547            code('    return "${{enum.ident}}";')
548        code.dedent()
549
550        # Trailer
551        code('''
552      default:
553        panic("Invalid range for type ${{self.c_ident}}");
554    }
555}
556
557// Code to convert from a string to the enumeration
558${{self.c_ident}}
559string_to_${{self.c_ident}}(const string& str)
560{
561''')
562
563        # For each field
564        start = ""
565        code.indent()
566        for enum in self.enums.itervalues():
567            code('${start}if (str == "${{enum.ident}}") {')
568            code('    return ${{self.c_ident}}_${{enum.ident}};')
569            start = "} else "
570        code.dedent()
571
572        code('''
573    } else {
574        panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
575    }
576}
577
578// Code to increment an enumeration type
579${{self.c_ident}}&
580operator++(${{self.c_ident}}& e)
581{
582    assert(e < ${{self.c_ident}}_NUM);
583    return e = ${{self.c_ident}}(e+1);
584}
585''')
586
587        # MachineType hack used to set the base level and number of
588        # components for each Machine
589        if self.isMachineType:
590            code('''
591/** \\brief returns the base vector index for each machine type to be
592  * used by NetDest
593  *
594  * \\return the base vector index for each machine type to be used by NetDest
595  * \\see NetDest.hh
596  */
597int
598${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
599{
600    switch(obj) {
601''')
602
603            # For each field
604            code.indent()
605            for i,enum in enumerate(self.enums.itervalues()):
606                code('  case ${{self.c_ident}}_${{enum.ident}}:')
607                code('    return $i;')
608            code.dedent()
609
610            # total num
611            code('''
612      case ${{self.c_ident}}_NUM:
613        return ${{len(self.enums)}};
614
615      default:
616        panic("Invalid range for type ${{self.c_ident}}");
617    }
618}
619
620/** \\brief returns the machine type for each base vector index used by NetDest
621 *
622 * \\return the MachineType
623 */
624MachineType
625${{self.c_ident}}_from_base_level(int type)
626{
627    switch(type) {
628''')
629
630            # For each field
631            code.indent()
632            for i,enum in enumerate(self.enums.itervalues()):
633                code('  case $i:')
634                code('    return ${{self.c_ident}}_${{enum.ident}};')
635            code.dedent()
636
637            # Trailer
638            code('''
639      default:
640        panic("Invalid range for type ${{self.c_ident}}");
641    }
642}
643
644/** \\brief The return value indicates the number of components created
645 * before a particular machine\'s components
646 *
647 * \\return the base number of components for each machine
648 */
649int
650${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
651{
652    int base = 0;
653    switch(obj) {
654''')
655
656            # For each field
657            code.indent()
658            code('  case ${{self.c_ident}}_NUM:')
659            for enum in reversed(self.enums.values()):
660                code('    base += ${{enum.ident}}_Controller::getNumControllers();')
661                code('  case ${{self.c_ident}}_${{enum.ident}}:')
662            code('    break;')
663            code.dedent()
664
665            code('''
666      default:
667        panic("Invalid range for type ${{self.c_ident}}");
668    }
669
670    return base;
671}
672
673/** \\brief returns the total number of components for each machine
674 * \\return the total number of components for each machine
675 */
676int
677${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
678{
679    switch(obj) {
680''')
681
682            # For each field
683            for enum in self.enums.itervalues():
684                code('''
685      case ${{self.c_ident}}_${{enum.ident}}:
686        return ${{enum.ident}}_Controller::getNumControllers();
687''')
688
689            # total num
690            code('''
691      case ${{self.c_ident}}_NUM:
692      default:
693        panic("Invalid range for type ${{self.c_ident}}");
694    }
695}
696''')
697
698        # Write the file
699        code.write(path, "%s.cc" % self.c_ident)
700
701__all__ = [ "Type" ]
702