Type.py revision 6862:3d308cbd1657
14403Srdreslin@umich.edu# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 21693Sstever@eecs.umich.edu# Copyright (c) 2009 The Hewlett-Packard Development Company 31693Sstever@eecs.umich.edu# All rights reserved. 41693Sstever@eecs.umich.edu# 51693Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 61693Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are 71693Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright 81693Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 91693Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 101693Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 111693Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution; 121693Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its 131693Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from 141693Sstever@eecs.umich.edu# this software without specific prior written permission. 151693Sstever@eecs.umich.edu# 161693Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171693Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181693Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191693Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201693Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211693Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221693Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231693Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241693Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251693Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261693Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271693Sstever@eecs.umich.edu 281693Sstever@eecs.umich.edufrom m5.util import code_formatter, orderdict 293358Srdreslin@umich.edu 303358Srdreslin@umich.edufrom slicc.util import PairContainer 311516SN/Afrom slicc.symbols.Symbol import Symbol 326654Snate@binkert.org 336654Snate@binkert.orgclass DataMember(PairContainer): 346654Snate@binkert.org def __init__(self, ident, type, pairs, init_code): 356654Snate@binkert.org super(DataMember, self).__init__(pairs) 363358Srdreslin@umich.edu self.ident = ident 373358Srdreslin@umich.edu self.type = type 386654Snate@binkert.org self.init_code = init_code 396654Snate@binkert.org 401516SN/Aclass Enumeration(PairContainer): 413358Srdreslin@umich.edu def __init__(self, ident, pairs): 423358Srdreslin@umich.edu super(Enumeration, self).__init__(pairs) 433358Srdreslin@umich.edu self.ident = ident 443358Srdreslin@umich.edu 453358Srdreslin@umich.educlass Method(object): 463358Srdreslin@umich.edu def __init__(self, return_type, param_types): 473358Srdreslin@umich.edu self.return_type = return_type 483358Srdreslin@umich.edu self.param_types = param_types 493358Srdreslin@umich.edu 503358Srdreslin@umich.educlass Type(Symbol): 513358Srdreslin@umich.edu def __init__(self, table, ident, location, pairs, machine=None): 523358Srdreslin@umich.edu super(Type, self).__init__(table, ident, location, pairs) 533360Srdreslin@umich.edu self.c_ident = ident 543358Srdreslin@umich.edu if machine: 553360Srdreslin@umich.edu if self.isExternal or self.isPrimitive: 563360Srdreslin@umich.edu if "external_name" in self: 573360Srdreslin@umich.edu self.c_ident = self["external_name"] 585255Ssaidi@eecs.umich.edu else: 593360Srdreslin@umich.edu # Append with machine name 603360Srdreslin@umich.edu self.c_ident = "%s_%s" % (machine, ident) 613360Srdreslin@umich.edu 625255Ssaidi@eecs.umich.edu self.pairs.setdefault("desc", "No description avaliable") 633358Srdreslin@umich.edu 644403Srdreslin@umich.edu # check for interface that this Type implements 653360Srdreslin@umich.edu if "interface" in self: 663358Srdreslin@umich.edu interface = self["interface"] 673358Srdreslin@umich.edu if interface in ("Message", "NetworkMessage"): 683358Srdreslin@umich.edu self["message"] = "yes" 693358Srdreslin@umich.edu if interface == "NetworkMessage": 703358Srdreslin@umich.edu self["networkmessage"] = "yes" 713358Srdreslin@umich.edu 723358Srdreslin@umich.edu # FIXME - all of the following id comparisons are fragile hacks 733358Srdreslin@umich.edu if self.ident in ("CacheMemory", "NewCacheMemory", 743358Srdreslin@umich.edu "TLCCacheMemory", "DNUCACacheMemory", 753360Srdreslin@umich.edu "DNUCABankCacheMemory", "L2BankCacheMemory", 763360Srdreslin@umich.edu "CompressedCacheMemory", "PrefetchCacheMemory"): 773360Srdreslin@umich.edu self["cache"] = "yes" 783360Srdreslin@umich.edu 793358Srdreslin@umich.edu if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"): 803358Srdreslin@umich.edu self["tbe"] = "yes" 813358Srdreslin@umich.edu 823358Srdreslin@umich.edu if self.ident == "NewTBETable": 834403Srdreslin@umich.edu self["newtbe"] = "yes" 844403Srdreslin@umich.edu 855256Ssaidi@eecs.umich.edu if self.ident == "TimerTable": 865255Ssaidi@eecs.umich.edu self["timer"] = "yes" 873358Srdreslin@umich.edu 883358Srdreslin@umich.edu if self.ident == "DirectoryMemory": 894403Srdreslin@umich.edu self["dir"] = "yes" 904403Srdreslin@umich.edu 915255Ssaidi@eecs.umich.edu if self.ident == "PersistentTable": 923358Srdreslin@umich.edu self["persistent"] = "yes" 933358Srdreslin@umich.edu 944403Srdreslin@umich.edu if self.ident == "Prefetcher": 955255Ssaidi@eecs.umich.edu self["prefetcher"] = "yes" 964403Srdreslin@umich.edu 973358Srdreslin@umich.edu if self.ident == "DNUCA_Movement": 983358Srdreslin@umich.edu self["mover"] = "yes" 994403Srdreslin@umich.edu 1005255Ssaidi@eecs.umich.edu self.isMachineType = (ident == "MachineType") 1014403Srdreslin@umich.edu 1023358Srdreslin@umich.edu self.data_members = orderdict() 1033358Srdreslin@umich.edu 1044403Srdreslin@umich.edu # Methods 1055255Ssaidi@eecs.umich.edu self.methods = {} 1064403Srdreslin@umich.edu 1073358Srdreslin@umich.edu # Enums 1083358Srdreslin@umich.edu self.enums = orderdict() 1094403Srdreslin@umich.edu 1105255Ssaidi@eecs.umich.edu @property 1114403Srdreslin@umich.edu def isPrimitive(self): 1124403Srdreslin@umich.edu return "primitive" in self 1133358Srdreslin@umich.edu @property 1143358Srdreslin@umich.edu def isNetworkMessage(self): 1154403Srdreslin@umich.edu return "networkmessage" in self 1165255Ssaidi@eecs.umich.edu @property 1174403Srdreslin@umich.edu def isMessage(self): 1184403Srdreslin@umich.edu return "message" in self 1194403Srdreslin@umich.edu @property 1203360Srdreslin@umich.edu def isBuffer(self): 1214403Srdreslin@umich.edu return "buffer" in self 1223358Srdreslin@umich.edu @property 1233358Srdreslin@umich.edu def isInPort(self): 1244403Srdreslin@umich.edu return "inport" in self 1255255Ssaidi@eecs.umich.edu @property 1264403Srdreslin@umich.edu def isOutPort(self): 1273358Srdreslin@umich.edu return "outport" in self 1283358Srdreslin@umich.edu @property 1294403Srdreslin@umich.edu def isEnumeration(self): 1305255Ssaidi@eecs.umich.edu return "enumeration" in self 1314403Srdreslin@umich.edu @property 1323358Srdreslin@umich.edu def isExternal(self): 1333358Srdreslin@umich.edu return "external" in self 1344403Srdreslin@umich.edu @property 1355256Ssaidi@eecs.umich.edu def isGlobal(self): 1365255Ssaidi@eecs.umich.edu return "global" in self 1374403Srdreslin@umich.edu @property 1383358Srdreslin@umich.edu def isInterface(self): 1393358Srdreslin@umich.edu return "interface" in self 1404403Srdreslin@umich.edu 1415255Ssaidi@eecs.umich.edu # Return false on error 1424403Srdreslin@umich.edu def dataMemberAdd(self, ident, type, pairs, init_code): 1434403Srdreslin@umich.edu if ident in self.data_members: 1444403Srdreslin@umich.edu return False 1453360Srdreslin@umich.edu 1464403Srdreslin@umich.edu member = DataMember(ident, type, pairs, init_code) 1473358Srdreslin@umich.edu self.data_members[ident] = member 1483358Srdreslin@umich.edu 1494403Srdreslin@umich.edu return True 1505255Ssaidi@eecs.umich.edu 1514403Srdreslin@umich.edu def dataMemberType(self, ident): 1524403Srdreslin@umich.edu return self.data_members[ident].type 1534403Srdreslin@umich.edu 1543360Srdreslin@umich.edu def methodId(self, name, param_type_vec): 1554403Srdreslin@umich.edu return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 1563358Srdreslin@umich.edu 1573358Srdreslin@umich.edu def methodAdd(self, name, return_type, param_type_vec): 1583358Srdreslin@umich.edu ident = self.methodId(name, param_type_vec) 1593358Srdreslin@umich.edu if ident in self.methods: 1603358Srdreslin@umich.edu return False 1613358Srdreslin@umich.edu 1623358Srdreslin@umich.edu self.methods[ident] = Method(return_type, param_type_vec) 1633358Srdreslin@umich.edu return True 1643358Srdreslin@umich.edu 1653358Srdreslin@umich.edu def enumAdd(self, ident, pairs): 1663358Srdreslin@umich.edu if ident in self.enums: 1673358Srdreslin@umich.edu return False 1683358Srdreslin@umich.edu 1693358Srdreslin@umich.edu self.enums[ident] = Enumeration(ident, pairs) 1703358Srdreslin@umich.edu 1713358Srdreslin@umich.edu # Add default 1723358Srdreslin@umich.edu if "default" not in self: 1733358Srdreslin@umich.edu self["default"] = "%s_NUM" % self.c_ident 1743358Srdreslin@umich.edu 1753358Srdreslin@umich.edu return True 1763358Srdreslin@umich.edu 1773358Srdreslin@umich.edu def writeCodeFiles(self, path): 1783358Srdreslin@umich.edu if self.isExternal: 1793358Srdreslin@umich.edu # Do nothing 1803358Srdreslin@umich.edu pass 1813358Srdreslin@umich.edu elif self.isEnumeration: 1823358Srdreslin@umich.edu self.printEnumHH(path) 1833358Srdreslin@umich.edu self.printEnumCC(path) 1843358Srdreslin@umich.edu else: 1853358Srdreslin@umich.edu # User defined structs and messages 1863358Srdreslin@umich.edu self.printTypeHH(path) 1873358Srdreslin@umich.edu self.printTypeCC(path) 1883358Srdreslin@umich.edu 1893358Srdreslin@umich.edu def printTypeHH(self, path): 1903358Srdreslin@umich.edu code = code_formatter() 1913358Srdreslin@umich.edu code(''' 1921516SN/A/** \\file ${{self.c_ident}}.hh 1933358Srdreslin@umich.edu * 1943358Srdreslin@umich.edu * 1953358Srdreslin@umich.edu * Auto generated C++ code started by $__file__:$__line__ 1961516SN/A */ 1973358Srdreslin@umich.edu 1983358Srdreslin@umich.edu#ifndef ${{self.c_ident}}_H 1993358Srdreslin@umich.edu#define ${{self.c_ident}}_H 2003358Srdreslin@umich.edu 2013358Srdreslin@umich.edu#include "mem/ruby/common/Global.hh" 2021516SN/A#include "mem/gems_common/Allocator.hh" 2033358Srdreslin@umich.edu''') 2043358Srdreslin@umich.edu 2053358Srdreslin@umich.edu for dm in self.data_members.values(): 2063358Srdreslin@umich.edu if not dm.type.isPrimitive: 2073358Srdreslin@umich.edu code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 2083358Srdreslin@umich.edu 2093358Srdreslin@umich.edu parent = "" 2103358Srdreslin@umich.edu if "interface" in self: 2113358Srdreslin@umich.edu code('#include "mem/protocol/$0.hh"', self["interface"]) 2123358Srdreslin@umich.edu parent = " : public %s" % self["interface"] 2133358Srdreslin@umich.edu 2143358Srdreslin@umich.edu code(''' 2153358Srdreslin@umich.edu$klass ${{self.c_ident}}$parent { 2163358Srdreslin@umich.edu public: 2173358Srdreslin@umich.edu ${{self.c_ident}}() 2183358Srdreslin@umich.edu''', klass="class") 2193358Srdreslin@umich.edu 2203358Srdreslin@umich.edu # Call superclass constructor 2217876Sgblack@eecs.umich.edu if "interface" in self: 2223358Srdreslin@umich.edu code(' : ${{self["interface"]}}()') 2233358Srdreslin@umich.edu 2243358Srdreslin@umich.edu code.indent() 2253358Srdreslin@umich.edu code("{") 2263358Srdreslin@umich.edu if not self.isGlobal: 2273358Srdreslin@umich.edu code.indent() 2283358Srdreslin@umich.edu for dm in self.data_members.values(): 2293358Srdreslin@umich.edu ident = dm.ident 2303358Srdreslin@umich.edu if "default" in dm: 2313358Srdreslin@umich.edu # look for default value 2323358Srdreslin@umich.edu code('m_$ident = ${{dm["default"]}}; // default for this field') 2333358Srdreslin@umich.edu elif "default" in dm.type: 2343358Srdreslin@umich.edu # Look for the type default 2353358Srdreslin@umich.edu tid = dm.type.c_ident 2363358Srdreslin@umich.edu code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 2373358Srdreslin@umich.edu else: 2383358Srdreslin@umich.edu code('// m_$ident has no default') 2393358Srdreslin@umich.edu code.dedent() 2403358Srdreslin@umich.edu code('}') 2413358Srdreslin@umich.edu 2423358Srdreslin@umich.edu # ******** Default destructor ******** 2433358Srdreslin@umich.edu code('~${{self.c_ident}}() { };') 2443358Srdreslin@umich.edu 2453358Srdreslin@umich.edu # ******** Full init constructor ******** 2463358Srdreslin@umich.edu if not self.isGlobal: 2473358Srdreslin@umich.edu params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 2483358Srdreslin@umich.edu for dm in self.data_members.itervalues() ] 2493358Srdreslin@umich.edu 2503358Srdreslin@umich.edu if self.isMessage: 2513358Srdreslin@umich.edu params.append('const unsigned local_proc_id') 2523358Srdreslin@umich.edu 2533358Srdreslin@umich.edu params = ', '.join(params) 2543358Srdreslin@umich.edu code('${{self.c_ident}}($params)') 2553358Srdreslin@umich.edu 2563358Srdreslin@umich.edu # Call superclass constructor 2571516SN/A if "interface" in self: 2585256Ssaidi@eecs.umich.edu code(' : ${{self["interface"]}}()') 2595256Ssaidi@eecs.umich.edu 2605256Ssaidi@eecs.umich.edu code('{') 2615256Ssaidi@eecs.umich.edu code.indent() 2623358Srdreslin@umich.edu for dm in self.data_members.values(): 2633358Srdreslin@umich.edu code('m_${{dm.ident}} = local_${{dm.ident}};') 2643358Srdreslin@umich.edu if "nextLineCallHack" in dm: 2653358Srdreslin@umich.edu code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};') 2663358Srdreslin@umich.edu 2673358Srdreslin@umich.edu if self.isMessage: 2683358Srdreslin@umich.edu code('proc_id = local_proc_id;') 2693358Srdreslin@umich.edu 2703358Srdreslin@umich.edu code.dedent() 2713358Srdreslin@umich.edu code('}') 2723358Srdreslin@umich.edu 2733358Srdreslin@umich.edu # create a static factory method 2743358Srdreslin@umich.edu if "interface" in self: 2753358Srdreslin@umich.edu code(''' 2763358Srdreslin@umich.edustatic ${{self["interface"]}}* create() { 2773358Srdreslin@umich.edu return new ${{self.c_ident}}(); 2787525Ssteve.reinhardt@amd.com} 2793358Srdreslin@umich.edu''') 2803358Srdreslin@umich.edu 2813358Srdreslin@umich.edu # ******** Message member functions ******** 2823358Srdreslin@umich.edu # FIXME: those should be moved into slicc file, slicc should 2833358Srdreslin@umich.edu # support more of the c++ class inheritance 2843646Srdreslin@umich.edu 2853358Srdreslin@umich.edu if self.isMessage: 2863358Srdreslin@umich.edu code(''' 2873358Srdreslin@umich.eduMessage* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); } 288void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); } 289static Allocator<${{self.c_ident}}>* s_allocator_ptr; 290static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }} 291''') 292 293 if not self.isGlobal: 294 # const Get methods for each field 295 code('// Const accessors methods for each field') 296 for dm in self.data_members.values(): 297 code(''' 298/** \\brief Const accessor method for ${{dm.ident}} field. 299 * \\return ${{dm.ident}} field 300 */ 301const ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; } 302''') 303 304 # Non-const Get methods for each field 305 code('// Non const Accessors methods for each field') 306 for dm in self.data_members.values(): 307 code(''' 308/** \\brief Non-const accessor method for ${{dm.ident}} field. 309 * \\return ${{dm.ident}} field 310 */ 311${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; } 312''') 313 314 #Set methods for each field 315 code('// Mutator methods for each field') 316 for dm in self.data_members.values(): 317 code(''' 318/** \\brief Mutator method for ${{dm.ident}} field */ 319void set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; } 320''') 321 322 code('void print(ostream& out) const;') 323 code.dedent() 324 code(' //private:') 325 code.indent() 326 327 # Data members for each field 328 for dm in self.data_members.values(): 329 if "abstract" not in dm: 330 const = "" 331 init = "" 332 333 # global structure 334 if self.isGlobal: 335 const = "static const " 336 337 # init value 338 if dm.init_code: 339 # only global structure can have init value here 340 assert self.isGlobal 341 init = " = %s" % (dm.init_code) 342 343 desc = "" 344 if "desc" in dm: 345 desc = '/**< %s */' % dm["desc"] 346 347 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc') 348 349 if self.isMessage: 350 code('unsigned proc_id;') 351 352 code.dedent() 353 code('};') 354 355 code(''' 356// Output operator declaration 357ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj); 358 359// Output operator definition 360extern inline 361ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj) 362{ 363 obj.print(out); 364 out << flush; 365 return out; 366} 367 368#endif // ${{self.c_ident}}_H 369''') 370 371 code.write(path, "%s.hh" % self.c_ident) 372 373 def printTypeCC(self, path): 374 code = code_formatter() 375 376 code(''' 377/** \\file ${{self.c_ident}}.cc 378 * 379 * Auto generated C++ code started by $__file__:$__line__ 380 */ 381 382#include "mem/protocol/${{self.c_ident}}.hh" 383''') 384 385 if self.isMessage: 386 code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;') 387 code(''' 388/** \\brief Print the state of this object */ 389void ${{self.c_ident}}::print(ostream& out) const 390{ 391 out << "[${{self.c_ident}}: "; 392''') 393 394 # For each field 395 code.indent() 396 for dm in self.data_members.values(): 397 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 398 399 if self.isMessage: 400 code('out << "Time = " << getTime() << " ";') 401 code.dedent() 402 403 # Trailer 404 code(''' 405 out << "]"; 406}''') 407 408 code.write(path, "%s.cc" % self.c_ident) 409 410 def printEnumHH(self, path): 411 code = code_formatter() 412 code(''' 413/** \\file ${{self.c_ident}}.hh 414 * 415 * Auto generated C++ code started by $__file__:$__line__ 416 */ 417#ifndef ${{self.c_ident}}_H 418#define ${{self.c_ident}}_H 419 420#include "mem/ruby/common/Global.hh" 421 422/** \\enum ${{self.c_ident}} 423 * \\brief ${{self.desc}} 424 */ 425enum ${{self.c_ident}} { 426 ${{self.c_ident}}_FIRST, 427''') 428 429 code.indent() 430 # For each field 431 for i,(ident,enum) in enumerate(self.enums.iteritems()): 432 desc = enum.get("desc", "No description avaliable") 433 if i == 0: 434 init = ' = %s_FIRST' % self.c_ident 435 else: 436 init = '' 437 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 438 code.dedent() 439 code(''' 440 ${{self.c_ident}}_NUM 441}; 442${{self.c_ident}} string_to_${{self.c_ident}}(const string& str); 443string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 444${{self.c_ident}} &operator++(${{self.c_ident}} &e); 445''') 446 447 # MachineType hack used to set the base component id for each Machine 448 if self.isMachineType: 449 code(''' 450int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 451MachineType ${{self.c_ident}}_from_base_level(int); 452int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 453int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 454''') 455 456 for enum in self.enums.itervalues(): 457 code('#define MACHINETYPE_${{enum.ident}} 1') 458 459 # Trailer 460 code(''' 461ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj); 462 463#endif // ${{self.c_ident}}_H 464''') 465 466 code.write(path, "%s.hh" % self.c_ident) 467 468 def printEnumCC(self, path): 469 code = code_formatter() 470 code(''' 471/** \\file ${{self.c_ident}}.hh 472 * 473 * Auto generated C++ code started by $__file__:$__line__ 474 */ 475 476#include "mem/protocol/${{self.c_ident}}.hh" 477 478''') 479 480 if self.isMachineType: 481 code('#include "mem/protocol/ControllerFactory.hh"') 482 for enum in self.enums.itervalues(): 483 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 484 485 code(''' 486ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj) 487{ 488 out << ${{self.c_ident}}_to_string(obj); 489 out << flush; 490 return out; 491} 492 493string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 494{ 495 switch(obj) { 496''') 497 498 # For each field 499 code.indent() 500 for enum in self.enums.itervalues(): 501 code(' case ${{self.c_ident}}_${{enum.ident}}:') 502 code(' return "${{enum.ident}}";') 503 code.dedent() 504 505 # Trailer 506 code(''' 507 default: 508 ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 509 return ""; 510 } 511} 512 513${{self.c_ident}} string_to_${{self.c_ident}}(const string& str) 514{ 515''') 516 517 # For each field 518 code.indent() 519 code("if (false) {") 520 start = "} else " 521 for enum in self.enums.itervalues(): 522 code('${start}if (str == "${{enum.ident}}") {') 523 code(' return ${{self.c_ident}}_${{enum.ident}};') 524 code.dedent() 525 526 code(''' 527 } else { 528 WARN_EXPR(str); 529 ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}"); 530 } 531} 532 533${{self.c_ident}}& operator++(${{self.c_ident}}& e) { 534 assert(e < ${{self.c_ident}}_NUM); 535 return e = ${{self.c_ident}}(e+1); 536} 537''') 538 539 # MachineType hack used to set the base level and number of 540 # components for each Machine 541 if self.isMachineType: 542 code(''' 543/** \\brief returns the base vector index for each machine type to be used by NetDest 544 * 545 * \\return the base vector index for each machine type to be used by NetDest 546 * \\see NetDest.hh 547 */ 548int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 549{ 550 switch(obj) { 551''') 552 553 # For each field 554 code.indent() 555 for i,enum in enumerate(self.enums.itervalues()): 556 code(' case ${{self.c_ident}}_${{enum.ident}}:') 557 code(' return $i;') 558 code.dedent() 559 560 # total num 561 code(''' 562 case ${{self.c_ident}}_NUM: 563 return ${{len(self.enums)}}; 564 565 default: 566 ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 567 return -1; 568 } 569} 570 571/** \\brief returns the machine type for each base vector index used by NetDest 572 * 573 * \\return the MachineTYpe 574 */ 575MachineType ${{self.c_ident}}_from_base_level(int type) 576{ 577 switch(type) { 578''') 579 580 # For each field 581 code.indent() 582 for i,enum in enumerate(self.enums.itervalues()): 583 code(' case $i:') 584 code(' return ${{self.c_ident}}_${{enum.ident}};') 585 code.dedent() 586 587 # Trailer 588 code(''' 589 default: 590 ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 591 return MachineType_NUM; 592 } 593} 594 595/** \\brief The return value indicates the number of components created 596 * before a particular machine\'s components 597 * 598 * \\return the base number of components for each machine 599 */ 600int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 601{ 602 int base = 0; 603 switch(obj) { 604''') 605 606 # For each field 607 code.indent() 608 code(' case ${{self.c_ident}}_NUM:') 609 for enum in reversed(self.enums.values()): 610 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 611 code(' case ${{self.c_ident}}_${{enum.ident}}:') 612 code(' break;') 613 code.dedent() 614 615 code(''' 616 default: 617 ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 618 return -1; 619 } 620 621 return base; 622} 623 624/** \\brief returns the total number of components for each machine 625 * \\return the total number of components for each machine 626 */ 627int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 628{ 629 switch(obj) { 630''') 631 632 # For each field 633 for enum in self.enums.itervalues(): 634 code(''' 635 case ${{self.c_ident}}_${{enum.ident}}: 636 return ${{enum.ident}}_Controller::getNumControllers(); 637''') 638 639 # total num 640 code(''' 641 case ${{self.c_ident}}_NUM: 642 default: 643 ERROR_MSG("Invalid range for type ${{self.c_ident}}"); 644 return -1; 645 } 646} 647''') 648 649 # Write the file 650 code.write(path, "%s.cc" % self.c_ident) 651 652__all__ = [ "Type" ] 653