Type.py revision 12065
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 286999Snate@binkert.orgfrom m5.util import orderdict 296657Snate@binkert.org 306657Snate@binkert.orgfrom slicc.util import PairContainer 316657Snate@binkert.orgfrom slicc.symbols.Symbol import Symbol 329302Snilay@cs.wisc.edufrom slicc.symbols.Var import Var 336657Snate@binkert.org 3411117Snilay@cs.wisc.educlass DataMember(Var): 3511117Snilay@cs.wisc.edu def __init__(self, symtab, ident, location, type, code, pairs, 3611117Snilay@cs.wisc.edu machine, init_code): 3711117Snilay@cs.wisc.edu super(DataMember, self).__init__(symtab, ident, location, type, 3811117Snilay@cs.wisc.edu code, pairs, machine) 396657Snate@binkert.org self.init_code = init_code 406657Snate@binkert.org 416657Snate@binkert.orgclass Enumeration(PairContainer): 426657Snate@binkert.org def __init__(self, ident, pairs): 436657Snate@binkert.org super(Enumeration, self).__init__(pairs) 446657Snate@binkert.org self.ident = ident 4511283Santhony.gutierrez@amd.com self.primary = False 466657Snate@binkert.org 476657Snate@binkert.orgclass Type(Symbol): 486657Snate@binkert.org def __init__(self, table, ident, location, pairs, machine=None): 496657Snate@binkert.org super(Type, self).__init__(table, ident, location, pairs) 506657Snate@binkert.org self.c_ident = ident 516882SBrad.Beckmann@amd.com self.abstract_ident = "" 526657Snate@binkert.org if machine: 536657Snate@binkert.org if self.isExternal or self.isPrimitive: 546657Snate@binkert.org if "external_name" in self: 556657Snate@binkert.org self.c_ident = self["external_name"] 566657Snate@binkert.org else: 576657Snate@binkert.org # Append with machine name 586657Snate@binkert.org self.c_ident = "%s_%s" % (machine, ident) 596657Snate@binkert.org 606657Snate@binkert.org self.pairs.setdefault("desc", "No description avaliable") 616657Snate@binkert.org 626657Snate@binkert.org # check for interface that this Type implements 636657Snate@binkert.org if "interface" in self: 646657Snate@binkert.org interface = self["interface"] 6510895Snilay@cs.wisc.edu if interface in ("Message"): 666657Snate@binkert.org self["message"] = "yes" 676657Snate@binkert.org 686657Snate@binkert.org # FIXME - all of the following id comparisons are fragile hacks 6910228Snilay@cs.wisc.edu if self.ident in ("CacheMemory"): 706657Snate@binkert.org self["cache"] = "yes" 716657Snate@binkert.org 7210228Snilay@cs.wisc.edu if self.ident in ("TBETable"): 736657Snate@binkert.org self["tbe"] = "yes" 746657Snate@binkert.org 756657Snate@binkert.org if self.ident == "TimerTable": 766657Snate@binkert.org self["timer"] = "yes" 776657Snate@binkert.org 786657Snate@binkert.org if self.ident == "DirectoryMemory": 796657Snate@binkert.org self["dir"] = "yes" 806657Snate@binkert.org 816657Snate@binkert.org if self.ident == "PersistentTable": 826657Snate@binkert.org self["persistent"] = "yes" 836657Snate@binkert.org 846657Snate@binkert.org if self.ident == "Prefetcher": 856657Snate@binkert.org self["prefetcher"] = "yes" 866657Snate@binkert.org 876657Snate@binkert.org self.isMachineType = (ident == "MachineType") 886657Snate@binkert.org 898086SBrad.Beckmann@amd.com self.isStateDecl = ("state_decl" in self) 908086SBrad.Beckmann@amd.com self.statePermPairs = [] 918086SBrad.Beckmann@amd.com 926657Snate@binkert.org self.data_members = orderdict() 936657Snate@binkert.org self.methods = {} 946657Snate@binkert.org self.enums = orderdict() 956657Snate@binkert.org 966657Snate@binkert.org @property 976657Snate@binkert.org def isPrimitive(self): 986657Snate@binkert.org return "primitive" in self 9910895Snilay@cs.wisc.edu 1006657Snate@binkert.org @property 1016657Snate@binkert.org def isMessage(self): 1026657Snate@binkert.org return "message" in self 1036657Snate@binkert.org @property 1046657Snate@binkert.org def isBuffer(self): 1056657Snate@binkert.org return "buffer" in self 1066657Snate@binkert.org @property 1076657Snate@binkert.org def isInPort(self): 1086657Snate@binkert.org return "inport" in self 1096657Snate@binkert.org @property 1106657Snate@binkert.org def isOutPort(self): 1116657Snate@binkert.org return "outport" in self 1126657Snate@binkert.org @property 1136657Snate@binkert.org def isEnumeration(self): 1146657Snate@binkert.org return "enumeration" in self 1156657Snate@binkert.org @property 1166657Snate@binkert.org def isExternal(self): 1176657Snate@binkert.org return "external" in self 1186657Snate@binkert.org @property 1196657Snate@binkert.org def isGlobal(self): 1206657Snate@binkert.org return "global" in self 1216657Snate@binkert.org @property 1226657Snate@binkert.org def isInterface(self): 1236657Snate@binkert.org return "interface" in self 1246657Snate@binkert.org 1256657Snate@binkert.org # Return false on error 1269298Snilay@cs.wisc.edu def addDataMember(self, ident, type, pairs, init_code): 1276657Snate@binkert.org if ident in self.data_members: 1286657Snate@binkert.org return False 1296657Snate@binkert.org 13011117Snilay@cs.wisc.edu member = DataMember(self.symtab, ident, self.location, type, 13111117Snilay@cs.wisc.edu "m_%s" % ident, pairs, None, init_code) 13211117Snilay@cs.wisc.edu 1336657Snate@binkert.org self.data_members[ident] = member 13411117Snilay@cs.wisc.edu self.symtab.registerSym(ident, member) 1356657Snate@binkert.org return True 1366657Snate@binkert.org 1376657Snate@binkert.org def dataMemberType(self, ident): 1386657Snate@binkert.org return self.data_members[ident].type 1396657Snate@binkert.org 1406657Snate@binkert.org def methodId(self, name, param_type_vec): 1416657Snate@binkert.org return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 1426657Snate@binkert.org 1436882SBrad.Beckmann@amd.com def methodIdAbstract(self, name, param_type_vec): 1446882SBrad.Beckmann@amd.com return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 1456882SBrad.Beckmann@amd.com 1468086SBrad.Beckmann@amd.com def statePermPairAdd(self, state_name, perm_name): 1478086SBrad.Beckmann@amd.com self.statePermPairs.append([state_name, perm_name]) 1488086SBrad.Beckmann@amd.com 14910307Snilay@cs.wisc.edu def addFunc(self, func): 15010307Snilay@cs.wisc.edu ident = self.methodId(func.ident, func.param_types) 1516657Snate@binkert.org if ident in self.methods: 1526657Snate@binkert.org return False 1536657Snate@binkert.org 15410307Snilay@cs.wisc.edu self.methods[ident] = func 1559298Snilay@cs.wisc.edu return True 1569298Snilay@cs.wisc.edu 1579298Snilay@cs.wisc.edu def addEnum(self, ident, pairs): 1586657Snate@binkert.org if ident in self.enums: 1596657Snate@binkert.org return False 1606657Snate@binkert.org 1616657Snate@binkert.org self.enums[ident] = Enumeration(ident, pairs) 1626657Snate@binkert.org 1636657Snate@binkert.org # Add default 1646657Snate@binkert.org if "default" not in self: 1656657Snate@binkert.org self["default"] = "%s_NUM" % self.c_ident 1666657Snate@binkert.org 1676657Snate@binkert.org return True 1686657Snate@binkert.org 16911283Santhony.gutierrez@amd.com ## Used to check if an enum has been already used and therefore 17011283Santhony.gutierrez@amd.com ## should not be used again. 17111283Santhony.gutierrez@amd.com def checkEnum(self, ident): 17211283Santhony.gutierrez@amd.com if ident in self.enums and not self.enums[ident].primary: 17311283Santhony.gutierrez@amd.com self.enums[ident].primary = True 17411283Santhony.gutierrez@amd.com return True 17511283Santhony.gutierrez@amd.com return False 17611283Santhony.gutierrez@amd.com 1779219Spower.jg@gmail.com def writeCodeFiles(self, path, includes): 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): 1906999Snate@binkert.org code = self.symtab.codeFormatter() 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 1987007Snate@binkert.org#ifndef __${{self.c_ident}}_HH__ 1997007Snate@binkert.org#define __${{self.c_ident}}_HH__ 2006657Snate@binkert.org 2017002Snate@binkert.org#include <iostream> 2027002Snate@binkert.org 2039466Snilay@cs.wisc.edu#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 2046657Snate@binkert.org''') 2056657Snate@binkert.org 2066657Snate@binkert.org for dm in self.data_members.values(): 2076657Snate@binkert.org if not dm.type.isPrimitive: 2086657Snate@binkert.org code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 2096657Snate@binkert.org 2106657Snate@binkert.org parent = "" 2116657Snate@binkert.org if "interface" in self: 2126657Snate@binkert.org code('#include "mem/protocol/$0.hh"', self["interface"]) 2136657Snate@binkert.org parent = " : public %s" % self["interface"] 2146657Snate@binkert.org 2156657Snate@binkert.org code(''' 2167007Snate@binkert.org$klass ${{self.c_ident}}$parent 2177007Snate@binkert.org{ 2186657Snate@binkert.org public: 2199466Snilay@cs.wisc.edu ${{self.c_ident}} 2206657Snate@binkert.org''', klass="class") 2216657Snate@binkert.org 2229466Snilay@cs.wisc.edu if self.isMessage: 2239508Snilay@cs.wisc.edu code('(Tick curTime) : %s(curTime) {' % self["interface"]) 2249466Snilay@cs.wisc.edu else: 2259466Snilay@cs.wisc.edu code('()\n\t\t{') 2269466Snilay@cs.wisc.edu 2276657Snate@binkert.org code.indent() 2286657Snate@binkert.org if not self.isGlobal: 2296657Snate@binkert.org code.indent() 2306657Snate@binkert.org for dm in self.data_members.values(): 2316657Snate@binkert.org ident = dm.ident 2326657Snate@binkert.org if "default" in dm: 2336657Snate@binkert.org # look for default value 2346657Snate@binkert.org code('m_$ident = ${{dm["default"]}}; // default for this field') 2356657Snate@binkert.org elif "default" in dm.type: 2366657Snate@binkert.org # Look for the type default 2376657Snate@binkert.org tid = dm.type.c_ident 2386657Snate@binkert.org code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 2396657Snate@binkert.org else: 2406657Snate@binkert.org code('// m_$ident has no default') 2416657Snate@binkert.org code.dedent() 2426657Snate@binkert.org code('}') 2436657Snate@binkert.org 2447453Snate@binkert.org # ******** Copy constructor ******** 2457453Snate@binkert.org if not self.isGlobal: 2467453Snate@binkert.org code('${{self.c_ident}}(const ${{self.c_ident}}&other)') 2477453Snate@binkert.org 2487453Snate@binkert.org # Call superclass constructor 2497453Snate@binkert.org if "interface" in self: 2507453Snate@binkert.org code(' : ${{self["interface"]}}(other)') 2517453Snate@binkert.org 2527453Snate@binkert.org code('{') 2537453Snate@binkert.org code.indent() 2547453Snate@binkert.org 2557453Snate@binkert.org for dm in self.data_members.values(): 2567453Snate@binkert.org code('m_${{dm.ident}} = other.m_${{dm.ident}};') 2577453Snate@binkert.org 2587453Snate@binkert.org code.dedent() 2597453Snate@binkert.org code('}') 2607453Snate@binkert.org 2616657Snate@binkert.org # ******** Full init constructor ******** 2626657Snate@binkert.org if not self.isGlobal: 2636657Snate@binkert.org params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 2646657Snate@binkert.org for dm in self.data_members.itervalues() ] 2659466Snilay@cs.wisc.edu params = ', '.join(params) 2666657Snate@binkert.org 2679466Snilay@cs.wisc.edu if self.isMessage: 2689508Snilay@cs.wisc.edu params = "const Tick curTime, " + params 2699466Snilay@cs.wisc.edu 2706657Snate@binkert.org code('${{self.c_ident}}($params)') 2716657Snate@binkert.org 2726657Snate@binkert.org # Call superclass constructor 2736657Snate@binkert.org if "interface" in self: 2749466Snilay@cs.wisc.edu if self.isMessage: 2759466Snilay@cs.wisc.edu code(' : ${{self["interface"]}}(curTime)') 2769466Snilay@cs.wisc.edu else: 2779466Snilay@cs.wisc.edu code(' : ${{self["interface"]}}()') 2786657Snate@binkert.org 2796657Snate@binkert.org code('{') 2806657Snate@binkert.org code.indent() 2816657Snate@binkert.org for dm in self.data_members.values(): 2826657Snate@binkert.org code('m_${{dm.ident}} = local_${{dm.ident}};') 2836657Snate@binkert.org 2846657Snate@binkert.org code.dedent() 2856657Snate@binkert.org code('}') 2866657Snate@binkert.org 2879466Snilay@cs.wisc.edu # create a clone member 28810472Sandreas.hansson@arm.com if self.isMessage: 28910472Sandreas.hansson@arm.com code(''' 29010472Sandreas.hansson@arm.comMsgPtr 29110472Sandreas.hansson@arm.comclone() const 29210472Sandreas.hansson@arm.com{ 29310472Sandreas.hansson@arm.com return std::shared_ptr<Message>(new ${{self.c_ident}}(*this)); 29410472Sandreas.hansson@arm.com} 29510472Sandreas.hansson@arm.com''') 29610472Sandreas.hansson@arm.com else: 29710472Sandreas.hansson@arm.com code(''' 2987453Snate@binkert.org${{self.c_ident}}* 2997007Snate@binkert.orgclone() const 3007007Snate@binkert.org{ 3017453Snate@binkert.org return new ${{self.c_ident}}(*this); 3027007Snate@binkert.org} 3036657Snate@binkert.org''') 3046657Snate@binkert.org 3056657Snate@binkert.org if not self.isGlobal: 3066657Snate@binkert.org # const Get methods for each field 3076657Snate@binkert.org code('// Const accessors methods for each field') 3086657Snate@binkert.org for dm in self.data_members.values(): 3096657Snate@binkert.org code(''' 3106657Snate@binkert.org/** \\brief Const accessor method for ${{dm.ident}} field. 3116657Snate@binkert.org * \\return ${{dm.ident}} field 3126657Snate@binkert.org */ 3137007Snate@binkert.orgconst ${{dm.type.c_ident}}& 3147007Snate@binkert.orgget${{dm.ident}}() const 3157007Snate@binkert.org{ 3167007Snate@binkert.org return m_${{dm.ident}}; 3177007Snate@binkert.org} 3186657Snate@binkert.org''') 3196657Snate@binkert.org 3206657Snate@binkert.org # Non-const Get methods for each field 3216657Snate@binkert.org code('// Non const Accessors methods for each field') 3226657Snate@binkert.org for dm in self.data_members.values(): 3236657Snate@binkert.org code(''' 3246657Snate@binkert.org/** \\brief Non-const accessor method for ${{dm.ident}} field. 3256657Snate@binkert.org * \\return ${{dm.ident}} field 3266657Snate@binkert.org */ 3277007Snate@binkert.org${{dm.type.c_ident}}& 3287007Snate@binkert.orgget${{dm.ident}}() 3297007Snate@binkert.org{ 3307007Snate@binkert.org return m_${{dm.ident}}; 3317007Snate@binkert.org} 3326657Snate@binkert.org''') 3336657Snate@binkert.org 3346657Snate@binkert.org #Set methods for each field 3356657Snate@binkert.org code('// Mutator methods for each field') 3366657Snate@binkert.org for dm in self.data_members.values(): 3376657Snate@binkert.org code(''' 3386657Snate@binkert.org/** \\brief Mutator method for ${{dm.ident}} field */ 3397007Snate@binkert.orgvoid 3407007Snate@binkert.orgset${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 3417007Snate@binkert.org{ 3427007Snate@binkert.org m_${{dm.ident}} = local_${{dm.ident}}; 3437007Snate@binkert.org} 3446657Snate@binkert.org''') 3456657Snate@binkert.org 3467002Snate@binkert.org code('void print(std::ostream& out) const;') 3476657Snate@binkert.org code.dedent() 3486657Snate@binkert.org code(' //private:') 3496657Snate@binkert.org code.indent() 3506657Snate@binkert.org 3516657Snate@binkert.org # Data members for each field 3526657Snate@binkert.org for dm in self.data_members.values(): 3536657Snate@binkert.org if "abstract" not in dm: 3546657Snate@binkert.org const = "" 3556657Snate@binkert.org init = "" 3566657Snate@binkert.org 3576657Snate@binkert.org # global structure 3586657Snate@binkert.org if self.isGlobal: 3596657Snate@binkert.org const = "static const " 3606657Snate@binkert.org 3616657Snate@binkert.org # init value 3626657Snate@binkert.org if dm.init_code: 3636657Snate@binkert.org # only global structure can have init value here 3646657Snate@binkert.org assert self.isGlobal 3656657Snate@binkert.org init = " = %s" % (dm.init_code) 3666657Snate@binkert.org 3676657Snate@binkert.org if "desc" in dm: 3687007Snate@binkert.org code('/** ${{dm["desc"]}} */') 3696657Snate@binkert.org 3707007Snate@binkert.org code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 3716657Snate@binkert.org 37210307Snilay@cs.wisc.edu # Prototypes for methods defined for the Type 37310307Snilay@cs.wisc.edu for item in self.methods: 37410307Snilay@cs.wisc.edu proto = self.methods[item].prototype 3759298Snilay@cs.wisc.edu if proto: 3769298Snilay@cs.wisc.edu code('$proto') 3779298Snilay@cs.wisc.edu 3786657Snate@binkert.org code.dedent() 3796657Snate@binkert.org code('};') 3806657Snate@binkert.org 3816657Snate@binkert.org code(''' 3827055Snate@binkert.orginline std::ostream& 3837007Snate@binkert.orgoperator<<(std::ostream& out, const ${{self.c_ident}}& obj) 3846657Snate@binkert.org{ 3856657Snate@binkert.org obj.print(out); 3867002Snate@binkert.org out << std::flush; 3876657Snate@binkert.org return out; 3886657Snate@binkert.org} 3896657Snate@binkert.org 3907007Snate@binkert.org#endif // __${{self.c_ident}}_HH__ 3916657Snate@binkert.org''') 3926657Snate@binkert.org 3936657Snate@binkert.org code.write(path, "%s.hh" % self.c_ident) 3946657Snate@binkert.org 3956657Snate@binkert.org def printTypeCC(self, path): 3966999Snate@binkert.org code = self.symtab.codeFormatter() 3976657Snate@binkert.org 3986657Snate@binkert.org code(''' 3996657Snate@binkert.org/** \\file ${{self.c_ident}}.cc 4006657Snate@binkert.org * 4016657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 4026657Snate@binkert.org */ 4036657Snate@binkert.org 4047002Snate@binkert.org#include <iostream> 40510472Sandreas.hansson@arm.com#include <memory> 4067002Snate@binkert.org 4076657Snate@binkert.org#include "mem/protocol/${{self.c_ident}}.hh" 40811108Sdavid.hashe@amd.com#include "mem/ruby/system/RubySystem.hh" 4097002Snate@binkert.org 4107002Snate@binkert.orgusing namespace std; 4116657Snate@binkert.org''') 4126657Snate@binkert.org 4136657Snate@binkert.org code(''' 4146657Snate@binkert.org/** \\brief Print the state of this object */ 4157007Snate@binkert.orgvoid 4167007Snate@binkert.org${{self.c_ident}}::print(ostream& out) const 4176657Snate@binkert.org{ 4186657Snate@binkert.org out << "[${{self.c_ident}}: "; 4196657Snate@binkert.org''') 4206657Snate@binkert.org 4216657Snate@binkert.org # For each field 4226657Snate@binkert.org code.indent() 4236657Snate@binkert.org for dm in self.data_members.values(): 42411118Snilay@cs.wisc.edu if dm.type.c_ident == "Addr": 42511118Snilay@cs.wisc.edu code(''' 42611118Snilay@cs.wisc.eduout << "${{dm.ident}} = " << printAddress(m_${{dm.ident}}) << " ";''') 42711118Snilay@cs.wisc.edu else: 42811118Snilay@cs.wisc.edu code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 4296657Snate@binkert.org 4306657Snate@binkert.org code.dedent() 4316657Snate@binkert.org 4326657Snate@binkert.org # Trailer 4336657Snate@binkert.org code(''' 4346657Snate@binkert.org out << "]"; 4356657Snate@binkert.org}''') 4366657Snate@binkert.org 43710307Snilay@cs.wisc.edu # print the code for the methods in the type 43810307Snilay@cs.wisc.edu for item in self.methods: 43910307Snilay@cs.wisc.edu code(self.methods[item].generateCode()) 4409298Snilay@cs.wisc.edu 4416657Snate@binkert.org code.write(path, "%s.cc" % self.c_ident) 4426657Snate@binkert.org 4436657Snate@binkert.org def printEnumHH(self, path): 4446999Snate@binkert.org code = self.symtab.codeFormatter() 4456657Snate@binkert.org code(''' 4466657Snate@binkert.org/** \\file ${{self.c_ident}}.hh 4476657Snate@binkert.org * 4486657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 4496657Snate@binkert.org */ 4507007Snate@binkert.org 4517007Snate@binkert.org#ifndef __${{self.c_ident}}_HH__ 4527007Snate@binkert.org#define __${{self.c_ident}}_HH__ 4536657Snate@binkert.org 4547002Snate@binkert.org#include <iostream> 4557002Snate@binkert.org#include <string> 4567002Snate@binkert.org 4578086SBrad.Beckmann@amd.com''') 4588086SBrad.Beckmann@amd.com if self.isStateDecl: 4598086SBrad.Beckmann@amd.com code('#include "mem/protocol/AccessPermission.hh"') 4608086SBrad.Beckmann@amd.com 4618602Snilay@cs.wisc.edu if self.isMachineType: 46212065Snikos.nikoleris@arm.com code('#include <functional>') 4638602Snilay@cs.wisc.edu code('#include "base/misc.hh"') 4648602Snilay@cs.wisc.edu code('#include "mem/ruby/common/Address.hh"') 46511025Snilay@cs.wisc.edu code('#include "mem/ruby/common/TypeDefines.hh"') 4668602Snilay@cs.wisc.edu code('struct MachineID;') 4678602Snilay@cs.wisc.edu 4688086SBrad.Beckmann@amd.com code(''' 4696657Snate@binkert.org 4707007Snate@binkert.org// Class definition 4716657Snate@binkert.org/** \\enum ${{self.c_ident}} 4726657Snate@binkert.org * \\brief ${{self.desc}} 4736657Snate@binkert.org */ 4746657Snate@binkert.orgenum ${{self.c_ident}} { 4756657Snate@binkert.org ${{self.c_ident}}_FIRST, 4766657Snate@binkert.org''') 4776657Snate@binkert.org 4786657Snate@binkert.org code.indent() 4796657Snate@binkert.org # For each field 4806657Snate@binkert.org for i,(ident,enum) in enumerate(self.enums.iteritems()): 4816657Snate@binkert.org desc = enum.get("desc", "No description avaliable") 48210917Sbrandon.potter@amd.com if i == 0: 48310917Sbrandon.potter@amd.com init = ' = %s_FIRST' % self.c_ident 4846862Sdrh5@cs.wisc.edu else: 4856862Sdrh5@cs.wisc.edu init = '' 4866657Snate@binkert.org code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 4876657Snate@binkert.org code.dedent() 4886657Snate@binkert.org code(''' 4896657Snate@binkert.org ${{self.c_ident}}_NUM 4906657Snate@binkert.org}; 4917007Snate@binkert.org 4927007Snate@binkert.org// Code to convert from a string to the enumeration 4937002Snate@binkert.org${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 4947007Snate@binkert.org 4957007Snate@binkert.org// Code to convert state to a string 4967002Snate@binkert.orgstd::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 4977007Snate@binkert.org 4987007Snate@binkert.org// Code to increment an enumeration type 4996657Snate@binkert.org${{self.c_ident}} &operator++(${{self.c_ident}} &e); 5006657Snate@binkert.org''') 5016657Snate@binkert.org 50212065Snikos.nikoleris@arm.com if self.isMachineType: 50312065Snikos.nikoleris@arm.com code(''' 50412065Snikos.nikoleris@arm.com 50512065Snikos.nikoleris@arm.com// define a hash function for the MachineType class 50612065Snikos.nikoleris@arm.comnamespace std { 50712065Snikos.nikoleris@arm.comtemplate<> 50812065Snikos.nikoleris@arm.comstruct hash<MachineType> { 50912065Snikos.nikoleris@arm.com std::size_t operator()(const MachineType &mtype) const { 51012065Snikos.nikoleris@arm.com return hash<size_t>()(static_cast<size_t>(mtype)); 51112065Snikos.nikoleris@arm.com } 51212065Snikos.nikoleris@arm.com}; 51312065Snikos.nikoleris@arm.com} 51412065Snikos.nikoleris@arm.com 51512065Snikos.nikoleris@arm.com''') 5166657Snate@binkert.org # MachineType hack used to set the base component id for each Machine 5176657Snate@binkert.org if self.isMachineType: 5186657Snate@binkert.org code(''' 5196657Snate@binkert.orgint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 5206657Snate@binkert.orgMachineType ${{self.c_ident}}_from_base_level(int); 5216657Snate@binkert.orgint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 5226657Snate@binkert.orgint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 5236657Snate@binkert.org''') 5246657Snate@binkert.org 5256657Snate@binkert.org for enum in self.enums.itervalues(): 5268602Snilay@cs.wisc.edu if enum.ident == "DMA": 5278602Snilay@cs.wisc.edu code(''' 52811025Snilay@cs.wisc.eduMachineID map_Address_to_DMA(const Addr &addr); 5298602Snilay@cs.wisc.edu''') 5308602Snilay@cs.wisc.edu code(''' 5318602Snilay@cs.wisc.edu 5328602Snilay@cs.wisc.eduMachineID get${{enum.ident}}MachineID(NodeID RubyNode); 5338602Snilay@cs.wisc.edu''') 5348602Snilay@cs.wisc.edu 5358086SBrad.Beckmann@amd.com if self.isStateDecl: 5368086SBrad.Beckmann@amd.com code(''' 5378086SBrad.Beckmann@amd.com 5388086SBrad.Beckmann@amd.com// Code to convert the current state to an access permission 5398086SBrad.Beckmann@amd.comAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 5408086SBrad.Beckmann@amd.com 5418086SBrad.Beckmann@amd.com''') 5428086SBrad.Beckmann@amd.com 5436657Snate@binkert.org # Trailer 5446657Snate@binkert.org code(''' 5457002Snate@binkert.orgstd::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 5466657Snate@binkert.org 5477007Snate@binkert.org#endif // __${{self.c_ident}}_HH__ 5486657Snate@binkert.org''') 5496657Snate@binkert.org 5506657Snate@binkert.org code.write(path, "%s.hh" % self.c_ident) 5516657Snate@binkert.org 5526657Snate@binkert.org def printEnumCC(self, path): 5536999Snate@binkert.org code = self.symtab.codeFormatter() 5546657Snate@binkert.org code(''' 5556657Snate@binkert.org/** \\file ${{self.c_ident}}.hh 5566657Snate@binkert.org * 5576657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 5586657Snate@binkert.org */ 5596657Snate@binkert.org 5607832Snate@binkert.org#include <cassert> 5617002Snate@binkert.org#include <iostream> 5627002Snate@binkert.org#include <string> 5637002Snate@binkert.org 5647805Snilay@cs.wisc.edu#include "base/misc.hh" 5656657Snate@binkert.org#include "mem/protocol/${{self.c_ident}}.hh" 5666657Snate@binkert.org 5677002Snate@binkert.orgusing namespace std; 5687002Snate@binkert.org 5696657Snate@binkert.org''') 5706657Snate@binkert.org 5718086SBrad.Beckmann@amd.com if self.isStateDecl: 5728086SBrad.Beckmann@amd.com code(''' 5738086SBrad.Beckmann@amd.com// Code to convert the current state to an access permission 5748086SBrad.Beckmann@amd.comAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 5758086SBrad.Beckmann@amd.com{ 5768086SBrad.Beckmann@amd.com switch(obj) { 5778086SBrad.Beckmann@amd.com''') 5788086SBrad.Beckmann@amd.com # For each case 5798086SBrad.Beckmann@amd.com code.indent() 5808086SBrad.Beckmann@amd.com for statePerm in self.statePermPairs: 5818086SBrad.Beckmann@amd.com code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 5828086SBrad.Beckmann@amd.com code(' return AccessPermission_${{statePerm[1]}};') 5838086SBrad.Beckmann@amd.com code.dedent() 5848086SBrad.Beckmann@amd.com code (''' 5858086SBrad.Beckmann@amd.com default: 5868086SBrad.Beckmann@amd.com panic("Unknown state access permission converstion for ${{self.c_ident}}"); 5878086SBrad.Beckmann@amd.com } 5888086SBrad.Beckmann@amd.com} 5898086SBrad.Beckmann@amd.com 5908086SBrad.Beckmann@amd.com''') 5918086SBrad.Beckmann@amd.com 5926657Snate@binkert.org if self.isMachineType: 5936657Snate@binkert.org for enum in self.enums.itervalues(): 59411283Santhony.gutierrez@amd.com if enum.primary: 5959773Snilay@cs.wisc.edu code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 59610301Snilay@cs.wisc.edu code('#include "mem/ruby/common/MachineID.hh"') 5976657Snate@binkert.org 5986657Snate@binkert.org code(''' 5997007Snate@binkert.org// Code for output operator 6007007Snate@binkert.orgostream& 6017007Snate@binkert.orgoperator<<(ostream& out, const ${{self.c_ident}}& obj) 6026657Snate@binkert.org{ 6036657Snate@binkert.org out << ${{self.c_ident}}_to_string(obj); 6046657Snate@binkert.org out << flush; 6056657Snate@binkert.org return out; 6066657Snate@binkert.org} 6076657Snate@binkert.org 6087007Snate@binkert.org// Code to convert state to a string 6097007Snate@binkert.orgstring 6107007Snate@binkert.org${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 6116657Snate@binkert.org{ 6126657Snate@binkert.org switch(obj) { 6136657Snate@binkert.org''') 6146657Snate@binkert.org 6156657Snate@binkert.org # For each field 6166657Snate@binkert.org code.indent() 6176657Snate@binkert.org for enum in self.enums.itervalues(): 6186657Snate@binkert.org code(' case ${{self.c_ident}}_${{enum.ident}}:') 6196657Snate@binkert.org code(' return "${{enum.ident}}";') 6206657Snate@binkert.org code.dedent() 6216657Snate@binkert.org 6226657Snate@binkert.org # Trailer 6236657Snate@binkert.org code(''' 6246657Snate@binkert.org default: 6257805Snilay@cs.wisc.edu panic("Invalid range for type ${{self.c_ident}}"); 6266657Snate@binkert.org } 6276657Snate@binkert.org} 6286657Snate@binkert.org 6297007Snate@binkert.org// Code to convert from a string to the enumeration 6307007Snate@binkert.org${{self.c_ident}} 6317007Snate@binkert.orgstring_to_${{self.c_ident}}(const string& str) 6326657Snate@binkert.org{ 6336657Snate@binkert.org''') 6346657Snate@binkert.org 6356657Snate@binkert.org # For each field 6367007Snate@binkert.org start = "" 6376657Snate@binkert.org code.indent() 6386657Snate@binkert.org for enum in self.enums.itervalues(): 6396657Snate@binkert.org code('${start}if (str == "${{enum.ident}}") {') 6406657Snate@binkert.org code(' return ${{self.c_ident}}_${{enum.ident}};') 6417007Snate@binkert.org start = "} else " 6426657Snate@binkert.org code.dedent() 6436657Snate@binkert.org 6446657Snate@binkert.org code(''' 6456657Snate@binkert.org } else { 6467805Snilay@cs.wisc.edu panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 6476657Snate@binkert.org } 6486657Snate@binkert.org} 6496657Snate@binkert.org 6507007Snate@binkert.org// Code to increment an enumeration type 6517007Snate@binkert.org${{self.c_ident}}& 6527007Snate@binkert.orgoperator++(${{self.c_ident}}& e) 6537007Snate@binkert.org{ 6546657Snate@binkert.org assert(e < ${{self.c_ident}}_NUM); 6556657Snate@binkert.org return e = ${{self.c_ident}}(e+1); 6566657Snate@binkert.org} 6576657Snate@binkert.org''') 6586657Snate@binkert.org 6596657Snate@binkert.org # MachineType hack used to set the base level and number of 6606657Snate@binkert.org # components for each Machine 6616657Snate@binkert.org if self.isMachineType: 6626657Snate@binkert.org code(''' 6637007Snate@binkert.org/** \\brief returns the base vector index for each machine type to be 6647007Snate@binkert.org * used by NetDest 6656657Snate@binkert.org * 6666657Snate@binkert.org * \\return the base vector index for each machine type to be used by NetDest 6676657Snate@binkert.org * \\see NetDest.hh 6686657Snate@binkert.org */ 6697007Snate@binkert.orgint 6707007Snate@binkert.org${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 6716657Snate@binkert.org{ 6726657Snate@binkert.org switch(obj) { 6736657Snate@binkert.org''') 6746657Snate@binkert.org 6756657Snate@binkert.org # For each field 6766657Snate@binkert.org code.indent() 6776657Snate@binkert.org for i,enum in enumerate(self.enums.itervalues()): 6786657Snate@binkert.org code(' case ${{self.c_ident}}_${{enum.ident}}:') 6796657Snate@binkert.org code(' return $i;') 6806657Snate@binkert.org code.dedent() 6816657Snate@binkert.org 6826657Snate@binkert.org # total num 6836657Snate@binkert.org code(''' 6846657Snate@binkert.org case ${{self.c_ident}}_NUM: 6856657Snate@binkert.org return ${{len(self.enums)}}; 6866657Snate@binkert.org 6876657Snate@binkert.org default: 6887805Snilay@cs.wisc.edu panic("Invalid range for type ${{self.c_ident}}"); 6896657Snate@binkert.org } 6906657Snate@binkert.org} 6916657Snate@binkert.org 6926657Snate@binkert.org/** \\brief returns the machine type for each base vector index used by NetDest 6936657Snate@binkert.org * 6947007Snate@binkert.org * \\return the MachineType 6956657Snate@binkert.org */ 6967007Snate@binkert.orgMachineType 6977007Snate@binkert.org${{self.c_ident}}_from_base_level(int type) 6986657Snate@binkert.org{ 6996657Snate@binkert.org switch(type) { 7006657Snate@binkert.org''') 7016657Snate@binkert.org 7026657Snate@binkert.org # For each field 7036657Snate@binkert.org code.indent() 7046657Snate@binkert.org for i,enum in enumerate(self.enums.itervalues()): 7056657Snate@binkert.org code(' case $i:') 7066657Snate@binkert.org code(' return ${{self.c_ident}}_${{enum.ident}};') 7076657Snate@binkert.org code.dedent() 7086657Snate@binkert.org 7096657Snate@binkert.org # Trailer 7106657Snate@binkert.org code(''' 7116657Snate@binkert.org default: 7127805Snilay@cs.wisc.edu panic("Invalid range for type ${{self.c_ident}}"); 7136657Snate@binkert.org } 7146657Snate@binkert.org} 7156657Snate@binkert.org 7166657Snate@binkert.org/** \\brief The return value indicates the number of components created 7176657Snate@binkert.org * before a particular machine\'s components 7186657Snate@binkert.org * 7196657Snate@binkert.org * \\return the base number of components for each machine 7206657Snate@binkert.org */ 7217007Snate@binkert.orgint 7227007Snate@binkert.org${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 7236657Snate@binkert.org{ 7246657Snate@binkert.org int base = 0; 7256657Snate@binkert.org switch(obj) { 7266657Snate@binkert.org''') 7276657Snate@binkert.org 7286657Snate@binkert.org # For each field 7296657Snate@binkert.org code.indent() 7306657Snate@binkert.org code(' case ${{self.c_ident}}_NUM:') 7316657Snate@binkert.org for enum in reversed(self.enums.values()): 7329773Snilay@cs.wisc.edu # Check if there is a defined machine with this type 73311283Santhony.gutierrez@amd.com if enum.primary: 7349773Snilay@cs.wisc.edu code(' base += ${{enum.ident}}_Controller::getNumControllers();') 7359773Snilay@cs.wisc.edu else: 7369773Snilay@cs.wisc.edu code(' base += 0;') 7376657Snate@binkert.org code(' case ${{self.c_ident}}_${{enum.ident}}:') 7386657Snate@binkert.org code(' break;') 7396657Snate@binkert.org code.dedent() 7406657Snate@binkert.org 7416657Snate@binkert.org code(''' 7426657Snate@binkert.org default: 7437805Snilay@cs.wisc.edu panic("Invalid range for type ${{self.c_ident}}"); 7446657Snate@binkert.org } 7456657Snate@binkert.org 7466657Snate@binkert.org return base; 7476657Snate@binkert.org} 7486657Snate@binkert.org 7496657Snate@binkert.org/** \\brief returns the total number of components for each machine 7506657Snate@binkert.org * \\return the total number of components for each machine 7516657Snate@binkert.org */ 7527007Snate@binkert.orgint 7537007Snate@binkert.org${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 7546657Snate@binkert.org{ 7556657Snate@binkert.org switch(obj) { 7566657Snate@binkert.org''') 7576657Snate@binkert.org 7586657Snate@binkert.org # For each field 7596657Snate@binkert.org for enum in self.enums.itervalues(): 7609773Snilay@cs.wisc.edu code('case ${{self.c_ident}}_${{enum.ident}}:') 76111283Santhony.gutierrez@amd.com if enum.primary: 7629773Snilay@cs.wisc.edu code('return ${{enum.ident}}_Controller::getNumControllers();') 7639773Snilay@cs.wisc.edu else: 7649773Snilay@cs.wisc.edu code('return 0;') 7656657Snate@binkert.org 7666657Snate@binkert.org # total num 7676657Snate@binkert.org code(''' 7686657Snate@binkert.org case ${{self.c_ident}}_NUM: 7696657Snate@binkert.org default: 7707805Snilay@cs.wisc.edu panic("Invalid range for type ${{self.c_ident}}"); 7716657Snate@binkert.org } 7726657Snate@binkert.org} 7736657Snate@binkert.org''') 7746657Snate@binkert.org 7758602Snilay@cs.wisc.edu for enum in self.enums.itervalues(): 7768602Snilay@cs.wisc.edu if enum.ident == "DMA": 7778602Snilay@cs.wisc.edu code(''' 7788602Snilay@cs.wisc.eduMachineID 77911025Snilay@cs.wisc.edumap_Address_to_DMA(const Addr &addr) 7808602Snilay@cs.wisc.edu{ 7818602Snilay@cs.wisc.edu MachineID dma = {MachineType_DMA, 0}; 7828602Snilay@cs.wisc.edu return dma; 7838602Snilay@cs.wisc.edu} 7848602Snilay@cs.wisc.edu''') 7858602Snilay@cs.wisc.edu 7868602Snilay@cs.wisc.edu code(''' 7878602Snilay@cs.wisc.edu 7888602Snilay@cs.wisc.eduMachineID 7898602Snilay@cs.wisc.eduget${{enum.ident}}MachineID(NodeID RubyNode) 7908602Snilay@cs.wisc.edu{ 7918602Snilay@cs.wisc.edu MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 7928602Snilay@cs.wisc.edu return mach; 7938602Snilay@cs.wisc.edu} 7948602Snilay@cs.wisc.edu''') 7958602Snilay@cs.wisc.edu 7966657Snate@binkert.org # Write the file 7976657Snate@binkert.org code.write(path, "%s.cc" % self.c_ident) 7986657Snate@binkert.org 7996657Snate@binkert.org__all__ = [ "Type" ] 800