Type.py revision 13672
16019Shines@cs.fsu.edu# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 26019Shines@cs.fsu.edu# Copyright (c) 2009 The Hewlett-Packard Development Company 37178Sgblack@eecs.umich.edu# All rights reserved. 47178Sgblack@eecs.umich.edu# 57178Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 67178Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 77178Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 87178Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 97178Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 107178Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 117178Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 127178Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 137178Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 147178Sgblack@eecs.umich.edu# this software without specific prior written permission. 156019Shines@cs.fsu.edu# 166019Shines@cs.fsu.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu 286019Shines@cs.fsu.edufrom collections import OrderedDict 296019Shines@cs.fsu.edu 306019Shines@cs.fsu.edufrom slicc.util import PairContainer 316019Shines@cs.fsu.edufrom slicc.symbols.Symbol import Symbol 326019Shines@cs.fsu.edufrom slicc.symbols.Var import Var 336019Shines@cs.fsu.edu 346019Shines@cs.fsu.educlass DataMember(Var): 356019Shines@cs.fsu.edu def __init__(self, symtab, ident, location, type, code, pairs, 366019Shines@cs.fsu.edu machine, init_code): 376019Shines@cs.fsu.edu super(DataMember, self).__init__(symtab, ident, location, type, 386019Shines@cs.fsu.edu code, pairs, machine) 396019Shines@cs.fsu.edu self.init_code = init_code 406019Shines@cs.fsu.edu 416019Shines@cs.fsu.educlass Enumeration(PairContainer): 426019Shines@cs.fsu.edu def __init__(self, ident, pairs): 436019Shines@cs.fsu.edu super(Enumeration, self).__init__(pairs) 446019Shines@cs.fsu.edu self.ident = ident 456019Shines@cs.fsu.edu self.primary = False 466019Shines@cs.fsu.edu 476019Shines@cs.fsu.educlass Type(Symbol): 486019Shines@cs.fsu.edu def __init__(self, table, ident, location, pairs, machine=None): 496019Shines@cs.fsu.edu super(Type, self).__init__(table, ident, location, pairs) 506019Shines@cs.fsu.edu self.c_ident = ident 516019Shines@cs.fsu.edu self.abstract_ident = "" 526019Shines@cs.fsu.edu if machine: 536019Shines@cs.fsu.edu if self.isExternal or self.isPrimitive: 546019Shines@cs.fsu.edu if "external_name" in self: 556019Shines@cs.fsu.edu self.c_ident = self["external_name"] 566019Shines@cs.fsu.edu else: 576019Shines@cs.fsu.edu # Append with machine name 586243Sgblack@eecs.umich.edu self.c_ident = "%s_%s" % (machine, ident) 596243Sgblack@eecs.umich.edu 606243Sgblack@eecs.umich.edu self.pairs.setdefault("desc", "No description avaliable") 616243Sgblack@eecs.umich.edu 626243Sgblack@eecs.umich.edu # check for interface that this Type implements 636019Shines@cs.fsu.edu if "interface" in self: 646019Shines@cs.fsu.edu interface = self["interface"] 656019Shines@cs.fsu.edu if interface in ("Message"): 666019Shines@cs.fsu.edu self["message"] = "yes" 676019Shines@cs.fsu.edu 686019Shines@cs.fsu.edu # FIXME - all of the following id comparisons are fragile hacks 696019Shines@cs.fsu.edu if self.ident in ("CacheMemory"): 706019Shines@cs.fsu.edu self["cache"] = "yes" 716019Shines@cs.fsu.edu 726019Shines@cs.fsu.edu if self.ident in ("TBETable"): 736019Shines@cs.fsu.edu self["tbe"] = "yes" 746019Shines@cs.fsu.edu 756019Shines@cs.fsu.edu if self.ident == "TimerTable": 766019Shines@cs.fsu.edu self["timer"] = "yes" 776019Shines@cs.fsu.edu 786019Shines@cs.fsu.edu if self.ident == "DirectoryMemory": 796019Shines@cs.fsu.edu self["dir"] = "yes" 806019Shines@cs.fsu.edu 816019Shines@cs.fsu.edu if self.ident == "PersistentTable": 826019Shines@cs.fsu.edu self["persistent"] = "yes" 836019Shines@cs.fsu.edu 846019Shines@cs.fsu.edu if self.ident == "Prefetcher": 856019Shines@cs.fsu.edu self["prefetcher"] = "yes" 866019Shines@cs.fsu.edu 876019Shines@cs.fsu.edu self.isMachineType = (ident == "MachineType") 886019Shines@cs.fsu.edu 896019Shines@cs.fsu.edu self.isStateDecl = ("state_decl" in self) 906019Shines@cs.fsu.edu self.statePermPairs = [] 916019Shines@cs.fsu.edu 926019Shines@cs.fsu.edu self.data_members = OrderedDict() 936019Shines@cs.fsu.edu self.methods = {} 946252Sgblack@eecs.umich.edu self.enums = OrderedDict() 956243Sgblack@eecs.umich.edu 966243Sgblack@eecs.umich.edu @property 976243Sgblack@eecs.umich.edu def isPrimitive(self): 986019Shines@cs.fsu.edu return "primitive" in self 996019Shines@cs.fsu.edu 1006019Shines@cs.fsu.edu @property 1016019Shines@cs.fsu.edu def isMessage(self): 1026019Shines@cs.fsu.edu return "message" in self 1036252Sgblack@eecs.umich.edu @property 1046243Sgblack@eecs.umich.edu def isBuffer(self): 1056243Sgblack@eecs.umich.edu return "buffer" in self 1066243Sgblack@eecs.umich.edu @property 1076019Shines@cs.fsu.edu def isInPort(self): 1086019Shines@cs.fsu.edu return "inport" in self 1096019Shines@cs.fsu.edu @property 1106019Shines@cs.fsu.edu def isOutPort(self): 1116019Shines@cs.fsu.edu return "outport" in self 1126019Shines@cs.fsu.edu @property 1136019Shines@cs.fsu.edu def isEnumeration(self): 1146252Sgblack@eecs.umich.edu return "enumeration" in self 1156243Sgblack@eecs.umich.edu @property 1166243Sgblack@eecs.umich.edu def isExternal(self): 1176243Sgblack@eecs.umich.edu return "external" in self 1186019Shines@cs.fsu.edu @property 1196019Shines@cs.fsu.edu def isGlobal(self): 1206019Shines@cs.fsu.edu return "global" in self 1216019Shines@cs.fsu.edu @property 1226019Shines@cs.fsu.edu def isInterface(self): 1236019Shines@cs.fsu.edu return "interface" in self 1246019Shines@cs.fsu.edu 1256019Shines@cs.fsu.edu # Return false on error 1266019Shines@cs.fsu.edu def addDataMember(self, ident, type, pairs, init_code): 1276019Shines@cs.fsu.edu if ident in self.data_members: 1286019Shines@cs.fsu.edu return False 1296019Shines@cs.fsu.edu 1306019Shines@cs.fsu.edu member = DataMember(self.symtab, ident, self.location, type, 1316019Shines@cs.fsu.edu "m_%s" % ident, pairs, None, init_code) 1326019Shines@cs.fsu.edu 1336019Shines@cs.fsu.edu self.data_members[ident] = member 1346724Sgblack@eecs.umich.edu self.symtab.registerSym(ident, member) 1356724Sgblack@eecs.umich.edu return True 1366019Shines@cs.fsu.edu 1376019Shines@cs.fsu.edu def dataMemberType(self, ident): 1386019Shines@cs.fsu.edu return self.data_members[ident].type 1396019Shines@cs.fsu.edu 1406019Shines@cs.fsu.edu def methodId(self, name, param_type_vec): 1416252Sgblack@eecs.umich.edu return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 1426243Sgblack@eecs.umich.edu 1436243Sgblack@eecs.umich.edu def methodIdAbstract(self, name, param_type_vec): 1446243Sgblack@eecs.umich.edu return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 1456019Shines@cs.fsu.edu 1466019Shines@cs.fsu.edu def statePermPairAdd(self, state_name, perm_name): 1476019Shines@cs.fsu.edu self.statePermPairs.append([state_name, perm_name]) 1486019Shines@cs.fsu.edu 1496019Shines@cs.fsu.edu def addFunc(self, func): 1506019Shines@cs.fsu.edu ident = self.methodId(func.ident, func.param_types) 1517356Sgblack@eecs.umich.edu if ident in self.methods: 1527356Sgblack@eecs.umich.edu return False 1537356Sgblack@eecs.umich.edu 1547356Sgblack@eecs.umich.edu self.methods[ident] = func 1557356Sgblack@eecs.umich.edu return True 1567356Sgblack@eecs.umich.edu 1577356Sgblack@eecs.umich.edu def addEnum(self, ident, pairs): 1587356Sgblack@eecs.umich.edu if ident in self.enums: 1597178Sgblack@eecs.umich.edu return False 1607178Sgblack@eecs.umich.edu 1617178Sgblack@eecs.umich.edu self.enums[ident] = Enumeration(ident, pairs) 1627337Sgblack@eecs.umich.edu 1637178Sgblack@eecs.umich.edu # Add default 1647178Sgblack@eecs.umich.edu if "default" not in self: 1657178Sgblack@eecs.umich.edu self["default"] = "%s_NUM" % self.c_ident 1667178Sgblack@eecs.umich.edu 1677178Sgblack@eecs.umich.edu return True 1687178Sgblack@eecs.umich.edu 1697178Sgblack@eecs.umich.edu ## Used to check if an enum has been already used and therefore 1707178Sgblack@eecs.umich.edu ## should not be used again. 1717178Sgblack@eecs.umich.edu def checkEnum(self, ident): 1727178Sgblack@eecs.umich.edu if ident in self.enums and not self.enums[ident].primary: 1737178Sgblack@eecs.umich.edu self.enums[ident].primary = True 1747335Sgblack@eecs.umich.edu return True 1757335Sgblack@eecs.umich.edu return False 1767335Sgblack@eecs.umich.edu 1777335Sgblack@eecs.umich.edu def writeCodeFiles(self, path, includes): 1787335Sgblack@eecs.umich.edu if self.isExternal: 1797335Sgblack@eecs.umich.edu # Do nothing 1807335Sgblack@eecs.umich.edu pass 1817335Sgblack@eecs.umich.edu elif self.isEnumeration: 1827335Sgblack@eecs.umich.edu self.printEnumHH(path) 1837335Sgblack@eecs.umich.edu self.printEnumCC(path) 1847335Sgblack@eecs.umich.edu else: 1857335Sgblack@eecs.umich.edu # User defined structs and messages 1867337Sgblack@eecs.umich.edu self.printTypeHH(path) 1877335Sgblack@eecs.umich.edu self.printTypeCC(path) 1887335Sgblack@eecs.umich.edu 1897335Sgblack@eecs.umich.edu def printTypeHH(self, path): 1907335Sgblack@eecs.umich.edu code = self.symtab.codeFormatter() 1917335Sgblack@eecs.umich.edu code(''' 1927335Sgblack@eecs.umich.edu/** \\file ${{self.c_ident}}.hh 1937335Sgblack@eecs.umich.edu * 1947335Sgblack@eecs.umich.edu * 1957335Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__ 1967335Sgblack@eecs.umich.edu */ 1977335Sgblack@eecs.umich.edu 1987335Sgblack@eecs.umich.edu#ifndef __${{self.c_ident}}_HH__ 1997178Sgblack@eecs.umich.edu#define __${{self.c_ident}}_HH__ 2007178Sgblack@eecs.umich.edu 2017178Sgblack@eecs.umich.edu#include <iostream> 2027178Sgblack@eecs.umich.edu 2037178Sgblack@eecs.umich.edu#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 2047178Sgblack@eecs.umich.edu''') 2057178Sgblack@eecs.umich.edu 2067178Sgblack@eecs.umich.edu for dm in self.data_members.values(): 2077178Sgblack@eecs.umich.edu if not dm.type.isPrimitive: 2087178Sgblack@eecs.umich.edu code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 2097178Sgblack@eecs.umich.edu 2107178Sgblack@eecs.umich.edu parent = "" 2117178Sgblack@eecs.umich.edu if "interface" in self: 2127178Sgblack@eecs.umich.edu code('#include "mem/protocol/$0.hh"', self["interface"]) 2137178Sgblack@eecs.umich.edu parent = " : public %s" % self["interface"] 2147178Sgblack@eecs.umich.edu 2157178Sgblack@eecs.umich.edu code(''' 2167178Sgblack@eecs.umich.edu$klass ${{self.c_ident}}$parent 2177178Sgblack@eecs.umich.edu{ 2187178Sgblack@eecs.umich.edu public: 2197178Sgblack@eecs.umich.edu ${{self.c_ident}} 2207178Sgblack@eecs.umich.edu''', klass="class") 2217178Sgblack@eecs.umich.edu 2227178Sgblack@eecs.umich.edu if self.isMessage: 2237178Sgblack@eecs.umich.edu code('(Tick curTime) : %s(curTime) {' % self["interface"]) 2247178Sgblack@eecs.umich.edu else: 2257178Sgblack@eecs.umich.edu code('()\n\t\t{') 2267178Sgblack@eecs.umich.edu 2277178Sgblack@eecs.umich.edu code.indent() 2287346Sgblack@eecs.umich.edu if not self.isGlobal: 2297346Sgblack@eecs.umich.edu code.indent() 2307346Sgblack@eecs.umich.edu for dm in self.data_members.values(): 2317346Sgblack@eecs.umich.edu ident = dm.ident 2327346Sgblack@eecs.umich.edu if "default" in dm: 2337346Sgblack@eecs.umich.edu # look for default value 2347346Sgblack@eecs.umich.edu code('m_$ident = ${{dm["default"]}}; // default for this field') 2357346Sgblack@eecs.umich.edu elif "default" in dm.type: 2367346Sgblack@eecs.umich.edu # Look for the type default 2377346Sgblack@eecs.umich.edu tid = dm.type.c_ident 2387178Sgblack@eecs.umich.edu code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 2397346Sgblack@eecs.umich.edu else: 2407346Sgblack@eecs.umich.edu code('// m_$ident has no default') 2417346Sgblack@eecs.umich.edu code.dedent() 2427346Sgblack@eecs.umich.edu code('}') 2437346Sgblack@eecs.umich.edu 2447346Sgblack@eecs.umich.edu # ******** Copy constructor ******** 2457346Sgblack@eecs.umich.edu if not self.isGlobal: 2467346Sgblack@eecs.umich.edu code('${{self.c_ident}}(const ${{self.c_ident}}&other)') 2477346Sgblack@eecs.umich.edu 2487346Sgblack@eecs.umich.edu # Call superclass constructor 2497346Sgblack@eecs.umich.edu if "interface" in self: 2507346Sgblack@eecs.umich.edu code(' : ${{self["interface"]}}(other)') 2517346Sgblack@eecs.umich.edu 2527346Sgblack@eecs.umich.edu code('{') 2537346Sgblack@eecs.umich.edu code.indent() 2547178Sgblack@eecs.umich.edu 2557337Sgblack@eecs.umich.edu for dm in self.data_members.values(): 2567337Sgblack@eecs.umich.edu code('m_${{dm.ident}} = other.m_${{dm.ident}};') 2577337Sgblack@eecs.umich.edu 2587337Sgblack@eecs.umich.edu code.dedent() 2597337Sgblack@eecs.umich.edu code('}') 2607337Sgblack@eecs.umich.edu 2617337Sgblack@eecs.umich.edu # ******** Full init constructor ******** 2627337Sgblack@eecs.umich.edu if not self.isGlobal: 2637337Sgblack@eecs.umich.edu params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 2647337Sgblack@eecs.umich.edu for dm in self.data_members.itervalues() ] 2657337Sgblack@eecs.umich.edu params = ', '.join(params) 2667337Sgblack@eecs.umich.edu 2677337Sgblack@eecs.umich.edu if self.isMessage: 2687337Sgblack@eecs.umich.edu params = "const Tick curTime, " + params 2697337Sgblack@eecs.umich.edu 2707178Sgblack@eecs.umich.edu code('${{self.c_ident}}($params)') 2717178Sgblack@eecs.umich.edu 2727178Sgblack@eecs.umich.edu # Call superclass constructor 2737178Sgblack@eecs.umich.edu if "interface" in self: 2747337Sgblack@eecs.umich.edu if self.isMessage: 2757337Sgblack@eecs.umich.edu code(' : ${{self["interface"]}}(curTime)') 2767337Sgblack@eecs.umich.edu else: 2777337Sgblack@eecs.umich.edu code(' : ${{self["interface"]}}()') 2787346Sgblack@eecs.umich.edu 2797346Sgblack@eecs.umich.edu code('{') 2807346Sgblack@eecs.umich.edu code.indent() 2817346Sgblack@eecs.umich.edu for dm in self.data_members.values(): 2827346Sgblack@eecs.umich.edu code('m_${{dm.ident}} = local_${{dm.ident}};') 2837337Sgblack@eecs.umich.edu 2847178Sgblack@eecs.umich.edu code.dedent() 2857321Sgblack@eecs.umich.edu code('}') 2867356Sgblack@eecs.umich.edu 2877321Sgblack@eecs.umich.edu # create a clone member 2887356Sgblack@eecs.umich.edu if self.isMessage: 2897356Sgblack@eecs.umich.edu code(''' 2907356Sgblack@eecs.umich.eduMsgPtr 2917356Sgblack@eecs.umich.educlone() const 2927356Sgblack@eecs.umich.edu{ 2937356Sgblack@eecs.umich.edu return std::shared_ptr<Message>(new ${{self.c_ident}}(*this)); 2947356Sgblack@eecs.umich.edu} 2957356Sgblack@eecs.umich.edu''') 2967356Sgblack@eecs.umich.edu else: 2977356Sgblack@eecs.umich.edu code(''' 2987356Sgblack@eecs.umich.edu${{self.c_ident}}* 2997356Sgblack@eecs.umich.educlone() const 3007321Sgblack@eecs.umich.edu{ 3017321Sgblack@eecs.umich.edu return new ${{self.c_ident}}(*this); 3027321Sgblack@eecs.umich.edu} 3037321Sgblack@eecs.umich.edu''') 3047321Sgblack@eecs.umich.edu 3057321Sgblack@eecs.umich.edu if not self.isGlobal: 3067321Sgblack@eecs.umich.edu # const Get methods for each field 3077321Sgblack@eecs.umich.edu code('// Const accessors methods for each field') 3087321Sgblack@eecs.umich.edu for dm in self.data_members.values(): 3097321Sgblack@eecs.umich.edu code(''' 3107321Sgblack@eecs.umich.edu/** \\brief Const accessor method for ${{dm.ident}} field. 3117335Sgblack@eecs.umich.edu * \\return ${{dm.ident}} field 3127335Sgblack@eecs.umich.edu */ 3137335Sgblack@eecs.umich.educonst ${{dm.type.c_ident}}& 3147335Sgblack@eecs.umich.eduget${{dm.ident}}() const 3157335Sgblack@eecs.umich.edu{ 3167335Sgblack@eecs.umich.edu return m_${{dm.ident}}; 3177335Sgblack@eecs.umich.edu} 3187335Sgblack@eecs.umich.edu''') 3197335Sgblack@eecs.umich.edu 3207321Sgblack@eecs.umich.edu # Non-const Get methods for each field 3217323Sgblack@eecs.umich.edu code('// Non const Accessors methods for each field') 3227323Sgblack@eecs.umich.edu for dm in self.data_members.values(): 3237323Sgblack@eecs.umich.edu code(''' 3247323Sgblack@eecs.umich.edu/** \\brief Non-const accessor method for ${{dm.ident}} field. 3257323Sgblack@eecs.umich.edu * \\return ${{dm.ident}} field 3267323Sgblack@eecs.umich.edu */ 3277323Sgblack@eecs.umich.edu${{dm.type.c_ident}}& 3287323Sgblack@eecs.umich.eduget${{dm.ident}}() 3297323Sgblack@eecs.umich.edu{ 3307323Sgblack@eecs.umich.edu return m_${{dm.ident}}; 3317323Sgblack@eecs.umich.edu} 3327323Sgblack@eecs.umich.edu''') 3337323Sgblack@eecs.umich.edu 3347323Sgblack@eecs.umich.edu #Set methods for each field 3357323Sgblack@eecs.umich.edu code('// Mutator methods for each field') 3367323Sgblack@eecs.umich.edu for dm in self.data_members.values(): 3377323Sgblack@eecs.umich.edu code(''' 3387321Sgblack@eecs.umich.edu/** \\brief Mutator method for ${{dm.ident}} field */ 3397321Sgblack@eecs.umich.eduvoid 3407321Sgblack@eecs.umich.eduset${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 3417335Sgblack@eecs.umich.edu{ 3427335Sgblack@eecs.umich.edu m_${{dm.ident}} = local_${{dm.ident}}; 3437335Sgblack@eecs.umich.edu} 3447335Sgblack@eecs.umich.edu''') 3457335Sgblack@eecs.umich.edu 3467335Sgblack@eecs.umich.edu code('void print(std::ostream& out) const;') 3477335Sgblack@eecs.umich.edu code.dedent() 3487335Sgblack@eecs.umich.edu code(' //private:') 3497335Sgblack@eecs.umich.edu code.indent() 3507335Sgblack@eecs.umich.edu 3517335Sgblack@eecs.umich.edu # Data members for each field 3527335Sgblack@eecs.umich.edu for dm in self.data_members.values(): 3537335Sgblack@eecs.umich.edu if "abstract" not in dm: 3547335Sgblack@eecs.umich.edu const = "" 3557335Sgblack@eecs.umich.edu init = "" 3567335Sgblack@eecs.umich.edu 3577335Sgblack@eecs.umich.edu # global structure 3587335Sgblack@eecs.umich.edu if self.isGlobal: 3597335Sgblack@eecs.umich.edu const = "static const " 3607335Sgblack@eecs.umich.edu 3617335Sgblack@eecs.umich.edu # init value 3627335Sgblack@eecs.umich.edu if dm.init_code: 3637335Sgblack@eecs.umich.edu # only global structure can have init value here 3647335Sgblack@eecs.umich.edu assert self.isGlobal 3657335Sgblack@eecs.umich.edu init = " = %s" % (dm.init_code) 3667335Sgblack@eecs.umich.edu 3677335Sgblack@eecs.umich.edu if "desc" in dm: 3687335Sgblack@eecs.umich.edu code('/** ${{dm["desc"]}} */') 3697335Sgblack@eecs.umich.edu 3707335Sgblack@eecs.umich.edu code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 3717335Sgblack@eecs.umich.edu 3727335Sgblack@eecs.umich.edu # Prototypes for methods defined for the Type 3737335Sgblack@eecs.umich.edu for item in self.methods: 3747321Sgblack@eecs.umich.edu proto = self.methods[item].prototype 3757321Sgblack@eecs.umich.edu if proto: 3767321Sgblack@eecs.umich.edu code('$proto') 3777321Sgblack@eecs.umich.edu 3787321Sgblack@eecs.umich.edu code.dedent() 3797321Sgblack@eecs.umich.edu code('};') 3807335Sgblack@eecs.umich.edu 3817335Sgblack@eecs.umich.edu code(''' 3827335Sgblack@eecs.umich.eduinline std::ostream& 3837335Sgblack@eecs.umich.eduoperator<<(std::ostream& out, const ${{self.c_ident}}& obj) 3847335Sgblack@eecs.umich.edu{ 3857335Sgblack@eecs.umich.edu obj.print(out); 3867335Sgblack@eecs.umich.edu out << std::flush; 3877335Sgblack@eecs.umich.edu return out; 3887335Sgblack@eecs.umich.edu} 3897321Sgblack@eecs.umich.edu 3907326Sgblack@eecs.umich.edu#endif // __${{self.c_ident}}_HH__ 3917326Sgblack@eecs.umich.edu''') 3927326Sgblack@eecs.umich.edu 3937326Sgblack@eecs.umich.edu code.write(path, "%s.hh" % self.c_ident) 3947326Sgblack@eecs.umich.edu 3957326Sgblack@eecs.umich.edu def printTypeCC(self, path): 3967326Sgblack@eecs.umich.edu code = self.symtab.codeFormatter() 3977326Sgblack@eecs.umich.edu 3987326Sgblack@eecs.umich.edu code(''' 3997326Sgblack@eecs.umich.edu/** \\file ${{self.c_ident}}.cc 4007326Sgblack@eecs.umich.edu * 4017326Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__ 4027326Sgblack@eecs.umich.edu */ 4037326Sgblack@eecs.umich.edu 4047326Sgblack@eecs.umich.edu#include <iostream> 4057326Sgblack@eecs.umich.edu#include <memory> 4067326Sgblack@eecs.umich.edu 4077326Sgblack@eecs.umich.edu#include "mem/protocol/${{self.c_ident}}.hh" 4087326Sgblack@eecs.umich.edu#include "mem/ruby/system/RubySystem.hh" 4097326Sgblack@eecs.umich.edu 4107326Sgblack@eecs.umich.eduusing namespace std; 4117326Sgblack@eecs.umich.edu''') 4127326Sgblack@eecs.umich.edu 4137321Sgblack@eecs.umich.edu code(''' 4147321Sgblack@eecs.umich.edu/** \\brief Print the state of this object */ 4157335Sgblack@eecs.umich.eduvoid 4167335Sgblack@eecs.umich.edu${{self.c_ident}}::print(ostream& out) const 4177335Sgblack@eecs.umich.edu{ 4187335Sgblack@eecs.umich.edu out << "[${{self.c_ident}}: "; 4197335Sgblack@eecs.umich.edu''') 4207335Sgblack@eecs.umich.edu 4217335Sgblack@eecs.umich.edu # For each field 4227335Sgblack@eecs.umich.edu code.indent() 4237335Sgblack@eecs.umich.edu for dm in self.data_members.values(): 4247335Sgblack@eecs.umich.edu if dm.type.c_ident == "Addr": 4257335Sgblack@eecs.umich.edu code(''' 4267335Sgblack@eecs.umich.eduout << "${{dm.ident}} = " << printAddress(m_${{dm.ident}}) << " ";''') 4277335Sgblack@eecs.umich.edu else: 4287335Sgblack@eecs.umich.edu code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 4297335Sgblack@eecs.umich.edu 4307335Sgblack@eecs.umich.edu code.dedent() 4317335Sgblack@eecs.umich.edu 4327335Sgblack@eecs.umich.edu # Trailer 4337335Sgblack@eecs.umich.edu code(''' 4347335Sgblack@eecs.umich.edu out << "]"; 4357335Sgblack@eecs.umich.edu}''') 4367335Sgblack@eecs.umich.edu 4377335Sgblack@eecs.umich.edu # print the code for the methods in the type 4387335Sgblack@eecs.umich.edu for item in self.methods: 4397335Sgblack@eecs.umich.edu code(self.methods[item].generateCode()) 4407335Sgblack@eecs.umich.edu 4417335Sgblack@eecs.umich.edu code.write(path, "%s.cc" % self.c_ident) 4427335Sgblack@eecs.umich.edu 4437335Sgblack@eecs.umich.edu def printEnumHH(self, path): 4447335Sgblack@eecs.umich.edu code = self.symtab.codeFormatter() 4457335Sgblack@eecs.umich.edu code(''' 4467335Sgblack@eecs.umich.edu/** \\file ${{self.c_ident}}.hh 4477335Sgblack@eecs.umich.edu * 4487335Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__ 4497335Sgblack@eecs.umich.edu */ 4507335Sgblack@eecs.umich.edu 4517335Sgblack@eecs.umich.edu#ifndef __${{self.c_ident}}_HH__ 4527335Sgblack@eecs.umich.edu#define __${{self.c_ident}}_HH__ 4537335Sgblack@eecs.umich.edu 4547335Sgblack@eecs.umich.edu#include <iostream> 4557335Sgblack@eecs.umich.edu#include <string> 4567335Sgblack@eecs.umich.edu 4577335Sgblack@eecs.umich.edu''') 4587335Sgblack@eecs.umich.edu if self.isStateDecl: 4597321Sgblack@eecs.umich.edu code('#include "mem/protocol/AccessPermission.hh"') 4607321Sgblack@eecs.umich.edu 4617321Sgblack@eecs.umich.edu if self.isMachineType: 4627321Sgblack@eecs.umich.edu code('#include <functional>') 4637321Sgblack@eecs.umich.edu code('#include "base/logging.hh"') 4647356Sgblack@eecs.umich.edu code('#include "mem/ruby/common/Address.hh"') 4657356Sgblack@eecs.umich.edu code('#include "mem/ruby/common/TypeDefines.hh"') 4667356Sgblack@eecs.umich.edu code('struct MachineID;') 4677356Sgblack@eecs.umich.edu 4687356Sgblack@eecs.umich.edu code(''' 4697356Sgblack@eecs.umich.edu 4707363Sgblack@eecs.umich.edu// Class definition 4717363Sgblack@eecs.umich.edu/** \\enum ${{self.c_ident}} 4727363Sgblack@eecs.umich.edu * \\brief ${{self.desc}} 4737363Sgblack@eecs.umich.edu */ 4747363Sgblack@eecs.umich.eduenum ${{self.c_ident}} { 4757363Sgblack@eecs.umich.edu ${{self.c_ident}}_FIRST, 4767363Sgblack@eecs.umich.edu''') 4777363Sgblack@eecs.umich.edu 4787363Sgblack@eecs.umich.edu code.indent() 4797363Sgblack@eecs.umich.edu # For each field 4807363Sgblack@eecs.umich.edu for i,(ident,enum) in enumerate(self.enums.iteritems()): 4817363Sgblack@eecs.umich.edu desc = enum.get("desc", "No description avaliable") 4827363Sgblack@eecs.umich.edu if i == 0: 4837363Sgblack@eecs.umich.edu init = ' = %s_FIRST' % self.c_ident 4847363Sgblack@eecs.umich.edu else: 4857363Sgblack@eecs.umich.edu init = '' 4867363Sgblack@eecs.umich.edu code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 4877363Sgblack@eecs.umich.edu code.dedent() 4887363Sgblack@eecs.umich.edu code(''' 4897364Sgblack@eecs.umich.edu ${{self.c_ident}}_NUM 4907364Sgblack@eecs.umich.edu}; 4917364Sgblack@eecs.umich.edu 4927364Sgblack@eecs.umich.edu// Code to convert from a string to the enumeration 4937364Sgblack@eecs.umich.edu${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 4947364Sgblack@eecs.umich.edu 4957364Sgblack@eecs.umich.edu// Code to convert state to a string 4967364Sgblack@eecs.umich.edustd::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 4977364Sgblack@eecs.umich.edu 4987364Sgblack@eecs.umich.edu// Code to increment an enumeration type 4997364Sgblack@eecs.umich.edu${{self.c_ident}} &operator++(${{self.c_ident}} &e); 5007364Sgblack@eecs.umich.edu''') 5017364Sgblack@eecs.umich.edu 5027364Sgblack@eecs.umich.edu if self.isMachineType: 5037364Sgblack@eecs.umich.edu code(''' 5047364Sgblack@eecs.umich.edu 5057364Sgblack@eecs.umich.edu// define a hash function for the MachineType class 5067364Sgblack@eecs.umich.edunamespace std { 5077364Sgblack@eecs.umich.edutemplate<> 5087363Sgblack@eecs.umich.edustruct hash<MachineType> { 5097363Sgblack@eecs.umich.edu std::size_t operator()(const MachineType &mtype) const { 5107363Sgblack@eecs.umich.edu return hash<size_t>()(static_cast<size_t>(mtype)); 5117363Sgblack@eecs.umich.edu } 5127363Sgblack@eecs.umich.edu}; 5137363Sgblack@eecs.umich.edu} 5147363Sgblack@eecs.umich.edu 5157363Sgblack@eecs.umich.edu''') 5167363Sgblack@eecs.umich.edu # MachineType hack used to set the base component id for each Machine 5177363Sgblack@eecs.umich.edu if self.isMachineType: 5187363Sgblack@eecs.umich.edu code(''' 5197363Sgblack@eecs.umich.eduint ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 5207363Sgblack@eecs.umich.eduMachineType ${{self.c_ident}}_from_base_level(int); 5217363Sgblack@eecs.umich.eduint ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 5227363Sgblack@eecs.umich.eduint ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 5237363Sgblack@eecs.umich.edu''') 5247363Sgblack@eecs.umich.edu 5257363Sgblack@eecs.umich.edu for enum in self.enums.itervalues(): 5267363Sgblack@eecs.umich.edu code(''' 5277363Sgblack@eecs.umich.edu 5287363Sgblack@eecs.umich.eduMachineID get${{enum.ident}}MachineID(NodeID RubyNode); 5297363Sgblack@eecs.umich.edu''') 5307363Sgblack@eecs.umich.edu 5317363Sgblack@eecs.umich.edu if self.isStateDecl: 5327363Sgblack@eecs.umich.edu code(''' 5337363Sgblack@eecs.umich.edu 5347363Sgblack@eecs.umich.edu// Code to convert the current state to an access permission 5357363Sgblack@eecs.umich.eduAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 5367363Sgblack@eecs.umich.edu 5377363Sgblack@eecs.umich.edu''') 5387363Sgblack@eecs.umich.edu 5397363Sgblack@eecs.umich.edu # Trailer 5407363Sgblack@eecs.umich.edu code(''' 5417363Sgblack@eecs.umich.edustd::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 5427363Sgblack@eecs.umich.edu 5437363Sgblack@eecs.umich.edu#endif // __${{self.c_ident}}_HH__ 5447363Sgblack@eecs.umich.edu''') 5457363Sgblack@eecs.umich.edu 5467363Sgblack@eecs.umich.edu code.write(path, "%s.hh" % self.c_ident) 5477363Sgblack@eecs.umich.edu 5487363Sgblack@eecs.umich.edu def printEnumCC(self, path): 5497363Sgblack@eecs.umich.edu code = self.symtab.codeFormatter() 5507363Sgblack@eecs.umich.edu code(''' 5517363Sgblack@eecs.umich.edu/** \\file ${{self.c_ident}}.hh 5527363Sgblack@eecs.umich.edu * 5537363Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__ 5547363Sgblack@eecs.umich.edu */ 5557363Sgblack@eecs.umich.edu 5567363Sgblack@eecs.umich.edu#include <cassert> 5577366Sgblack@eecs.umich.edu#include <iostream> 5587366Sgblack@eecs.umich.edu#include <string> 5597366Sgblack@eecs.umich.edu 5607366Sgblack@eecs.umich.edu#include "base/logging.hh" 5617366Sgblack@eecs.umich.edu#include "mem/protocol/${{self.c_ident}}.hh" 5627366Sgblack@eecs.umich.edu 5637366Sgblack@eecs.umich.eduusing namespace std; 5647366Sgblack@eecs.umich.edu 5657366Sgblack@eecs.umich.edu''') 5667366Sgblack@eecs.umich.edu 5677366Sgblack@eecs.umich.edu if self.isStateDecl: 5687366Sgblack@eecs.umich.edu code(''' 5697366Sgblack@eecs.umich.edu// Code to convert the current state to an access permission 5707366Sgblack@eecs.umich.eduAccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 5717366Sgblack@eecs.umich.edu{ 5727363Sgblack@eecs.umich.edu switch(obj) { 5737363Sgblack@eecs.umich.edu''') 5747363Sgblack@eecs.umich.edu # For each case 5757365Sgblack@eecs.umich.edu code.indent() 5767365Sgblack@eecs.umich.edu for statePerm in self.statePermPairs: 5777365Sgblack@eecs.umich.edu code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 5787365Sgblack@eecs.umich.edu code(' return AccessPermission_${{statePerm[1]}};') 5797365Sgblack@eecs.umich.edu code.dedent() 5807365Sgblack@eecs.umich.edu code (''' 5817365Sgblack@eecs.umich.edu default: 5827365Sgblack@eecs.umich.edu panic("Unknown state access permission converstion for ${{self.c_ident}}"); 5837365Sgblack@eecs.umich.edu } 5847365Sgblack@eecs.umich.edu} 5857365Sgblack@eecs.umich.edu 5867365Sgblack@eecs.umich.edu''') 5877365Sgblack@eecs.umich.edu 5887365Sgblack@eecs.umich.edu if self.isMachineType: 5897365Sgblack@eecs.umich.edu for enum in self.enums.itervalues(): 5907363Sgblack@eecs.umich.edu if enum.primary: 5917363Sgblack@eecs.umich.edu code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 5927363Sgblack@eecs.umich.edu code('#include "mem/ruby/common/MachineID.hh"') 5937363Sgblack@eecs.umich.edu 5947363Sgblack@eecs.umich.edu code(''' 5957363Sgblack@eecs.umich.edu// Code for output operator 5967363Sgblack@eecs.umich.eduostream& 5977363Sgblack@eecs.umich.eduoperator<<(ostream& out, const ${{self.c_ident}}& obj) 5987363Sgblack@eecs.umich.edu{ 5997363Sgblack@eecs.umich.edu out << ${{self.c_ident}}_to_string(obj); 6007363Sgblack@eecs.umich.edu out << flush; 6017363Sgblack@eecs.umich.edu return out; 6027363Sgblack@eecs.umich.edu} 6037363Sgblack@eecs.umich.edu 6047363Sgblack@eecs.umich.edu// Code to convert state to a string 6057363Sgblack@eecs.umich.edustring 6067363Sgblack@eecs.umich.edu${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 6077363Sgblack@eecs.umich.edu{ 6087363Sgblack@eecs.umich.edu switch(obj) { 6097363Sgblack@eecs.umich.edu''') 6107363Sgblack@eecs.umich.edu 6117363Sgblack@eecs.umich.edu # For each field 6127363Sgblack@eecs.umich.edu code.indent() 6137363Sgblack@eecs.umich.edu for enum in self.enums.itervalues(): 6147363Sgblack@eecs.umich.edu code(' case ${{self.c_ident}}_${{enum.ident}}:') 6157363Sgblack@eecs.umich.edu code(' return "${{enum.ident}}";') 6167363Sgblack@eecs.umich.edu code.dedent() 6177363Sgblack@eecs.umich.edu 6187363Sgblack@eecs.umich.edu # Trailer 6197363Sgblack@eecs.umich.edu code(''' 6207363Sgblack@eecs.umich.edu default: 6217363Sgblack@eecs.umich.edu panic("Invalid range for type ${{self.c_ident}}"); 6227363Sgblack@eecs.umich.edu } 6237363Sgblack@eecs.umich.edu} 6247363Sgblack@eecs.umich.edu 6257363Sgblack@eecs.umich.edu// Code to convert from a string to the enumeration 6267363Sgblack@eecs.umich.edu${{self.c_ident}} 6277363Sgblack@eecs.umich.edustring_to_${{self.c_ident}}(const string& str) 6287363Sgblack@eecs.umich.edu{ 6297363Sgblack@eecs.umich.edu''') 6307363Sgblack@eecs.umich.edu 6317363Sgblack@eecs.umich.edu # For each field 6327363Sgblack@eecs.umich.edu start = "" 6337363Sgblack@eecs.umich.edu code.indent() 634 for enum in self.enums.itervalues(): 635 code('${start}if (str == "${{enum.ident}}") {') 636 code(' return ${{self.c_ident}}_${{enum.ident}};') 637 start = "} else " 638 code.dedent() 639 640 code(''' 641 } else { 642 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 643 } 644} 645 646// Code to increment an enumeration type 647${{self.c_ident}}& 648operator++(${{self.c_ident}}& e) 649{ 650 assert(e < ${{self.c_ident}}_NUM); 651 return e = ${{self.c_ident}}(e+1); 652} 653''') 654 655 # MachineType hack used to set the base level and number of 656 # components for each Machine 657 if self.isMachineType: 658 code(''' 659/** \\brief returns the base vector index for each machine type to be 660 * used by NetDest 661 * 662 * \\return the base vector index for each machine type to be used by NetDest 663 * \\see NetDest.hh 664 */ 665int 666${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 667{ 668 switch(obj) { 669''') 670 671 # For each field 672 code.indent() 673 for i,enum in enumerate(self.enums.itervalues()): 674 code(' case ${{self.c_ident}}_${{enum.ident}}:') 675 code(' return $i;') 676 code.dedent() 677 678 # total num 679 code(''' 680 case ${{self.c_ident}}_NUM: 681 return ${{len(self.enums)}}; 682 683 default: 684 panic("Invalid range for type ${{self.c_ident}}"); 685 } 686} 687 688/** \\brief returns the machine type for each base vector index used by NetDest 689 * 690 * \\return the MachineType 691 */ 692MachineType 693${{self.c_ident}}_from_base_level(int type) 694{ 695 switch(type) { 696''') 697 698 # For each field 699 code.indent() 700 for i,enum in enumerate(self.enums.itervalues()): 701 code(' case $i:') 702 code(' return ${{self.c_ident}}_${{enum.ident}};') 703 code.dedent() 704 705 # Trailer 706 code(''' 707 default: 708 panic("Invalid range for type ${{self.c_ident}}"); 709 } 710} 711 712/** \\brief The return value indicates the number of components created 713 * before a particular machine\'s components 714 * 715 * \\return the base number of components for each machine 716 */ 717int 718${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 719{ 720 int base = 0; 721 switch(obj) { 722''') 723 724 # For each field 725 code.indent() 726 code(' case ${{self.c_ident}}_NUM:') 727 for enum in reversed(self.enums.values()): 728 # Check if there is a defined machine with this type 729 if enum.primary: 730 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 731 else: 732 code(' base += 0;') 733 code(' M5_FALLTHROUGH;') 734 code(' case ${{self.c_ident}}_${{enum.ident}}:') 735 code(' break;') 736 code.dedent() 737 738 code(''' 739 default: 740 panic("Invalid range for type ${{self.c_ident}}"); 741 } 742 743 return base; 744} 745 746/** \\brief returns the total number of components for each machine 747 * \\return the total number of components for each machine 748 */ 749int 750${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 751{ 752 switch(obj) { 753''') 754 755 # For each field 756 for enum in self.enums.itervalues(): 757 code('case ${{self.c_ident}}_${{enum.ident}}:') 758 if enum.primary: 759 code('return ${{enum.ident}}_Controller::getNumControllers();') 760 else: 761 code('return 0;') 762 763 # total num 764 code(''' 765 case ${{self.c_ident}}_NUM: 766 default: 767 panic("Invalid range for type ${{self.c_ident}}"); 768 } 769} 770''') 771 772 for enum in self.enums.itervalues(): 773 code(''' 774 775MachineID 776get${{enum.ident}}MachineID(NodeID RubyNode) 777{ 778 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 779 return mach; 780} 781''') 782 783 # Write the file 784 code.write(path, "%s.cc" % self.c_ident) 785 786__all__ = [ "Type" ] 787