Type.py revision 8602
14120Sgblack@eecs.umich.edu# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 24120Sgblack@eecs.umich.edu# Copyright (c) 2009 The Hewlett-Packard Development Company 34120Sgblack@eecs.umich.edu# All rights reserved. 44120Sgblack@eecs.umich.edu# 57087Snate@binkert.org# Redistribution and use in source and binary forms, with or without 67087Snate@binkert.org# modification, are permitted provided that the following conditions are 77087Snate@binkert.org# met: redistributions of source code must retain the above copyright 87087Snate@binkert.org# notice, this list of conditions and the following disclaimer; 97087Snate@binkert.org# redistributions in binary form must reproduce the above copyright 107087Snate@binkert.org# notice, this list of conditions and the following disclaimer in the 117087Snate@binkert.org# documentation and/or other materials provided with the distribution; 127087Snate@binkert.org# neither the name of the copyright holders nor the names of its 134120Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 147087Snate@binkert.org# this software without specific prior written permission. 157087Snate@binkert.org# 167087Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177087Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187087Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197087Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207087Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217087Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224120Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237087Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244120Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254120Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264120Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274120Sgblack@eecs.umich.edu 284120Sgblack@eecs.umich.edufrom m5.util import orderdict 294120Sgblack@eecs.umich.edu 304120Sgblack@eecs.umich.edufrom slicc.util import PairContainer 314120Sgblack@eecs.umich.edufrom slicc.symbols.Symbol import Symbol 324120Sgblack@eecs.umich.edu 334120Sgblack@eecs.umich.educlass DataMember(PairContainer): 344120Sgblack@eecs.umich.edu def __init__(self, ident, type, pairs, init_code): 354120Sgblack@eecs.umich.edu super(DataMember, self).__init__(pairs) 364120Sgblack@eecs.umich.edu self.ident = ident 374120Sgblack@eecs.umich.edu self.type = type 384120Sgblack@eecs.umich.edu self.init_code = init_code 394120Sgblack@eecs.umich.edu 404120Sgblack@eecs.umich.educlass Enumeration(PairContainer): 414120Sgblack@eecs.umich.edu def __init__(self, ident, pairs): 424120Sgblack@eecs.umich.edu super(Enumeration, self).__init__(pairs) 434166Sgblack@eecs.umich.edu self.ident = ident 444166Sgblack@eecs.umich.edu 458229Snate@binkert.orgclass Method(object): 4612044Sgabeblack@google.com def __init__(self, return_type, param_types): 4711854Sbrandon.potter@amd.com self.return_type = return_type 484166Sgblack@eecs.umich.edu self.param_types = param_types 494120Sgblack@eecs.umich.edu 505956Sgblack@eecs.umich.educlass Type(Symbol): 515956Sgblack@eecs.umich.edu def __init__(self, table, ident, location, pairs, machine=None): 524120Sgblack@eecs.umich.edu super(Type, self).__init__(table, ident, location, pairs) 534120Sgblack@eecs.umich.edu self.c_ident = ident 547073Sgblack@eecs.umich.edu self.abstract_ident = "" 557073Sgblack@eecs.umich.edu if machine: 567073Sgblack@eecs.umich.edu if self.isExternal or self.isPrimitive: 577073Sgblack@eecs.umich.edu if "external_name" in self: 584166Sgblack@eecs.umich.edu self.c_ident = self["external_name"] 5911851Sbrandon.potter@amd.com else: 604166Sgblack@eecs.umich.edu # Append with machine name 614166Sgblack@eecs.umich.edu self.c_ident = "%s_%s" % (machine, ident) 625962Sgblack@eecs.umich.edu 635962Sgblack@eecs.umich.edu self.pairs.setdefault("desc", "No description avaliable") 645962Sgblack@eecs.umich.edu 655956Sgblack@eecs.umich.edu # check for interface that this Type implements 665956Sgblack@eecs.umich.edu if "interface" in self: 674166Sgblack@eecs.umich.edu interface = self["interface"] 6811851Sbrandon.potter@amd.com if interface in ("Message", "NetworkMessage"): 6911851Sbrandon.potter@amd.com self["message"] = "yes" 705956Sgblack@eecs.umich.edu if interface == "NetworkMessage": 715956Sgblack@eecs.umich.edu self["networkmessage"] = "yes" 725973Sgblack@eecs.umich.edu 7311884Sbrandon.potter@amd.com # FIXME - all of the following id comparisons are fragile hacks 744166Sgblack@eecs.umich.edu if self.ident in ("CacheMemory", "NewCacheMemory", 754166Sgblack@eecs.umich.edu "TLCCacheMemory", "DNUCACacheMemory", 765962Sgblack@eecs.umich.edu "DNUCABankCacheMemory", "L2BankCacheMemory", 775962Sgblack@eecs.umich.edu "CompressedCacheMemory", "PrefetchCacheMemory"): 7811320Ssteve.reinhardt@amd.com self["cache"] = "yes" 795962Sgblack@eecs.umich.edu 805962Sgblack@eecs.umich.edu if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"): 815962Sgblack@eecs.umich.edu self["tbe"] = "yes" 8212074Sspwilson2@wisc.edu 835958Sgblack@eecs.umich.edu if self.ident == "NewTBETable": 8412074Sspwilson2@wisc.edu self["newtbe"] = "yes" 8512074Sspwilson2@wisc.edu 8611886Sbrandon.potter@amd.com if self.ident == "TimerTable": 8711886Sbrandon.potter@amd.com self["timer"] = "yes" 8811886Sbrandon.potter@amd.com 8911886Sbrandon.potter@amd.com if self.ident == "DirectoryMemory": 9011886Sbrandon.potter@amd.com self["dir"] = "yes" 9111886Sbrandon.potter@amd.com 9211886Sbrandon.potter@amd.com if self.ident == "PersistentTable": 9311886Sbrandon.potter@amd.com self["persistent"] = "yes" 9411886Sbrandon.potter@amd.com 9511886Sbrandon.potter@amd.com if self.ident == "Prefetcher": 9611886Sbrandon.potter@amd.com self["prefetcher"] = "yes" 9711886Sbrandon.potter@amd.com 9811886Sbrandon.potter@amd.com if self.ident == "DNUCA_Movement": 9911886Sbrandon.potter@amd.com self["mover"] = "yes" 10011886Sbrandon.potter@amd.com 1015956Sgblack@eecs.umich.edu self.isMachineType = (ident == "MachineType") 1024166Sgblack@eecs.umich.edu 10311851Sbrandon.potter@amd.com self.isStateDecl = ("state_decl" in self) 1045956Sgblack@eecs.umich.edu self.statePermPairs = [] 1055956Sgblack@eecs.umich.edu 10611851Sbrandon.potter@amd.com self.data_members = orderdict() 10711851Sbrandon.potter@amd.com 1084166Sgblack@eecs.umich.edu # Methods 1096709Svince@csl.cornell.edu self.methods = {} 1106709Svince@csl.cornell.edu 1116709Svince@csl.cornell.edu # Enums 1126709Svince@csl.cornell.edu self.enums = orderdict() 1136709Svince@csl.cornell.edu 1146709Svince@csl.cornell.edu @property 1156709Svince@csl.cornell.edu def isPrimitive(self): 11611886Sbrandon.potter@amd.com return "primitive" in self 11711886Sbrandon.potter@amd.com @property 11811886Sbrandon.potter@amd.com def isNetworkMessage(self): 11911886Sbrandon.potter@amd.com return "networkmessage" in self 12011886Sbrandon.potter@amd.com @property 12111886Sbrandon.potter@amd.com def isMessage(self): 12211886Sbrandon.potter@amd.com return "message" in self 12311886Sbrandon.potter@amd.com @property 12411886Sbrandon.potter@amd.com def isBuffer(self): 12511886Sbrandon.potter@amd.com return "buffer" in self 12611886Sbrandon.potter@amd.com @property 12711886Sbrandon.potter@amd.com def isInPort(self): 12811886Sbrandon.potter@amd.com return "inport" in self 12911886Sbrandon.potter@amd.com @property 1306709Svince@csl.cornell.edu def isOutPort(self): 1316709Svince@csl.cornell.edu return "outport" in self 1326709Svince@csl.cornell.edu @property 1335956Sgblack@eecs.umich.edu def isEnumeration(self): 13411884Sbrandon.potter@amd.com return "enumeration" in self 13512074Sspwilson2@wisc.edu @property 1365958Sgblack@eecs.umich.edu def isExternal(self): 13712074Sspwilson2@wisc.edu return "external" in self 1389552Sandreas.hansson@arm.com @property 13911851Sbrandon.potter@amd.com def isGlobal(self): 14012074Sspwilson2@wisc.edu return "global" in self 14112074Sspwilson2@wisc.edu @property 14211886Sbrandon.potter@amd.com def isInterface(self): 14311886Sbrandon.potter@amd.com return "interface" in self 1445956Sgblack@eecs.umich.edu 1455956Sgblack@eecs.umich.edu # Return false on error 14611851Sbrandon.potter@amd.com def dataMemberAdd(self, ident, type, pairs, init_code): 1475956Sgblack@eecs.umich.edu if ident in self.data_members: 1485956Sgblack@eecs.umich.edu return False 14911851Sbrandon.potter@amd.com 15011851Sbrandon.potter@amd.com member = DataMember(ident, type, pairs, init_code) 1515956Sgblack@eecs.umich.edu self.data_members[ident] = member 1525973Sgblack@eecs.umich.edu 1535973Sgblack@eecs.umich.edu return True 1545973Sgblack@eecs.umich.edu 1555973Sgblack@eecs.umich.edu def dataMemberType(self, ident): 1565973Sgblack@eecs.umich.edu return self.data_members[ident].type 1575973Sgblack@eecs.umich.edu 1585973Sgblack@eecs.umich.edu def methodId(self, name, param_type_vec): 15911886Sbrandon.potter@amd.com return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 16011886Sbrandon.potter@amd.com 16111886Sbrandon.potter@amd.com def methodIdAbstract(self, name, param_type_vec): 16211886Sbrandon.potter@amd.com return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 16311886Sbrandon.potter@amd.com 16411886Sbrandon.potter@amd.com def statePermPairAdd(self, state_name, perm_name): 16511886Sbrandon.potter@amd.com self.statePermPairs.append([state_name, perm_name]) 16611886Sbrandon.potter@amd.com 16711886Sbrandon.potter@amd.com def methodAdd(self, name, return_type, param_type_vec): 16811886Sbrandon.potter@amd.com ident = self.methodId(name, param_type_vec) 16911886Sbrandon.potter@amd.com if ident in self.methods: 17011886Sbrandon.potter@amd.com return False 17111886Sbrandon.potter@amd.com 17211886Sbrandon.potter@amd.com self.methods[ident] = Method(return_type, param_type_vec) 1735973Sgblack@eecs.umich.edu return True 1745973Sgblack@eecs.umich.edu 1755973Sgblack@eecs.umich.edu def enumAdd(self, ident, pairs): 1765956Sgblack@eecs.umich.edu if ident in self.enums: 17711884Sbrandon.potter@amd.com return False 17812074Sspwilson2@wisc.edu 1795958Sgblack@eecs.umich.edu self.enums[ident] = Enumeration(ident, pairs) 18012044Sgabeblack@google.com 18112044Sgabeblack@google.com # Add default 18212074Sspwilson2@wisc.edu if "default" not in self: 18312074Sspwilson2@wisc.edu self["default"] = "%s_NUM" % self.c_ident 18412074Sspwilson2@wisc.edu 18512074Sspwilson2@wisc.edu return True 18612074Sspwilson2@wisc.edu 18712074Sspwilson2@wisc.edu def writeCodeFiles(self, path): 18811886Sbrandon.potter@amd.com if self.isExternal: 18911886Sbrandon.potter@amd.com # Do nothing 1904166Sgblack@eecs.umich.edu pass 19110299Salexandru.dutu@amd.com elif self.isEnumeration: 19210299Salexandru.dutu@amd.com self.printEnumHH(path) 19310299Salexandru.dutu@amd.com self.printEnumCC(path) 19410299Salexandru.dutu@amd.com else: 19512044Sgabeblack@google.com # User defined structs and messages 19612044Sgabeblack@google.com self.printTypeHH(path) 19710299Salexandru.dutu@amd.com self.printTypeCC(path) 19810299Salexandru.dutu@amd.com 19910299Salexandru.dutu@amd.com def printTypeHH(self, path): 2004166Sgblack@eecs.umich.edu code = self.symtab.codeFormatter() 2014120Sgblack@eecs.umich.edu code(''' 2024120Sgblack@eecs.umich.edu/** \\file ${{self.c_ident}}.hh 203 * 204 * 205 * Auto generated C++ code started by $__file__:$__line__ 206 */ 207 208#ifndef __${{self.c_ident}}_HH__ 209#define __${{self.c_ident}}_HH__ 210 211#include <iostream> 212 213#include "mem/ruby/common/Global.hh" 214''') 215 216 for dm in self.data_members.values(): 217 if not dm.type.isPrimitive: 218 code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 219 220 parent = "" 221 if "interface" in self: 222 code('#include "mem/protocol/$0.hh"', self["interface"]) 223 parent = " : public %s" % self["interface"] 224 225 code(''' 226$klass ${{self.c_ident}}$parent 227{ 228 public: 229 ${{self.c_ident}}() 230 { 231''', klass="class") 232 233 code.indent() 234 if not self.isGlobal: 235 code.indent() 236 for dm in self.data_members.values(): 237 ident = dm.ident 238 if "default" in dm: 239 # look for default value 240 code('m_$ident = ${{dm["default"]}}; // default for this field') 241 elif "default" in dm.type: 242 # Look for the type default 243 tid = dm.type.c_ident 244 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 245 else: 246 code('// m_$ident has no default') 247 code.dedent() 248 code('}') 249 250 # ******** Copy constructor ******** 251 if not self.isGlobal: 252 code('${{self.c_ident}}(const ${{self.c_ident}}&other)') 253 254 # Call superclass constructor 255 if "interface" in self: 256 code(' : ${{self["interface"]}}(other)') 257 258 code('{') 259 code.indent() 260 261 for dm in self.data_members.values(): 262 code('m_${{dm.ident}} = other.m_${{dm.ident}};') 263 264 code.dedent() 265 code('}') 266 267 # ******** Full init constructor ******** 268 if not self.isGlobal: 269 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 270 for dm in self.data_members.itervalues() ] 271 272 params = ', '.join(params) 273 code('${{self.c_ident}}($params)') 274 275 # Call superclass constructor 276 if "interface" in self: 277 code(' : ${{self["interface"]}}()') 278 279 code('{') 280 code.indent() 281 for dm in self.data_members.values(): 282 code('m_${{dm.ident}} = local_${{dm.ident}};') 283 if "nextLineCallHack" in dm: 284 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};') 285 286 code.dedent() 287 code('}') 288 289 # create a static factory method and a clone member 290 code(''' 291static ${{self.c_ident}}* 292create() 293{ 294 return new ${{self.c_ident}}(); 295} 296 297${{self.c_ident}}* 298clone() const 299{ 300 return new ${{self.c_ident}}(*this); 301} 302''') 303 304 if not self.isGlobal: 305 # const Get methods for each field 306 code('// Const accessors methods for each field') 307 for dm in self.data_members.values(): 308 code(''' 309/** \\brief Const accessor method for ${{dm.ident}} field. 310 * \\return ${{dm.ident}} field 311 */ 312const ${{dm.type.c_ident}}& 313get${{dm.ident}}() const 314{ 315 return m_${{dm.ident}}; 316} 317''') 318 319 # Non-const Get methods for each field 320 code('// Non const Accessors methods for each field') 321 for dm in self.data_members.values(): 322 code(''' 323/** \\brief Non-const accessor method for ${{dm.ident}} field. 324 * \\return ${{dm.ident}} field 325 */ 326${{dm.type.c_ident}}& 327get${{dm.ident}}() 328{ 329 return m_${{dm.ident}}; 330} 331''') 332 333 #Set methods for each field 334 code('// Mutator methods for each field') 335 for dm in self.data_members.values(): 336 code(''' 337/** \\brief Mutator method for ${{dm.ident}} field */ 338void 339set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 340{ 341 m_${{dm.ident}} = local_${{dm.ident}}; 342} 343''') 344 345 code('void print(std::ostream& out) const;') 346 code.dedent() 347 code(' //private:') 348 code.indent() 349 350 # Data members for each field 351 for dm in self.data_members.values(): 352 if "abstract" not in dm: 353 const = "" 354 init = "" 355 356 # global structure 357 if self.isGlobal: 358 const = "static const " 359 360 # init value 361 if dm.init_code: 362 # only global structure can have init value here 363 assert self.isGlobal 364 init = " = %s" % (dm.init_code) 365 366 if "desc" in dm: 367 code('/** ${{dm["desc"]}} */') 368 369 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 370 371 code.dedent() 372 code('};') 373 374 code(''' 375inline std::ostream& 376operator<<(std::ostream& out, const ${{self.c_ident}}& obj) 377{ 378 obj.print(out); 379 out << std::flush; 380 return out; 381} 382 383#endif // __${{self.c_ident}}_HH__ 384''') 385 386 code.write(path, "%s.hh" % self.c_ident) 387 388 def printTypeCC(self, path): 389 code = self.symtab.codeFormatter() 390 391 code(''' 392/** \\file ${{self.c_ident}}.cc 393 * 394 * Auto generated C++ code started by $__file__:$__line__ 395 */ 396 397#include <iostream> 398 399#include "mem/protocol/${{self.c_ident}}.hh" 400 401using namespace std; 402''') 403 404 code(''' 405/** \\brief Print the state of this object */ 406void 407${{self.c_ident}}::print(ostream& out) const 408{ 409 out << "[${{self.c_ident}}: "; 410''') 411 412 # For each field 413 code.indent() 414 for dm in self.data_members.values(): 415 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 416 417 if self.isMessage: 418 code('out << "Time = " << getTime() * g_eventQueue_ptr->getClock() << " ";') 419 code.dedent() 420 421 # Trailer 422 code(''' 423 out << "]"; 424}''') 425 426 code.write(path, "%s.cc" % self.c_ident) 427 428 def printEnumHH(self, path): 429 code = self.symtab.codeFormatter() 430 code(''' 431/** \\file ${{self.c_ident}}.hh 432 * 433 * Auto generated C++ code started by $__file__:$__line__ 434 */ 435 436#ifndef __${{self.c_ident}}_HH__ 437#define __${{self.c_ident}}_HH__ 438 439#include <iostream> 440#include <string> 441 442#include "mem/ruby/common/Global.hh" 443''') 444 if self.isStateDecl: 445 code('#include "mem/protocol/AccessPermission.hh"') 446 447 if self.isMachineType: 448 code('#include "base/misc.hh"') 449 code('#include "mem/protocol/GenericMachineType.hh"') 450 code('#include "mem/ruby/common/Address.hh"') 451 code('#include "mem/ruby/system/NodeID.hh"') 452 code('struct MachineID;') 453 454 code(''' 455 456// Class definition 457/** \\enum ${{self.c_ident}} 458 * \\brief ${{self.desc}} 459 */ 460enum ${{self.c_ident}} { 461 ${{self.c_ident}}_FIRST, 462''') 463 464 code.indent() 465 # For each field 466 for i,(ident,enum) in enumerate(self.enums.iteritems()): 467 desc = enum.get("desc", "No description avaliable") 468 if i == 0: 469 init = ' = %s_FIRST' % self.c_ident 470 else: 471 init = '' 472 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 473 code.dedent() 474 code(''' 475 ${{self.c_ident}}_NUM 476}; 477 478// Code to convert from a string to the enumeration 479${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 480 481// Code to convert state to a string 482std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 483 484// Code to increment an enumeration type 485${{self.c_ident}} &operator++(${{self.c_ident}} &e); 486''') 487 488 # MachineType hack used to set the base component id for each Machine 489 if self.isMachineType: 490 code(''' 491int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 492MachineType ${{self.c_ident}}_from_base_level(int); 493int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 494int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 495''') 496 497 for enum in self.enums.itervalues(): 498 if enum.ident == "DMA": 499 code(''' 500MachineID map_Address_to_DMA(const Address &addr); 501''') 502 code(''' 503 504MachineID get${{enum.ident}}MachineID(NodeID RubyNode); 505''') 506 507 code(''' 508inline GenericMachineType 509ConvertMachToGenericMach(MachineType machType) 510{ 511''') 512 for enum in self.enums.itervalues(): 513 code(''' 514 if (machType == MachineType_${{enum.ident}}) 515 return GenericMachineType_${{enum.ident}}; 516''') 517 code(''' 518 panic("cannot convert to a GenericMachineType"); 519} 520''') 521 522 if self.isStateDecl: 523 code(''' 524 525// Code to convert the current state to an access permission 526AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 527 528''') 529 530 # Trailer 531 code(''' 532std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 533 534#endif // __${{self.c_ident}}_HH__ 535''') 536 537 code.write(path, "%s.hh" % self.c_ident) 538 539 def printEnumCC(self, path): 540 code = self.symtab.codeFormatter() 541 code(''' 542/** \\file ${{self.c_ident}}.hh 543 * 544 * Auto generated C++ code started by $__file__:$__line__ 545 */ 546 547#include <cassert> 548#include <iostream> 549#include <string> 550 551#include "base/misc.hh" 552#include "mem/protocol/${{self.c_ident}}.hh" 553 554using namespace std; 555 556''') 557 558 if self.isStateDecl: 559 code(''' 560// Code to convert the current state to an access permission 561AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 562{ 563 switch(obj) { 564''') 565 # For each case 566 code.indent() 567 for statePerm in self.statePermPairs: 568 code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 569 code(' return AccessPermission_${{statePerm[1]}};') 570 code.dedent() 571 code (''' 572 default: 573 panic("Unknown state access permission converstion for ${{self.c_ident}}"); 574 } 575} 576 577''') 578 579 if self.isMachineType: 580 for enum in self.enums.itervalues(): 581 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 582 code('#include "mem/ruby/system/MachineID.hh"') 583 584 code(''' 585// Code for output operator 586ostream& 587operator<<(ostream& out, const ${{self.c_ident}}& obj) 588{ 589 out << ${{self.c_ident}}_to_string(obj); 590 out << flush; 591 return out; 592} 593 594// Code to convert state to a string 595string 596${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 597{ 598 switch(obj) { 599''') 600 601 # For each field 602 code.indent() 603 for enum in self.enums.itervalues(): 604 code(' case ${{self.c_ident}}_${{enum.ident}}:') 605 code(' return "${{enum.ident}}";') 606 code.dedent() 607 608 # Trailer 609 code(''' 610 default: 611 panic("Invalid range for type ${{self.c_ident}}"); 612 } 613} 614 615// Code to convert from a string to the enumeration 616${{self.c_ident}} 617string_to_${{self.c_ident}}(const string& str) 618{ 619''') 620 621 # For each field 622 start = "" 623 code.indent() 624 for enum in self.enums.itervalues(): 625 code('${start}if (str == "${{enum.ident}}") {') 626 code(' return ${{self.c_ident}}_${{enum.ident}};') 627 start = "} else " 628 code.dedent() 629 630 code(''' 631 } else { 632 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 633 } 634} 635 636// Code to increment an enumeration type 637${{self.c_ident}}& 638operator++(${{self.c_ident}}& e) 639{ 640 assert(e < ${{self.c_ident}}_NUM); 641 return e = ${{self.c_ident}}(e+1); 642} 643''') 644 645 # MachineType hack used to set the base level and number of 646 # components for each Machine 647 if self.isMachineType: 648 code(''' 649/** \\brief returns the base vector index for each machine type to be 650 * used by NetDest 651 * 652 * \\return the base vector index for each machine type to be used by NetDest 653 * \\see NetDest.hh 654 */ 655int 656${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 657{ 658 switch(obj) { 659''') 660 661 # For each field 662 code.indent() 663 for i,enum in enumerate(self.enums.itervalues()): 664 code(' case ${{self.c_ident}}_${{enum.ident}}:') 665 code(' return $i;') 666 code.dedent() 667 668 # total num 669 code(''' 670 case ${{self.c_ident}}_NUM: 671 return ${{len(self.enums)}}; 672 673 default: 674 panic("Invalid range for type ${{self.c_ident}}"); 675 } 676} 677 678/** \\brief returns the machine type for each base vector index used by NetDest 679 * 680 * \\return the MachineType 681 */ 682MachineType 683${{self.c_ident}}_from_base_level(int type) 684{ 685 switch(type) { 686''') 687 688 # For each field 689 code.indent() 690 for i,enum in enumerate(self.enums.itervalues()): 691 code(' case $i:') 692 code(' return ${{self.c_ident}}_${{enum.ident}};') 693 code.dedent() 694 695 # Trailer 696 code(''' 697 default: 698 panic("Invalid range for type ${{self.c_ident}}"); 699 } 700} 701 702/** \\brief The return value indicates the number of components created 703 * before a particular machine\'s components 704 * 705 * \\return the base number of components for each machine 706 */ 707int 708${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 709{ 710 int base = 0; 711 switch(obj) { 712''') 713 714 # For each field 715 code.indent() 716 code(' case ${{self.c_ident}}_NUM:') 717 for enum in reversed(self.enums.values()): 718 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 719 code(' case ${{self.c_ident}}_${{enum.ident}}:') 720 code(' break;') 721 code.dedent() 722 723 code(''' 724 default: 725 panic("Invalid range for type ${{self.c_ident}}"); 726 } 727 728 return base; 729} 730 731/** \\brief returns the total number of components for each machine 732 * \\return the total number of components for each machine 733 */ 734int 735${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 736{ 737 switch(obj) { 738''') 739 740 # For each field 741 for enum in self.enums.itervalues(): 742 code(''' 743 case ${{self.c_ident}}_${{enum.ident}}: 744 return ${{enum.ident}}_Controller::getNumControllers(); 745''') 746 747 # total num 748 code(''' 749 case ${{self.c_ident}}_NUM: 750 default: 751 panic("Invalid range for type ${{self.c_ident}}"); 752 } 753} 754''') 755 756 for enum in self.enums.itervalues(): 757 if enum.ident == "DMA": 758 code(''' 759MachineID 760map_Address_to_DMA(const Address &addr) 761{ 762 MachineID dma = {MachineType_DMA, 0}; 763 return dma; 764} 765''') 766 767 code(''' 768 769MachineID 770get${{enum.ident}}MachineID(NodeID RubyNode) 771{ 772 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 773 return mach; 774} 775''') 776 777 # Write the file 778 code.write(path, "%s.cc" % self.c_ident) 779 780__all__ = [ "Type" ] 781