Type.py revision 8602
13970Sgblack@eecs.umich.edu# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
23005Sstever@eecs.umich.edu# Copyright (c) 2009 The Hewlett-Packard Development Company
33005Sstever@eecs.umich.edu# All rights reserved.
43005Sstever@eecs.umich.edu#
53005Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
63005Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are
73005Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright
83005Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
93005Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
103005Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
113005Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution;
123005Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its
133005Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from
143005Sstever@eecs.umich.edu# this software without specific prior written permission.
153005Sstever@eecs.umich.edu#
163005Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173005Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183005Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193005Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203005Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213005Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223005Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233005Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243005Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253005Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263005Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273005Sstever@eecs.umich.edu
283005Sstever@eecs.umich.edufrom m5.util import orderdict
292889SN/A
302889SN/Afrom slicc.util import PairContainer
312710SN/Afrom slicc.symbols.Symbol import Symbol
322710SN/A
332934SN/Aclass DataMember(PairContainer):
342934SN/A    def __init__(self, ident, type, pairs, init_code):
352549SN/A        super(DataMember, self).__init__(pairs)
362995SN/A        self.ident = ident
373395Shsul@eecs.umich.edu        self.type = type
383448Shsul@eecs.umich.edu        self.init_code = init_code
392549SN/A
403088Sstever@eecs.umich.educlass Enumeration(PairContainer):
413088Sstever@eecs.umich.edu    def __init__(self, ident, pairs):
423088Sstever@eecs.umich.edu        super(Enumeration, self).__init__(pairs)
433444Sktlim@umich.edu        self.ident = ident
443444Sktlim@umich.edu
453444Sktlim@umich.educlass Method(object):
463444Sktlim@umich.edu    def __init__(self, return_type, param_types):
472889SN/A        self.return_type = return_type
482710SN/A        self.param_types = param_types
493873Sbinkertn@umich.edu
503873Sbinkertn@umich.educlass Type(Symbol):
513873Sbinkertn@umich.edu    def __init__(self, table, ident, location, pairs, machine=None):
523873Sbinkertn@umich.edu        super(Type, self).__init__(table, ident, location, pairs)
533322Shsul@eecs.umich.edu        self.c_ident = ident
543668Srdreslin@umich.edu        self.abstract_ident = ""
552995SN/A        if machine:
562995SN/A            if self.isExternal or self.isPrimitive:
572995SN/A                if "external_name" in self:
582995SN/A                    self.c_ident = self["external_name"]
592995SN/A            else:
603143Shsul@eecs.umich.edu                # Append with machine name
613322Shsul@eecs.umich.edu                self.c_ident = "%s_%s" % (machine, ident)
623322Shsul@eecs.umich.edu
633025Ssaidi@eecs.umich.edu        self.pairs.setdefault("desc", "No description avaliable")
643143Shsul@eecs.umich.edu
653143Shsul@eecs.umich.edu        # check for interface that this Type implements
663322Shsul@eecs.umich.edu        if "interface" in self:
673444Sktlim@umich.edu            interface = self["interface"]
683322Shsul@eecs.umich.edu            if interface in ("Message", "NetworkMessage"):
692710SN/A                self["message"] = "yes"
702710SN/A            if interface == "NetworkMessage":
712710SN/A                self["networkmessage"] = "yes"
722710SN/A
732710SN/A        # FIXME - all of the following id comparisons are fragile hacks
742710SN/A        if self.ident in ("CacheMemory", "NewCacheMemory",
753322Shsul@eecs.umich.edu                          "TLCCacheMemory", "DNUCACacheMemory",
763304Sstever@eecs.umich.edu                          "DNUCABankCacheMemory", "L2BankCacheMemory",
773322Shsul@eecs.umich.edu                          "CompressedCacheMemory", "PrefetchCacheMemory"):
783322Shsul@eecs.umich.edu            self["cache"] = "yes"
793304Sstever@eecs.umich.edu
803481Shsul@eecs.umich.edu        if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"):
813481Shsul@eecs.umich.edu            self["tbe"] = "yes"
822566SN/A
833322Shsul@eecs.umich.edu        if self.ident == "NewTBETable":
843322Shsul@eecs.umich.edu            self["newtbe"] = "yes"
852995SN/A
862995SN/A        if self.ident == "TimerTable":
873304Sstever@eecs.umich.edu            self["timer"] = "yes"
883304Sstever@eecs.umich.edu
893304Sstever@eecs.umich.edu        if self.ident == "DirectoryMemory":
902995SN/A            self["dir"] = "yes"
912995SN/A
922995SN/A        if self.ident == "PersistentTable":
932917SN/A            self["persistent"] = "yes"
942995SN/A
953304Sstever@eecs.umich.edu        if self.ident == "Prefetcher":
962995SN/A            self["prefetcher"] = "yes"
973304Sstever@eecs.umich.edu
983304Sstever@eecs.umich.edu        if self.ident == "DNUCA_Movement":
993819Shsul@eecs.umich.edu            self["mover"] = "yes"
1003819Shsul@eecs.umich.edu
1013819Shsul@eecs.umich.edu        self.isMachineType = (ident == "MachineType")
1023819Shsul@eecs.umich.edu
1033819Shsul@eecs.umich.edu        self.isStateDecl = ("state_decl" in self)
1043819Shsul@eecs.umich.edu        self.statePermPairs = []
1053819Shsul@eecs.umich.edu
1063873Sbinkertn@umich.edu        self.data_members = orderdict()
1073873Sbinkertn@umich.edu
1083873Sbinkertn@umich.edu        # Methods
1093873Sbinkertn@umich.edu        self.methods = {}
1103873Sbinkertn@umich.edu
1113873Sbinkertn@umich.edu        # Enums
1123312Sstever@eecs.umich.edu        self.enums = orderdict()
1133668Srdreslin@umich.edu
1143668Srdreslin@umich.edu    @property
1153668Srdreslin@umich.edu    def isPrimitive(self):
1163668Srdreslin@umich.edu        return "primitive" in self
1173668Srdreslin@umich.edu    @property
1183668Srdreslin@umich.edu    def isNetworkMessage(self):
1193668Srdreslin@umich.edu        return "networkmessage" in self
1203322Shsul@eecs.umich.edu    @property
1213312Sstever@eecs.umich.edu    def isMessage(self):
1223514Sktlim@umich.edu        return "message" in self
1233395Shsul@eecs.umich.edu    @property
1243448Shsul@eecs.umich.edu    def isBuffer(self):
1253668Srdreslin@umich.edu        return "buffer" in self
1263668Srdreslin@umich.edu    @property
1273668Srdreslin@umich.edu    def isInPort(self):
1283668Srdreslin@umich.edu        return "inport" in self
1293668Srdreslin@umich.edu    @property
1303005Sstever@eecs.umich.edu    def isOutPort(self):
1313005Sstever@eecs.umich.edu        return "outport" in self
1323819Shsul@eecs.umich.edu    @property
1333819Shsul@eecs.umich.edu    def isEnumeration(self):
1343819Shsul@eecs.umich.edu        return "enumeration" in self
1353819Shsul@eecs.umich.edu    @property
1363322Shsul@eecs.umich.edu    def isExternal(self):
1373322Shsul@eecs.umich.edu        return "external" in self
1383322Shsul@eecs.umich.edu    @property
1393005Sstever@eecs.umich.edu    def isGlobal(self):
1404167Sbinkertn@umich.edu        return "global" in self
1413005Sstever@eecs.umich.edu    @property
1423005Sstever@eecs.umich.edu    def isInterface(self):
1433005Sstever@eecs.umich.edu        return "interface" in self
1442566SN/A
1453481Shsul@eecs.umich.edu    # Return false on error
146    def dataMemberAdd(self, ident, type, pairs, init_code):
147        if ident in self.data_members:
148            return False
149
150        member = DataMember(ident, type, pairs, init_code)
151        self.data_members[ident] = member
152
153        return True
154
155    def dataMemberType(self, ident):
156        return self.data_members[ident].type
157
158    def methodId(self, name, param_type_vec):
159        return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
160
161    def methodIdAbstract(self, name, param_type_vec):
162        return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
163
164    def statePermPairAdd(self, state_name, perm_name):
165        self.statePermPairs.append([state_name, perm_name])
166
167    def methodAdd(self, name, return_type, param_type_vec):
168        ident = self.methodId(name, param_type_vec)
169        if ident in self.methods:
170            return False
171
172        self.methods[ident] = Method(return_type, param_type_vec)
173        return True
174
175    def enumAdd(self, ident, pairs):
176        if ident in self.enums:
177            return False
178
179        self.enums[ident] = Enumeration(ident, pairs)
180
181        # Add default
182        if "default" not in self:
183            self["default"] = "%s_NUM" % self.c_ident
184
185        return True
186
187    def writeCodeFiles(self, path):
188        if self.isExternal:
189            # Do nothing
190            pass
191        elif self.isEnumeration:
192            self.printEnumHH(path)
193            self.printEnumCC(path)
194        else:
195            # User defined structs and messages
196            self.printTypeHH(path)
197            self.printTypeCC(path)
198
199    def printTypeHH(self, path):
200        code = self.symtab.codeFormatter()
201        code('''
202/** \\file ${{self.c_ident}}.hh
203 *
204 *
205 * Auto generated C++ code started by $__file__:$__line__
206 */
207
208#ifndef __${{self.c_ident}}_HH__
209#define __${{self.c_ident}}_HH__
210
211#include <iostream>
212
213#include "mem/ruby/common/Global.hh"
214''')
215
216        for dm in self.data_members.values():
217            if not dm.type.isPrimitive:
218                code('#include "mem/protocol/$0.hh"', dm.type.c_ident)
219
220        parent = ""
221        if "interface" in self:
222            code('#include "mem/protocol/$0.hh"', self["interface"])
223            parent = " :  public %s" % self["interface"]
224
225        code('''
226$klass ${{self.c_ident}}$parent
227{
228  public:
229    ${{self.c_ident}}()
230    {
231''', klass="class")
232
233        code.indent()
234        if not self.isGlobal:
235            code.indent()
236            for dm in self.data_members.values():
237                ident = dm.ident
238                if "default" in dm:
239                    # look for default value
240                    code('m_$ident = ${{dm["default"]}}; // default for this field')
241                elif "default" in dm.type:
242                    # Look for the type default
243                    tid = dm.type.c_ident
244                    code('m_$ident = ${{dm.type["default"]}}; // default value of $tid')
245                else:
246                    code('// m_$ident has no default')
247            code.dedent()
248        code('}')
249
250        # ******** Copy constructor ********
251        if not self.isGlobal:
252            code('${{self.c_ident}}(const ${{self.c_ident}}&other)')
253
254            # Call superclass constructor
255            if "interface" in self:
256                code('    : ${{self["interface"]}}(other)')
257
258            code('{')
259            code.indent()
260
261            for dm in self.data_members.values():
262                code('m_${{dm.ident}} = other.m_${{dm.ident}};')
263
264            code.dedent()
265            code('}')
266
267        # ******** Full init constructor ********
268        if not self.isGlobal:
269            params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \
270                       for dm in self.data_members.itervalues() ]
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            code.dedent()
287            code('}')
288
289        # create a static factory method and a clone member
290        code('''
291static ${{self.c_ident}}*
292create()
293{
294    return new ${{self.c_ident}}();
295}
296
297${{self.c_ident}}*
298clone() const
299{
300     return new ${{self.c_ident}}(*this);
301}
302''')
303
304        if not self.isGlobal:
305            # const Get methods for each field
306            code('// Const accessors methods for each field')
307            for dm in self.data_members.values():
308                code('''
309/** \\brief Const accessor method for ${{dm.ident}} field.
310 *  \\return ${{dm.ident}} field
311 */
312const ${{dm.type.c_ident}}&
313get${{dm.ident}}() const
314{
315    return m_${{dm.ident}};
316}
317''')
318
319            # Non-const Get methods for each field
320            code('// Non const Accessors methods for each field')
321            for dm in self.data_members.values():
322                code('''
323/** \\brief Non-const accessor method for ${{dm.ident}} field.
324 *  \\return ${{dm.ident}} field
325 */
326${{dm.type.c_ident}}&
327get${{dm.ident}}()
328{
329    return m_${{dm.ident}};
330}
331''')
332
333            #Set methods for each field
334            code('// Mutator methods for each field')
335            for dm in self.data_members.values():
336                code('''
337/** \\brief Mutator method for ${{dm.ident}} field */
338void
339set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
340{
341    m_${{dm.ident}} = local_${{dm.ident}};
342}
343''')
344
345        code('void print(std::ostream& out) const;')
346        code.dedent()
347        code('  //private:')
348        code.indent()
349
350        # Data members for each field
351        for dm in self.data_members.values():
352            if "abstract" not in dm:
353                const = ""
354                init = ""
355
356                # global structure
357                if self.isGlobal:
358                    const = "static const "
359
360                # init value
361                if dm.init_code:
362                    # only global structure can have init value here
363                    assert self.isGlobal
364                    init = " = %s" % (dm.init_code)
365
366                if "desc" in dm:
367                    code('/** ${{dm["desc"]}} */')
368
369                code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
370
371        code.dedent()
372        code('};')
373
374        code('''
375inline std::ostream&
376operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
377{
378    obj.print(out);
379    out << std::flush;
380    return out;
381}
382
383#endif // __${{self.c_ident}}_HH__
384''')
385
386        code.write(path, "%s.hh" % self.c_ident)
387
388    def printTypeCC(self, path):
389        code = self.symtab.codeFormatter()
390
391        code('''
392/** \\file ${{self.c_ident}}.cc
393 *
394 * Auto generated C++ code started by $__file__:$__line__
395 */
396
397#include <iostream>
398
399#include "mem/protocol/${{self.c_ident}}.hh"
400
401using namespace std;
402''')
403
404        code('''
405/** \\brief Print the state of this object */
406void
407${{self.c_ident}}::print(ostream& out) const
408{
409    out << "[${{self.c_ident}}: ";
410''')
411
412        # For each field
413        code.indent()
414        for dm in self.data_members.values():
415            code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''')
416
417        if self.isMessage:
418            code('out << "Time = " << getTime() * g_eventQueue_ptr->getClock() << " ";')
419        code.dedent()
420
421        # Trailer
422        code('''
423    out << "]";
424}''')
425
426        code.write(path, "%s.cc" % self.c_ident)
427
428    def printEnumHH(self, path):
429        code = self.symtab.codeFormatter()
430        code('''
431/** \\file ${{self.c_ident}}.hh
432 *
433 * Auto generated C++ code started by $__file__:$__line__
434 */
435
436#ifndef __${{self.c_ident}}_HH__
437#define __${{self.c_ident}}_HH__
438
439#include <iostream>
440#include <string>
441
442#include "mem/ruby/common/Global.hh"
443''')
444        if self.isStateDecl:
445            code('#include "mem/protocol/AccessPermission.hh"')
446
447        if self.isMachineType:
448            code('#include "base/misc.hh"')
449            code('#include "mem/protocol/GenericMachineType.hh"')
450            code('#include "mem/ruby/common/Address.hh"')
451            code('#include "mem/ruby/system/NodeID.hh"')
452            code('struct MachineID;')
453
454        code('''
455
456// Class definition
457/** \\enum ${{self.c_ident}}
458 *  \\brief ${{self.desc}}
459 */
460enum ${{self.c_ident}} {
461    ${{self.c_ident}}_FIRST,
462''')
463
464        code.indent()
465        # For each field
466        for i,(ident,enum) in enumerate(self.enums.iteritems()):
467            desc = enum.get("desc", "No description avaliable")
468            if i == 0:
469                init = ' = %s_FIRST' % self.c_ident
470            else:
471                init = ''
472            code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */')
473        code.dedent()
474        code('''
475    ${{self.c_ident}}_NUM
476};
477
478// Code to convert from a string to the enumeration
479${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str);
480
481// Code to convert state to a string
482std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj);
483
484// Code to increment an enumeration type
485${{self.c_ident}} &operator++(${{self.c_ident}} &e);
486''')
487
488        # MachineType hack used to set the base component id for each Machine
489        if self.isMachineType:
490            code('''
491int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj);
492MachineType ${{self.c_ident}}_from_base_level(int);
493int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj);
494int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj);
495''')
496
497            for enum in self.enums.itervalues():
498                if enum.ident == "DMA":
499                    code('''
500MachineID map_Address_to_DMA(const Address &addr);
501''')
502                code('''
503
504MachineID get${{enum.ident}}MachineID(NodeID RubyNode);
505''')
506
507            code('''
508inline GenericMachineType
509ConvertMachToGenericMach(MachineType machType)
510{
511''')
512            for enum in self.enums.itervalues():
513                code('''
514      if (machType == MachineType_${{enum.ident}})
515          return GenericMachineType_${{enum.ident}};
516''')
517            code('''
518      panic("cannot convert to a GenericMachineType");
519}
520''')
521
522        if self.isStateDecl:
523            code('''
524
525// Code to convert the current state to an access permission
526AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj);
527
528''')
529
530        # Trailer
531        code('''
532std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj);
533
534#endif // __${{self.c_ident}}_HH__
535''')
536
537        code.write(path, "%s.hh" % self.c_ident)
538
539    def printEnumCC(self, path):
540        code = self.symtab.codeFormatter()
541        code('''
542/** \\file ${{self.c_ident}}.hh
543 *
544 * Auto generated C++ code started by $__file__:$__line__
545 */
546
547#include <cassert>
548#include <iostream>
549#include <string>
550
551#include "base/misc.hh"
552#include "mem/protocol/${{self.c_ident}}.hh"
553
554using namespace std;
555
556''')
557
558        if self.isStateDecl:
559            code('''
560// Code to convert the current state to an access permission
561AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj)
562{
563    switch(obj) {
564''')
565            # For each case
566            code.indent()
567            for statePerm in self.statePermPairs:
568                code('  case ${{self.c_ident}}_${{statePerm[0]}}:')
569                code('    return AccessPermission_${{statePerm[1]}};')
570            code.dedent()
571            code ('''
572      default:
573        panic("Unknown state access permission converstion for ${{self.c_ident}}");
574    }
575}
576
577''')
578
579        if self.isMachineType:
580            for enum in self.enums.itervalues():
581                code('#include "mem/protocol/${{enum.ident}}_Controller.hh"')
582            code('#include "mem/ruby/system/MachineID.hh"')
583
584        code('''
585// Code for output operator
586ostream&
587operator<<(ostream& out, const ${{self.c_ident}}& obj)
588{
589    out << ${{self.c_ident}}_to_string(obj);
590    out << flush;
591    return out;
592}
593
594// Code to convert state to a string
595string
596${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj)
597{
598    switch(obj) {
599''')
600
601        # For each field
602        code.indent()
603        for enum in self.enums.itervalues():
604            code('  case ${{self.c_ident}}_${{enum.ident}}:')
605            code('    return "${{enum.ident}}";')
606        code.dedent()
607
608        # Trailer
609        code('''
610      default:
611        panic("Invalid range for type ${{self.c_ident}}");
612    }
613}
614
615// Code to convert from a string to the enumeration
616${{self.c_ident}}
617string_to_${{self.c_ident}}(const string& str)
618{
619''')
620
621        # For each field
622        start = ""
623        code.indent()
624        for enum in self.enums.itervalues():
625            code('${start}if (str == "${{enum.ident}}") {')
626            code('    return ${{self.c_ident}}_${{enum.ident}};')
627            start = "} else "
628        code.dedent()
629
630        code('''
631    } else {
632        panic("Invalid string conversion for %s, type ${{self.c_ident}}", str);
633    }
634}
635
636// Code to increment an enumeration type
637${{self.c_ident}}&
638operator++(${{self.c_ident}}& e)
639{
640    assert(e < ${{self.c_ident}}_NUM);
641    return e = ${{self.c_ident}}(e+1);
642}
643''')
644
645        # MachineType hack used to set the base level and number of
646        # components for each Machine
647        if self.isMachineType:
648            code('''
649/** \\brief returns the base vector index for each machine type to be
650  * used by NetDest
651  *
652  * \\return the base vector index for each machine type to be used by NetDest
653  * \\see NetDest.hh
654  */
655int
656${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj)
657{
658    switch(obj) {
659''')
660
661            # For each field
662            code.indent()
663            for i,enum in enumerate(self.enums.itervalues()):
664                code('  case ${{self.c_ident}}_${{enum.ident}}:')
665                code('    return $i;')
666            code.dedent()
667
668            # total num
669            code('''
670      case ${{self.c_ident}}_NUM:
671        return ${{len(self.enums)}};
672
673      default:
674        panic("Invalid range for type ${{self.c_ident}}");
675    }
676}
677
678/** \\brief returns the machine type for each base vector index used by NetDest
679 *
680 * \\return the MachineType
681 */
682MachineType
683${{self.c_ident}}_from_base_level(int type)
684{
685    switch(type) {
686''')
687
688            # For each field
689            code.indent()
690            for i,enum in enumerate(self.enums.itervalues()):
691                code('  case $i:')
692                code('    return ${{self.c_ident}}_${{enum.ident}};')
693            code.dedent()
694
695            # Trailer
696            code('''
697      default:
698        panic("Invalid range for type ${{self.c_ident}}");
699    }
700}
701
702/** \\brief The return value indicates the number of components created
703 * before a particular machine\'s components
704 *
705 * \\return the base number of components for each machine
706 */
707int
708${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj)
709{
710    int base = 0;
711    switch(obj) {
712''')
713
714            # For each field
715            code.indent()
716            code('  case ${{self.c_ident}}_NUM:')
717            for enum in reversed(self.enums.values()):
718                code('    base += ${{enum.ident}}_Controller::getNumControllers();')
719                code('  case ${{self.c_ident}}_${{enum.ident}}:')
720            code('    break;')
721            code.dedent()
722
723            code('''
724      default:
725        panic("Invalid range for type ${{self.c_ident}}");
726    }
727
728    return base;
729}
730
731/** \\brief returns the total number of components for each machine
732 * \\return the total number of components for each machine
733 */
734int
735${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj)
736{
737    switch(obj) {
738''')
739
740            # For each field
741            for enum in self.enums.itervalues():
742                code('''
743      case ${{self.c_ident}}_${{enum.ident}}:
744        return ${{enum.ident}}_Controller::getNumControllers();
745''')
746
747            # total num
748            code('''
749      case ${{self.c_ident}}_NUM:
750      default:
751        panic("Invalid range for type ${{self.c_ident}}");
752    }
753}
754''')
755
756            for enum in self.enums.itervalues():
757                if enum.ident == "DMA":
758                    code('''
759MachineID
760map_Address_to_DMA(const Address &addr)
761{
762      MachineID dma = {MachineType_DMA, 0};
763      return dma;
764}
765''')
766
767                code('''
768
769MachineID
770get${{enum.ident}}MachineID(NodeID RubyNode)
771{
772      MachineID mach = {MachineType_${{enum.ident}}, RubyNode};
773      return mach;
774}
775''')
776
777        # Write the file
778        code.write(path, "%s.cc" % self.c_ident)
779
780__all__ = [ "Type" ]
781