Type.py revision 6657
16657Snate@binkert.org# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 26657Snate@binkert.org# Copyright (c) 2009 The Hewlett-Packard Development Company 36657Snate@binkert.org# All rights reserved. 46657Snate@binkert.org# 56657Snate@binkert.org# Redistribution and use in source and binary forms, with or without 66657Snate@binkert.org# modification, are permitted provided that the following conditions are 76657Snate@binkert.org# met: redistributions of source code must retain the above copyright 86657Snate@binkert.org# notice, this list of conditions and the following disclaimer; 96657Snate@binkert.org# redistributions in binary form must reproduce the above copyright 106657Snate@binkert.org# notice, this list of conditions and the following disclaimer in the 116657Snate@binkert.org# documentation and/or other materials provided with the distribution; 126657Snate@binkert.org# neither the name of the copyright holders nor the names of its 136657Snate@binkert.org# contributors may be used to endorse or promote products derived from 146657Snate@binkert.org# this software without specific prior written permission. 156657Snate@binkert.org# 166657Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176657Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186657Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196657Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206657Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216657Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226657Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236657Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246657Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256657Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266657Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276657Snate@binkert.org 286657Snate@binkert.orgfrom m5.util import code_formatter, orderdict 296657Snate@binkert.org 306657Snate@binkert.orgfrom slicc.util import PairContainer 316657Snate@binkert.orgfrom slicc.symbols.Symbol import Symbol 326657Snate@binkert.org 336657Snate@binkert.orgclass DataMember(PairContainer): 346657Snate@binkert.org def __init__(self, ident, type, pairs, init_code): 356657Snate@binkert.org super(DataMember, self).__init__(pairs) 366657Snate@binkert.org self.ident = ident 376657Snate@binkert.org self.type = type 386657Snate@binkert.org self.init_code = init_code 396657Snate@binkert.org 406657Snate@binkert.orgclass Enumeration(PairContainer): 416657Snate@binkert.org def __init__(self, ident, pairs): 426657Snate@binkert.org super(Enumeration, self).__init__(pairs) 436657Snate@binkert.org self.ident = ident 446657Snate@binkert.org 456657Snate@binkert.orgclass Method(object): 466657Snate@binkert.org def __init__(self, return_type, param_types): 476657Snate@binkert.org self.return_type = return_type 486657Snate@binkert.org self.param_types = param_types 496657Snate@binkert.org 506657Snate@binkert.orgclass Type(Symbol): 516657Snate@binkert.org def __init__(self, table, ident, location, pairs, machine=None): 526657Snate@binkert.org super(Type, self).__init__(table, ident, location, pairs) 536657Snate@binkert.org self.c_ident = ident 546657Snate@binkert.org if machine: 556657Snate@binkert.org if self.isExternal or self.isPrimitive: 566657Snate@binkert.org if "external_name" in self: 576657Snate@binkert.org self.c_ident = self["external_name"] 586657Snate@binkert.org else: 596657Snate@binkert.org # Append with machine name 606657Snate@binkert.org self.c_ident = "%s_%s" % (machine, ident) 616657Snate@binkert.org 626657Snate@binkert.org self.pairs.setdefault("desc", "No description avaliable") 636657Snate@binkert.org 646657Snate@binkert.org # check for interface that this Type implements 656657Snate@binkert.org if "interface" in self: 666657Snate@binkert.org interface = self["interface"] 676657Snate@binkert.org if interface in ("Message", "NetworkMessage"): 686657Snate@binkert.org self["message"] = "yes" 696657Snate@binkert.org if interface == "NetworkMessage": 706657Snate@binkert.org self["networkmessage"] = "yes" 716657Snate@binkert.org 726657Snate@binkert.org # FIXME - all of the following id comparisons are fragile hacks 736657Snate@binkert.org if self.ident in ("CacheMemory", "NewCacheMemory", 746657Snate@binkert.org "TLCCacheMemory", "DNUCACacheMemory", 756657Snate@binkert.org "DNUCABankCacheMemory", "L2BankCacheMemory", 766657Snate@binkert.org "CompressedCacheMemory", "PrefetchCacheMemory"): 776657Snate@binkert.org self["cache"] = "yes" 786657Snate@binkert.org 796657Snate@binkert.org if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"): 806657Snate@binkert.org self["tbe"] = "yes" 816657Snate@binkert.org 826657Snate@binkert.org if self.ident == "NewTBETable": 836657Snate@binkert.org self["newtbe"] = "yes" 846657Snate@binkert.org 856657Snate@binkert.org if self.ident == "TimerTable": 866657Snate@binkert.org self["timer"] = "yes" 876657Snate@binkert.org 886657Snate@binkert.org if self.ident == "DirectoryMemory": 896657Snate@binkert.org self["dir"] = "yes" 906657Snate@binkert.org 916657Snate@binkert.org if self.ident == "PersistentTable": 926657Snate@binkert.org self["persistent"] = "yes" 936657Snate@binkert.org 946657Snate@binkert.org if self.ident == "Prefetcher": 956657Snate@binkert.org self["prefetcher"] = "yes" 966657Snate@binkert.org 976657Snate@binkert.org if self.ident == "DNUCA_Movement": 986657Snate@binkert.org self["mover"] = "yes" 996657Snate@binkert.org 1006657Snate@binkert.org self.isMachineType = (ident == "MachineType") 1016657Snate@binkert.org 1026657Snate@binkert.org self.data_members = orderdict() 1036657Snate@binkert.org 1046657Snate@binkert.org # Methods 1056657Snate@binkert.org self.methods = {} 1066657Snate@binkert.org 1076657Snate@binkert.org # Enums 1086657Snate@binkert.org self.enums = orderdict() 1096657Snate@binkert.org 1106657Snate@binkert.org @property 1116657Snate@binkert.org def isPrimitive(self): 1126657Snate@binkert.org return "primitive" in self 1136657Snate@binkert.org @property 1146657Snate@binkert.org def isNetworkMessage(self): 1156657Snate@binkert.org return "networkmessage" in self 1166657Snate@binkert.org @property 1176657Snate@binkert.org def isMessage(self): 1186657Snate@binkert.org return "message" in self 1196657Snate@binkert.org @property 1206657Snate@binkert.org def isBuffer(self): 1216657Snate@binkert.org return "buffer" in self 1226657Snate@binkert.org @property 1236657Snate@binkert.org def isInPort(self): 1246657Snate@binkert.org return "inport" in self 1256657Snate@binkert.org @property 1266657Snate@binkert.org def isOutPort(self): 1276657Snate@binkert.org return "outport" in self 1286657Snate@binkert.org @property 1296657Snate@binkert.org def isEnumeration(self): 1306657Snate@binkert.org return "enumeration" in self 1316657Snate@binkert.org @property 1326657Snate@binkert.org def isExternal(self): 1336657Snate@binkert.org return "external" in self 1346657Snate@binkert.org @property 1356657Snate@binkert.org def isGlobal(self): 1366657Snate@binkert.org return "global" in self 1376657Snate@binkert.org @property 1386657Snate@binkert.org def isInterface(self): 1396657Snate@binkert.org return "interface" in self 1406657Snate@binkert.org 1416657Snate@binkert.org # Return false on error 1426657Snate@binkert.org def dataMemberAdd(self, ident, type, pairs, init_code): 1436657Snate@binkert.org if ident in self.data_members: 1446657Snate@binkert.org return False 1456657Snate@binkert.org 1466657Snate@binkert.org member = DataMember(ident, type, pairs, init_code) 1476657Snate@binkert.org self.data_members[ident] = member 1486657Snate@binkert.org 1496657Snate@binkert.org return True 1506657Snate@binkert.org 1516657Snate@binkert.org def dataMemberType(self, ident): 1526657Snate@binkert.org return self.data_members[ident].type 1536657Snate@binkert.org 1546657Snate@binkert.org def methodId(self, name, param_type_vec): 1556657Snate@binkert.org return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 1566657Snate@binkert.org 1576657Snate@binkert.org def methodAdd(self, name, return_type, param_type_vec): 1586657Snate@binkert.org ident = self.methodId(name, param_type_vec) 1596657Snate@binkert.org if ident in self.methods: 1606657Snate@binkert.org return False 1616657Snate@binkert.org 1626657Snate@binkert.org self.methods[ident] = Method(return_type, param_type_vec) 1636657Snate@binkert.org return True 1646657Snate@binkert.org 1656657Snate@binkert.org def enumAdd(self, ident, pairs): 1666657Snate@binkert.org if ident in self.enums: 1676657Snate@binkert.org return False 1686657Snate@binkert.org 1696657Snate@binkert.org self.enums[ident] = Enumeration(ident, pairs) 1706657Snate@binkert.org 1716657Snate@binkert.org # Add default 1726657Snate@binkert.org if "default" not in self: 1736657Snate@binkert.org self["default"] = "%s_NUM" % self.c_ident 1746657Snate@binkert.org 1756657Snate@binkert.org return True 1766657Snate@binkert.org 1776657Snate@binkert.org def writeCodeFiles(self, path): 1786657Snate@binkert.org if self.isExternal: 1796657Snate@binkert.org # Do nothing 1806657Snate@binkert.org pass 1816657Snate@binkert.org elif self.isEnumeration: 1826657Snate@binkert.org self.printEnumHH(path) 1836657Snate@binkert.org self.printEnumCC(path) 1846657Snate@binkert.org else: 1856657Snate@binkert.org # User defined structs and messages 1866657Snate@binkert.org self.printTypeHH(path) 1876657Snate@binkert.org self.printTypeCC(path) 1886657Snate@binkert.org 1896657Snate@binkert.org def printTypeHH(self, path): 1906657Snate@binkert.org code = code_formatter() 1916657Snate@binkert.org code(''' 1926657Snate@binkert.org/** \\file ${{self.c_ident}}.hh 1936657Snate@binkert.org * 1946657Snate@binkert.org * 1956657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 1966657Snate@binkert.org */ 1976657Snate@binkert.org 1986657Snate@binkert.org#ifndef ${{self.c_ident}}_H 1996657Snate@binkert.org#define ${{self.c_ident}}_H 2006657Snate@binkert.org 2016657Snate@binkert.org#include "mem/ruby/common/Global.hh" 2026657Snate@binkert.org#include "mem/gems_common/Allocator.hh" 2036657Snate@binkert.org''') 2046657Snate@binkert.org 2056657Snate@binkert.org for dm in self.data_members.values(): 2066657Snate@binkert.org if not dm.type.isPrimitive: 2076657Snate@binkert.org code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 2086657Snate@binkert.org 2096657Snate@binkert.org parent = "" 2106657Snate@binkert.org if "interface" in self: 2116657Snate@binkert.org code('#include "mem/protocol/$0.hh"', self["interface"]) 2126657Snate@binkert.org parent = " : public %s" % self["interface"] 2136657Snate@binkert.org 2146657Snate@binkert.org code(''' 2156657Snate@binkert.org$klass ${{self.c_ident}}$parent { 2166657Snate@binkert.org public: 2176657Snate@binkert.org ${{self.c_ident}}() 2186657Snate@binkert.org''', klass="class") 2196657Snate@binkert.org 2206657Snate@binkert.org # Call superclass constructor 2216657Snate@binkert.org if "interface" in self: 2226657Snate@binkert.org code(' : ${{self["interface"]}}()') 2236657Snate@binkert.org 2246657Snate@binkert.org code.indent() 2256657Snate@binkert.org code("{") 2266657Snate@binkert.org if not self.isGlobal: 2276657Snate@binkert.org code.indent() 2286657Snate@binkert.org for dm in self.data_members.values(): 2296657Snate@binkert.org ident = dm.ident 2306657Snate@binkert.org if "default" in dm: 2316657Snate@binkert.org # look for default value 2326657Snate@binkert.org code('m_$ident = ${{dm["default"]}}; // default for this field') 2336657Snate@binkert.org elif "default" in dm.type: 2346657Snate@binkert.org # Look for the type default 2356657Snate@binkert.org tid = dm.type.c_ident 2366657Snate@binkert.org code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 2376657Snate@binkert.org else: 2386657Snate@binkert.org code('// m_$ident has no default') 2396657Snate@binkert.org code.dedent() 2406657Snate@binkert.org code('}') 2416657Snate@binkert.org 2426657Snate@binkert.org # ******** Default destructor ******** 2436657Snate@binkert.org code('~${{self.c_ident}}() { };') 2446657Snate@binkert.org 2456657Snate@binkert.org # ******** Full init constructor ******** 2466657Snate@binkert.org if not self.isGlobal: 2476657Snate@binkert.org params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 2486657Snate@binkert.org for dm in self.data_members.itervalues() ] 2496657Snate@binkert.org 2506657Snate@binkert.org if self.isMessage: 2516657Snate@binkert.org params.append('const unsigned local_proc_id') 2526657Snate@binkert.org 2536657Snate@binkert.org params = ', '.join(params) 2546657Snate@binkert.org code('${{self.c_ident}}($params)') 2556657Snate@binkert.org 2566657Snate@binkert.org # Call superclass constructor 2576657Snate@binkert.org if "interface" in self: 2586657Snate@binkert.org code(' : ${{self["interface"]}}()') 2596657Snate@binkert.org 2606657Snate@binkert.org code('{') 2616657Snate@binkert.org code.indent() 2626657Snate@binkert.org for dm in self.data_members.values(): 2636657Snate@binkert.org code('m_${{dm.ident}} = local_${{dm.ident}};') 2646657Snate@binkert.org if "nextLineCallHack" in dm: 2656657Snate@binkert.org code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};') 2666657Snate@binkert.org 2676657Snate@binkert.org if self.isMessage: 2686657Snate@binkert.org code('proc_id = local_proc_id;') 2696657Snate@binkert.org 2706657Snate@binkert.org code.dedent() 2716657Snate@binkert.org code('}') 2726657Snate@binkert.org 2736657Snate@binkert.org # create a static factory method 2746657Snate@binkert.org if "interface" in self: 2756657Snate@binkert.org code(''' 2766657Snate@binkert.orgstatic ${{self["interface"]}}* create() { 2776657Snate@binkert.org return new ${{self.c_ident}}(); 2786657Snate@binkert.org} 2796657Snate@binkert.org''') 2806657Snate@binkert.org 2816657Snate@binkert.org # ******** Message member functions ******** 2826657Snate@binkert.org # FIXME: those should be moved into slicc file, slicc should 2836657Snate@binkert.org # support more of the c++ class inheritance 2846657Snate@binkert.org 2856657Snate@binkert.org if self.isMessage: 2866657Snate@binkert.org code(''' 2876657Snate@binkert.orgMessage* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); } 2886657Snate@binkert.orgvoid destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); } 2896657Snate@binkert.orgstatic Allocator<${{self.c_ident}}>* s_allocator_ptr; 2906657Snate@binkert.orgstatic void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }} 2916657Snate@binkert.org''') 2926657Snate@binkert.org 2936657Snate@binkert.org if not self.isGlobal: 2946657Snate@binkert.org # const Get methods for each field 2956657Snate@binkert.org code('// Const accessors methods for each field') 2966657Snate@binkert.org for dm in self.data_members.values(): 2976657Snate@binkert.org code(''' 2986657Snate@binkert.org/** \\brief Const accessor method for ${{dm.ident}} field. 2996657Snate@binkert.org * \\return ${{dm.ident}} field 3006657Snate@binkert.org */ 3016657Snate@binkert.orgconst ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; } 3026657Snate@binkert.org''') 3036657Snate@binkert.org 3046657Snate@binkert.org # Non-const Get methods for each field 3056657Snate@binkert.org code('// Non const Accessors methods for each field') 3066657Snate@binkert.org for dm in self.data_members.values(): 3076657Snate@binkert.org code(''' 3086657Snate@binkert.org/** \\brief Non-const accessor method for ${{dm.ident}} field. 3096657Snate@binkert.org * \\return ${{dm.ident}} field 3106657Snate@binkert.org */ 3116657Snate@binkert.org${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; } 3126657Snate@binkert.org''') 3136657Snate@binkert.org 3146657Snate@binkert.org #Set methods for each field 3156657Snate@binkert.org code('// Mutator methods for each field') 3166657Snate@binkert.org for dm in self.data_members.values(): 3176657Snate@binkert.org code(''' 3186657Snate@binkert.org/** \\brief Mutator method for ${{dm.ident}} field */ 3196657Snate@binkert.orgvoid set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; } 3206657Snate@binkert.org''') 3216657Snate@binkert.org 3226657Snate@binkert.org code('void print(ostream& out) const;') 3236657Snate@binkert.org code.dedent() 3246657Snate@binkert.org code(' //private:') 3256657Snate@binkert.org code.indent() 3266657Snate@binkert.org 3276657Snate@binkert.org # Data members for each field 3286657Snate@binkert.org for dm in self.data_members.values(): 3296657Snate@binkert.org if "abstract" not in dm: 3306657Snate@binkert.org const = "" 3316657Snate@binkert.org init = "" 3326657Snate@binkert.org 3336657Snate@binkert.org # global structure 3346657Snate@binkert.org if self.isGlobal: 3356657Snate@binkert.org const = "static const " 3366657Snate@binkert.org 3376657Snate@binkert.org # init value 3386657Snate@binkert.org if dm.init_code: 3396657Snate@binkert.org # only global structure can have init value here 3406657Snate@binkert.org assert self.isGlobal 3416657Snate@binkert.org init = " = %s" % (dm.init_code) 3426657Snate@binkert.org 3436657Snate@binkert.org desc = "" 3446657Snate@binkert.org if "desc" in dm: 3456657Snate@binkert.org desc = '/**< %s */' % dm["desc"] 3466657Snate@binkert.org 3476657Snate@binkert.org code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc') 3486657Snate@binkert.org 3496657Snate@binkert.org if self.isMessage: 3506657Snate@binkert.org code('unsigned proc_id;') 3516657Snate@binkert.org 3526657Snate@binkert.org code.dedent() 3536657Snate@binkert.org code('};') 3546657Snate@binkert.org 3556657Snate@binkert.org code(''' 3566657Snate@binkert.org// Output operator declaration 3576657Snate@binkert.orgostream& operator<<(ostream& out, const ${{self.c_ident}}& obj); 3586657Snate@binkert.org 3596657Snate@binkert.org// Output operator definition 3606657Snate@binkert.orgextern inline 3616657Snate@binkert.orgostream& operator<<(ostream& out, const ${{self.c_ident}}& obj) 3626657Snate@binkert.org{ 3636657Snate@binkert.org obj.print(out); 3646657Snate@binkert.org out << flush; 3656657Snate@binkert.org return out; 3666657Snate@binkert.org} 3676657Snate@binkert.org 3686657Snate@binkert.org#endif // ${{self.c_ident}}_H 3696657Snate@binkert.org''') 3706657Snate@binkert.org 3716657Snate@binkert.org code.write(path, "%s.hh" % self.c_ident) 3726657Snate@binkert.org 3736657Snate@binkert.org def printTypeCC(self, path): 3746657Snate@binkert.org code = code_formatter() 3756657Snate@binkert.org 3766657Snate@binkert.org code(''' 3776657Snate@binkert.org/** \\file ${{self.c_ident}}.cc 3786657Snate@binkert.org * 3796657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 3806657Snate@binkert.org */ 3816657Snate@binkert.org 3826657Snate@binkert.org#include "mem/protocol/${{self.c_ident}}.hh" 3836657Snate@binkert.org''') 3846657Snate@binkert.org 3856657Snate@binkert.org if self.isMessage: 3866657Snate@binkert.org code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;') 3876657Snate@binkert.org code(''' 3886657Snate@binkert.org/** \\brief Print the state of this object */ 3896657Snate@binkert.orgvoid ${{self.c_ident}}::print(ostream& out) const 3906657Snate@binkert.org{ 3916657Snate@binkert.org out << "[${{self.c_ident}}: "; 3926657Snate@binkert.org''') 3936657Snate@binkert.org 3946657Snate@binkert.org # For each field 3956657Snate@binkert.org code.indent() 3966657Snate@binkert.org for dm in self.data_members.values(): 3976657Snate@binkert.org code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 3986657Snate@binkert.org 3996657Snate@binkert.org if self.isMessage: 4006657Snate@binkert.org code('out << "Time = " << getTime() << " ";') 4016657Snate@binkert.org code.dedent() 4026657Snate@binkert.org 4036657Snate@binkert.org # Trailer 4046657Snate@binkert.org code(''' 4056657Snate@binkert.org out << "]"; 4066657Snate@binkert.org}''') 4076657Snate@binkert.org 4086657Snate@binkert.org code.write(path, "%s.cc" % self.c_ident) 4096657Snate@binkert.org 4106657Snate@binkert.org def printEnumHH(self, path): 4116657Snate@binkert.org code = code_formatter() 4126657Snate@binkert.org code(''' 4136657Snate@binkert.org/** \\file ${{self.c_ident}}.hh 4146657Snate@binkert.org * 4156657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 4166657Snate@binkert.org */ 4176657Snate@binkert.org#ifndef ${{self.c_ident}}_H 4186657Snate@binkert.org#define ${{self.c_ident}}_H 4196657Snate@binkert.org 4206657Snate@binkert.org#include "mem/ruby/common/Global.hh" 4216657Snate@binkert.org 4226657Snate@binkert.org/** \\enum ${{self.c_ident}} 4236657Snate@binkert.org * \\brief ${{self.desc}} 4246657Snate@binkert.org */ 4256657Snate@binkert.orgenum ${{self.c_ident}} { 4266657Snate@binkert.org ${{self.c_ident}}_FIRST, 4276657Snate@binkert.org''') 4286657Snate@binkert.org 4296657Snate@binkert.org code.indent() 4306657Snate@binkert.org # For each field 4316657Snate@binkert.org for i,(ident,enum) in enumerate(self.enums.iteritems()): 4326657Snate@binkert.org desc = enum.get("desc", "No description avaliable") 4336657Snate@binkert.org init = ' = %s_FIRST' % self.c_ident if i == 0 else '' 4346657Snate@binkert.org 4356657Snate@binkert.org code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 4366657Snate@binkert.org code.dedent() 4376657Snate@binkert.org code(''' 4386657Snate@binkert.org ${{self.c_ident}}_NUM 4396657Snate@binkert.org}; 4406657Snate@binkert.org${{self.c_ident}} string_to_${{self.c_ident}}(const string& str); 4416657Snate@binkert.orgstring ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 4426657Snate@binkert.org${{self.c_ident}} &operator++(${{self.c_ident}} &e); 4436657Snate@binkert.org''') 4446657Snate@binkert.org 4456657Snate@binkert.org # MachineType hack used to set the base component id for each Machine 4466657Snate@binkert.org if self.isMachineType: 4476657Snate@binkert.org code(''' 4486657Snate@binkert.orgint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 4496657Snate@binkert.orgMachineType ${{self.c_ident}}_from_base_level(int); 4506657Snate@binkert.orgint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 4516657Snate@binkert.orgint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 4526657Snate@binkert.org''') 4536657Snate@binkert.org 4546657Snate@binkert.org for enum in self.enums.itervalues(): 4556657Snate@binkert.org code('#define MACHINETYPE_${{enum.ident}} 1') 4566657Snate@binkert.org 4576657Snate@binkert.org # Trailer 4586657Snate@binkert.org code(''' 4596657Snate@binkert.orgostream& operator<<(ostream& out, const ${{self.c_ident}}& obj); 4606657Snate@binkert.org 4616657Snate@binkert.org#endif // ${{self.c_ident}}_H 4626657Snate@binkert.org''') 4636657Snate@binkert.org 4646657Snate@binkert.org code.write(path, "%s.hh" % self.c_ident) 4656657Snate@binkert.org 4666657Snate@binkert.org def printEnumCC(self, path): 4676657Snate@binkert.org code = code_formatter() 4686657Snate@binkert.org code(''' 4696657Snate@binkert.org/** \\file ${{self.c_ident}}.hh 4706657Snate@binkert.org * 4716657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 4726657Snate@binkert.org */ 4736657Snate@binkert.org 4746657Snate@binkert.org#include "mem/protocol/${{self.c_ident}}.hh" 4756657Snate@binkert.org 4766657Snate@binkert.org''') 4776657Snate@binkert.org 4786657Snate@binkert.org if self.isMachineType: 4796657Snate@binkert.org code('#include "mem/protocol/ControllerFactory.hh"') 4806657Snate@binkert.org for enum in self.enums.itervalues(): 4816657Snate@binkert.org code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 4826657Snate@binkert.org 4836657Snate@binkert.org code(''' 4846657Snate@binkert.orgostream& operator<<(ostream& out, const ${{self.c_ident}}& obj) 4856657Snate@binkert.org{ 4866657Snate@binkert.org out << ${{self.c_ident}}_to_string(obj); 4876657Snate@binkert.org out << flush; 4886657Snate@binkert.org return out; 4896657Snate@binkert.org} 4906657Snate@binkert.org 4916657Snate@binkert.orgstring ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 4926657Snate@binkert.org{ 4936657Snate@binkert.org switch(obj) { 4946657Snate@binkert.org''') 4956657Snate@binkert.org 4966657Snate@binkert.org # For each field 4976657Snate@binkert.org code.indent() 4986657Snate@binkert.org for enum in self.enums.itervalues(): 4996657Snate@binkert.org code(' case ${{self.c_ident}}_${{enum.ident}}:') 5006657Snate@binkert.org code(' return "${{enum.ident}}";') 5016657Snate@binkert.org code.dedent() 5026657Snate@binkert.org 5036657Snate@binkert.org # Trailer 5046657Snate@binkert.org code(''' 5056657Snate@binkert.org default: 5066657Snate@binkert.org ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 5076657Snate@binkert.org return ""; 5086657Snate@binkert.org } 5096657Snate@binkert.org} 5106657Snate@binkert.org 5116657Snate@binkert.org${{self.c_ident}} string_to_${{self.c_ident}}(const string& str) 5126657Snate@binkert.org{ 5136657Snate@binkert.org''') 5146657Snate@binkert.org 5156657Snate@binkert.org # For each field 5166657Snate@binkert.org code.indent() 5176657Snate@binkert.org code("if (false) {") 5186657Snate@binkert.org start = "} else " 5196657Snate@binkert.org for enum in self.enums.itervalues(): 5206657Snate@binkert.org code('${start}if (str == "${{enum.ident}}") {') 5216657Snate@binkert.org code(' return ${{self.c_ident}}_${{enum.ident}};') 5226657Snate@binkert.org code.dedent() 5236657Snate@binkert.org 5246657Snate@binkert.org code(''' 5256657Snate@binkert.org } else { 5266657Snate@binkert.org WARN_EXPR(str); 5276657Snate@binkert.org ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}"); 5286657Snate@binkert.org } 5296657Snate@binkert.org} 5306657Snate@binkert.org 5316657Snate@binkert.org${{self.c_ident}}& operator++(${{self.c_ident}}& e) { 5326657Snate@binkert.org assert(e < ${{self.c_ident}}_NUM); 5336657Snate@binkert.org return e = ${{self.c_ident}}(e+1); 5346657Snate@binkert.org} 5356657Snate@binkert.org''') 5366657Snate@binkert.org 5376657Snate@binkert.org # MachineType hack used to set the base level and number of 5386657Snate@binkert.org # components for each Machine 5396657Snate@binkert.org if self.isMachineType: 5406657Snate@binkert.org code(''' 5416657Snate@binkert.org/** \\brief returns the base vector index for each machine type to be used by NetDest 5426657Snate@binkert.org * 5436657Snate@binkert.org * \\return the base vector index for each machine type to be used by NetDest 5446657Snate@binkert.org * \\see NetDest.hh 5456657Snate@binkert.org */ 5466657Snate@binkert.orgint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 5476657Snate@binkert.org{ 5486657Snate@binkert.org switch(obj) { 5496657Snate@binkert.org''') 5506657Snate@binkert.org 5516657Snate@binkert.org # For each field 5526657Snate@binkert.org code.indent() 5536657Snate@binkert.org for i,enum in enumerate(self.enums.itervalues()): 5546657Snate@binkert.org code(' case ${{self.c_ident}}_${{enum.ident}}:') 5556657Snate@binkert.org code(' return $i;') 5566657Snate@binkert.org code.dedent() 5576657Snate@binkert.org 5586657Snate@binkert.org # total num 5596657Snate@binkert.org code(''' 5606657Snate@binkert.org case ${{self.c_ident}}_NUM: 5616657Snate@binkert.org return ${{len(self.enums)}}; 5626657Snate@binkert.org 5636657Snate@binkert.org default: 5646657Snate@binkert.org ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 5656657Snate@binkert.org return -1; 5666657Snate@binkert.org } 5676657Snate@binkert.org} 5686657Snate@binkert.org 5696657Snate@binkert.org/** \\brief returns the machine type for each base vector index used by NetDest 5706657Snate@binkert.org * 5716657Snate@binkert.org * \\return the MachineTYpe 5726657Snate@binkert.org */ 5736657Snate@binkert.orgMachineType ${{self.c_ident}}_from_base_level(int type) 5746657Snate@binkert.org{ 5756657Snate@binkert.org switch(type) { 5766657Snate@binkert.org''') 5776657Snate@binkert.org 5786657Snate@binkert.org # For each field 5796657Snate@binkert.org code.indent() 5806657Snate@binkert.org for i,enum in enumerate(self.enums.itervalues()): 5816657Snate@binkert.org code(' case $i:') 5826657Snate@binkert.org code(' return ${{self.c_ident}}_${{enum.ident}};') 5836657Snate@binkert.org code.dedent() 5846657Snate@binkert.org 5856657Snate@binkert.org # Trailer 5866657Snate@binkert.org code(''' 5876657Snate@binkert.org default: 5886657Snate@binkert.org ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 5896657Snate@binkert.org return MachineType_NUM; 5906657Snate@binkert.org } 5916657Snate@binkert.org} 5926657Snate@binkert.org 5936657Snate@binkert.org/** \\brief The return value indicates the number of components created 5946657Snate@binkert.org * before a particular machine\'s components 5956657Snate@binkert.org * 5966657Snate@binkert.org * \\return the base number of components for each machine 5976657Snate@binkert.org */ 5986657Snate@binkert.orgint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 5996657Snate@binkert.org{ 6006657Snate@binkert.org int base = 0; 6016657Snate@binkert.org switch(obj) { 6026657Snate@binkert.org''') 6036657Snate@binkert.org 6046657Snate@binkert.org # For each field 6056657Snate@binkert.org code.indent() 6066657Snate@binkert.org code(' case ${{self.c_ident}}_NUM:') 6076657Snate@binkert.org for enum in reversed(self.enums.values()): 6086657Snate@binkert.org code(' base += ${{enum.ident}}_Controller::getNumControllers();') 6096657Snate@binkert.org code(' case ${{self.c_ident}}_${{enum.ident}}:') 6106657Snate@binkert.org code(' break;') 6116657Snate@binkert.org code.dedent() 6126657Snate@binkert.org 6136657Snate@binkert.org code(''' 6146657Snate@binkert.org default: 6156657Snate@binkert.org ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 6166657Snate@binkert.org return -1; 6176657Snate@binkert.org } 6186657Snate@binkert.org 6196657Snate@binkert.org return base; 6206657Snate@binkert.org} 6216657Snate@binkert.org 6226657Snate@binkert.org/** \\brief returns the total number of components for each machine 6236657Snate@binkert.org * \\return the total number of components for each machine 6246657Snate@binkert.org */ 6256657Snate@binkert.orgint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 6266657Snate@binkert.org{ 6276657Snate@binkert.org switch(obj) { 6286657Snate@binkert.org''') 6296657Snate@binkert.org 6306657Snate@binkert.org # For each field 6316657Snate@binkert.org for enum in self.enums.itervalues(): 6326657Snate@binkert.org code(''' 6336657Snate@binkert.org case ${{self.c_ident}}_${{enum.ident}}: 6346657Snate@binkert.org return ${{enum.ident}}_Controller::getNumControllers(); 6356657Snate@binkert.org''') 6366657Snate@binkert.org 6376657Snate@binkert.org # total num 6386657Snate@binkert.org code(''' 6396657Snate@binkert.org case ${{self.c_ident}}_NUM: 6406657Snate@binkert.org default: 6416657Snate@binkert.org ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 6426657Snate@binkert.org return -1; 6436657Snate@binkert.org } 6446657Snate@binkert.org} 6456657Snate@binkert.org''') 6466657Snate@binkert.org 6476657Snate@binkert.org # Write the file 6486657Snate@binkert.org code.write(path, "%s.cc" % self.c_ident) 6496657Snate@binkert.org 6506657Snate@binkert.org__all__ = [ "Type" ] 651