Type.py revision 10917:c38f28fad4c3
18926Sandreas.hansson@arm.com# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 27586SAli.Saidi@arm.com# Copyright (c) 2009 The Hewlett-Packard Development Company 37586SAli.Saidi@arm.com# All rights reserved. 47586SAli.Saidi@arm.com# 57586SAli.Saidi@arm.com# Redistribution and use in source and binary forms, with or without 67586SAli.Saidi@arm.com# modification, are permitted provided that the following conditions are 77586SAli.Saidi@arm.com# met: redistributions of source code must retain the above copyright 87586SAli.Saidi@arm.com# notice, this list of conditions and the following disclaimer; 97586SAli.Saidi@arm.com# redistributions in binary form must reproduce the above copyright 107586SAli.Saidi@arm.com# notice, this list of conditions and the following disclaimer in the 117586SAli.Saidi@arm.com# documentation and/or other materials provided with the distribution; 127586SAli.Saidi@arm.com# neither the name of the copyright holders nor the names of its 133970Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 143005Sstever@eecs.umich.edu# this software without specific prior written permission. 153005Sstever@eecs.umich.edu# 163005Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173005Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183005Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193005Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203005Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213005Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223005Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233005Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243005Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253005Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263005Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273005Sstever@eecs.umich.edu 283005Sstever@eecs.umich.edufrom m5.util import orderdict 293005Sstever@eecs.umich.edu 303005Sstever@eecs.umich.edufrom slicc.util import PairContainer 313005Sstever@eecs.umich.edufrom slicc.symbols.Symbol import Symbol 323005Sstever@eecs.umich.edufrom slicc.symbols.Var import Var 333005Sstever@eecs.umich.edu 343005Sstever@eecs.umich.educlass DataMember(PairContainer): 353005Sstever@eecs.umich.edu def __init__(self, ident, type, pairs, init_code): 363005Sstever@eecs.umich.edu super(DataMember, self).__init__(pairs) 373005Sstever@eecs.umich.edu self.ident = ident 383005Sstever@eecs.umich.edu self.type = type 393005Sstever@eecs.umich.edu self.init_code = init_code 403005Sstever@eecs.umich.edu 416654Snate@binkert.orgclass Enumeration(PairContainer): 426654Snate@binkert.org def __init__(self, ident, pairs): 432889SN/A super(Enumeration, self).__init__(pairs) 442710SN/A self.ident = ident 456654Snate@binkert.org 466654Snate@binkert.orgclass Type(Symbol): 476654Snate@binkert.org def __init__(self, table, ident, location, pairs, machine=None): 485457Ssaidi@eecs.umich.edu super(Type, self).__init__(table, ident, location, pairs) 496654Snate@binkert.org self.c_ident = ident 506654Snate@binkert.org self.abstract_ident = "" 512934SN/A if machine: 522549SN/A if self.isExternal or self.isPrimitive: 532995SN/A if "external_name" in self: 543395Shsul@eecs.umich.edu self.c_ident = self["external_name"] 556981SLisa.Hsu@amd.com else: 563448Shsul@eecs.umich.edu # Append with machine name 578920Snilay@cs.wisc.edu self.c_ident = "%s_%s" % (machine, ident) 583444Sktlim@umich.edu 592889SN/A self.pairs.setdefault("desc", "No description avaliable") 608920Snilay@cs.wisc.edu 618920Snilay@cs.wisc.edu # check for interface that this Type implements 623322Shsul@eecs.umich.edu if "interface" in self: 632710SN/A interface = self["interface"] 642710SN/A if interface in ("Message"): 652710SN/A self["message"] = "yes" 662710SN/A 672710SN/A # FIXME - all of the following id comparisons are fragile hacks 682710SN/A if self.ident in ("CacheMemory"): 693322Shsul@eecs.umich.edu self["cache"] = "yes" 703304Sstever@eecs.umich.edu 713322Shsul@eecs.umich.edu if self.ident in ("TBETable"): 723322Shsul@eecs.umich.edu self["tbe"] = "yes" 733304Sstever@eecs.umich.edu 743481Shsul@eecs.umich.edu if self.ident == "TimerTable": 753481Shsul@eecs.umich.edu self["timer"] = "yes" 762566SN/A 773322Shsul@eecs.umich.edu if self.ident == "DirectoryMemory": 783322Shsul@eecs.umich.edu self["dir"] = "yes" 792995SN/A 802995SN/A if self.ident == "PersistentTable": 813304Sstever@eecs.umich.edu self["persistent"] = "yes" 823304Sstever@eecs.umich.edu 833304Sstever@eecs.umich.edu if self.ident == "Prefetcher": 842995SN/A self["prefetcher"] = "yes" 852995SN/A 862995SN/A self.isMachineType = (ident == "MachineType") 872917SN/A 882995SN/A self.isStateDecl = ("state_decl" in self) 898956Sjayneel@cs.wisc.edu self.statePermPairs = [] 902995SN/A 918956Sjayneel@cs.wisc.edu self.data_members = orderdict() 923304Sstever@eecs.umich.edu self.methods = {} 936135Sgblack@eecs.umich.edu self.enums = orderdict() 946135Sgblack@eecs.umich.edu 956654Snate@binkert.org @property 963819Shsul@eecs.umich.edu def isPrimitive(self): 976654Snate@binkert.org return "primitive" in self 985222Sksewell@umich.edu 996654Snate@binkert.org @property 1003819Shsul@eecs.umich.edu def isMessage(self): 1016654Snate@binkert.org return "message" in self 1027925Sgblack@eecs.umich.edu @property 1037586SAli.Saidi@arm.com def isBuffer(self): 1048061SAli.Saidi@ARM.com return "buffer" in self 1058061SAli.Saidi@ARM.com @property 1068061SAli.Saidi@ARM.com def isInPort(self): 1073819Shsul@eecs.umich.edu return "inport" in self 1089059Snilay@cs.wisc.edu @property 1093819Shsul@eecs.umich.edu def isOutPort(self): 1103873Sbinkertn@umich.edu return "outport" in self 1113873Sbinkertn@umich.edu @property 1123873Sbinkertn@umich.edu def isEnumeration(self): 1133873Sbinkertn@umich.edu return "enumeration" in self 1143873Sbinkertn@umich.edu @property 1153873Sbinkertn@umich.edu def isExternal(self): 1168659SAli.Saidi@ARM.com return "external" in self 1178659SAli.Saidi@ARM.com @property 1186995Sgblack@eecs.umich.edu def isGlobal(self): 1193668Srdreslin@umich.edu return "global" in self 1208713Sandreas.hansson@arm.com @property 1218713Sandreas.hansson@arm.com def isInterface(self): 1228713Sandreas.hansson@arm.com return "interface" in self 1238713Sandreas.hansson@arm.com 1246636Ssteve.reinhardt@amd.com # Return false on error 1258894Ssaidi@eecs.umich.edu def addDataMember(self, ident, type, pairs, init_code): 1268839Sandreas.hansson@arm.com if ident in self.data_members: 1278839Sandreas.hansson@arm.com return False 1288713Sandreas.hansson@arm.com 1298713Sandreas.hansson@arm.com member = DataMember(ident, type, pairs, init_code) 1308870SAli.Saidi@ARM.com self.data_members[ident] = member 1318839Sandreas.hansson@arm.com 1328839Sandreas.hansson@arm.com var = Var(self.symtab, ident, self.location, type, 1335142Ssaidi@eecs.umich.edu "m_%s" % ident, {}, None) 1348926Sandreas.hansson@arm.com self.symtab.registerSym(ident, var) 1358926Sandreas.hansson@arm.com return True 1368926Sandreas.hansson@arm.com 1378926Sandreas.hansson@arm.com def dataMemberType(self, ident): 1383312Sstever@eecs.umich.edu return self.data_members[ident].type 1394968Sacolyte@umich.edu 1408926Sandreas.hansson@arm.com def methodId(self, name, param_type_vec): 1418887Sgeoffrey.blake@arm.com return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 1428887Sgeoffrey.blake@arm.com 1438887Sgeoffrey.blake@arm.com def methodIdAbstract(self, name, param_type_vec): 1448887Sgeoffrey.blake@arm.com return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 1454968Sacolyte@umich.edu 1463005Sstever@eecs.umich.edu def statePermPairAdd(self, state_name, perm_name): 1476654Snate@binkert.org self.statePermPairs.append([state_name, perm_name]) 1483819Shsul@eecs.umich.edu 1496654Snate@binkert.org def addFunc(self, func): 1505222Sksewell@umich.edu ident = self.methodId(func.ident, func.param_types) 1516654Snate@binkert.org if ident in self.methods: 1523819Shsul@eecs.umich.edu return False 1536654Snate@binkert.org 1546135Sgblack@eecs.umich.edu self.methods[ident] = func 1557586SAli.Saidi@arm.com return True 1568661SAli.Saidi@ARM.com 1578661SAli.Saidi@ARM.com def addEnum(self, ident, pairs): 1583322Shsul@eecs.umich.edu if ident in self.enums: 1598863Snilay@cs.wisc.edu return False 1607876Sgblack@eecs.umich.edu 1614968Sacolyte@umich.edu self.enums[ident] = Enumeration(ident, pairs) 1628926Sandreas.hansson@arm.com 1634837Ssaidi@eecs.umich.edu # Add default 1644837Ssaidi@eecs.umich.edu if "default" not in self: 1658810SAli.Saidi@ARM.com self["default"] = "%s_NUM" % self.c_ident 1668870SAli.Saidi@ARM.com 1678845Sandreas.hansson@arm.com return True 1688845Sandreas.hansson@arm.com 1694837Ssaidi@eecs.umich.edu def writeCodeFiles(self, path, includes): 1708659SAli.Saidi@ARM.com if self.isExternal: 1718801Sgblack@eecs.umich.edu # Do nothing 1723005Sstever@eecs.umich.edu pass 1738801Sgblack@eecs.umich.edu elif self.isEnumeration: 1743005Sstever@eecs.umich.edu self.printEnumHH(path) 1753005Sstever@eecs.umich.edu self.printEnumCC(path) 1763005Sstever@eecs.umich.edu else: 1772566SN/A # User defined structs and messages 1787861Sgblack@eecs.umich.edu self.printTypeHH(path) 1797861Sgblack@eecs.umich.edu self.printTypeCC(path) 1807861Sgblack@eecs.umich.edu 1818635Schris.emmons@arm.com def printTypeHH(self, path): 1828635Schris.emmons@arm.com code = self.symtab.codeFormatter() 1838635Schris.emmons@arm.com code(''' 1849061Snilay@cs.wisc.edu/** \\file ${{self.c_ident}}.hh 1853481Shsul@eecs.umich.edu * 186 * 187 * Auto generated C++ code started by $__file__:$__line__ 188 */ 189 190#ifndef __${{self.c_ident}}_HH__ 191#define __${{self.c_ident}}_HH__ 192 193#include <iostream> 194 195#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 196''') 197 198 for dm in self.data_members.values(): 199 if not dm.type.isPrimitive: 200 code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 201 202 parent = "" 203 if "interface" in self: 204 code('#include "mem/protocol/$0.hh"', self["interface"]) 205 parent = " : public %s" % self["interface"] 206 207 code(''' 208$klass ${{self.c_ident}}$parent 209{ 210 public: 211 ${{self.c_ident}} 212''', klass="class") 213 214 if self.isMessage: 215 code('(Tick curTime) : %s(curTime) {' % self["interface"]) 216 else: 217 code('()\n\t\t{') 218 219 code.indent() 220 if not self.isGlobal: 221 code.indent() 222 for dm in self.data_members.values(): 223 ident = dm.ident 224 if "default" in dm: 225 # look for default value 226 code('m_$ident = ${{dm["default"]}}; // default for this field') 227 elif "default" in dm.type: 228 # Look for the type default 229 tid = dm.type.c_ident 230 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 231 else: 232 code('// m_$ident has no default') 233 code.dedent() 234 code('}') 235 236 # ******** Copy constructor ******** 237 if not self.isGlobal: 238 code('${{self.c_ident}}(const ${{self.c_ident}}&other)') 239 240 # Call superclass constructor 241 if "interface" in self: 242 code(' : ${{self["interface"]}}(other)') 243 244 code('{') 245 code.indent() 246 247 for dm in self.data_members.values(): 248 code('m_${{dm.ident}} = other.m_${{dm.ident}};') 249 250 code.dedent() 251 code('}') 252 253 # ******** Full init constructor ******** 254 if not self.isGlobal: 255 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 256 for dm in self.data_members.itervalues() ] 257 params = ', '.join(params) 258 259 if self.isMessage: 260 params = "const Tick curTime, " + params 261 262 code('${{self.c_ident}}($params)') 263 264 # Call superclass constructor 265 if "interface" in self: 266 if self.isMessage: 267 code(' : ${{self["interface"]}}(curTime)') 268 else: 269 code(' : ${{self["interface"]}}()') 270 271 code('{') 272 code.indent() 273 for dm in self.data_members.values(): 274 code('m_${{dm.ident}} = local_${{dm.ident}};') 275 if "nextLineCallHack" in dm: 276 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};') 277 278 code.dedent() 279 code('}') 280 281 # create a clone member 282 if self.isMessage: 283 code(''' 284MsgPtr 285clone() const 286{ 287 return std::shared_ptr<Message>(new ${{self.c_ident}}(*this)); 288} 289''') 290 else: 291 code(''' 292${{self.c_ident}}* 293clone() const 294{ 295 return new ${{self.c_ident}}(*this); 296} 297''') 298 299 if not self.isGlobal: 300 # const Get methods for each field 301 code('// Const accessors methods for each field') 302 for dm in self.data_members.values(): 303 code(''' 304/** \\brief Const accessor method for ${{dm.ident}} field. 305 * \\return ${{dm.ident}} field 306 */ 307const ${{dm.type.c_ident}}& 308get${{dm.ident}}() const 309{ 310 return m_${{dm.ident}}; 311} 312''') 313 314 # Non-const Get methods for each field 315 code('// Non const Accessors methods for each field') 316 for dm in self.data_members.values(): 317 code(''' 318/** \\brief Non-const accessor method for ${{dm.ident}} field. 319 * \\return ${{dm.ident}} field 320 */ 321${{dm.type.c_ident}}& 322get${{dm.ident}}() 323{ 324 return m_${{dm.ident}}; 325} 326''') 327 328 #Set methods for each field 329 code('// Mutator methods for each field') 330 for dm in self.data_members.values(): 331 code(''' 332/** \\brief Mutator method for ${{dm.ident}} field */ 333void 334set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 335{ 336 m_${{dm.ident}} = local_${{dm.ident}}; 337} 338''') 339 340 code('void print(std::ostream& out) const;') 341 code.dedent() 342 code(' //private:') 343 code.indent() 344 345 # Data members for each field 346 for dm in self.data_members.values(): 347 if "abstract" not in dm: 348 const = "" 349 init = "" 350 351 # global structure 352 if self.isGlobal: 353 const = "static const " 354 355 # init value 356 if dm.init_code: 357 # only global structure can have init value here 358 assert self.isGlobal 359 init = " = %s" % (dm.init_code) 360 361 if "desc" in dm: 362 code('/** ${{dm["desc"]}} */') 363 364 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 365 366 # Prototypes for methods defined for the Type 367 for item in self.methods: 368 proto = self.methods[item].prototype 369 if proto: 370 code('$proto') 371 372 code.dedent() 373 code('};') 374 375 code(''' 376inline std::ostream& 377operator<<(std::ostream& out, const ${{self.c_ident}}& obj) 378{ 379 obj.print(out); 380 out << std::flush; 381 return out; 382} 383 384#endif // __${{self.c_ident}}_HH__ 385''') 386 387 code.write(path, "%s.hh" % self.c_ident) 388 389 def printTypeCC(self, path): 390 code = self.symtab.codeFormatter() 391 392 code(''' 393/** \\file ${{self.c_ident}}.cc 394 * 395 * Auto generated C++ code started by $__file__:$__line__ 396 */ 397 398#include <iostream> 399#include <memory> 400 401#include "mem/protocol/${{self.c_ident}}.hh" 402#include "mem/ruby/common/Global.hh" 403#include "mem/ruby/system/System.hh" 404 405using namespace std; 406''') 407 408 code(''' 409/** \\brief Print the state of this object */ 410void 411${{self.c_ident}}::print(ostream& out) const 412{ 413 out << "[${{self.c_ident}}: "; 414''') 415 416 # For each field 417 code.indent() 418 for dm in self.data_members.values(): 419 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 420 421 if self.isMessage: 422 code('out << "Time = " << g_system_ptr->clockPeriod() * getTime() << " ";') 423 code.dedent() 424 425 # Trailer 426 code(''' 427 out << "]"; 428}''') 429 430 # print the code for the methods in the type 431 for item in self.methods: 432 code(self.methods[item].generateCode()) 433 434 code.write(path, "%s.cc" % self.c_ident) 435 436 def printEnumHH(self, path): 437 code = self.symtab.codeFormatter() 438 code(''' 439/** \\file ${{self.c_ident}}.hh 440 * 441 * Auto generated C++ code started by $__file__:$__line__ 442 */ 443 444#ifndef __${{self.c_ident}}_HH__ 445#define __${{self.c_ident}}_HH__ 446 447#include <iostream> 448#include <string> 449 450''') 451 if self.isStateDecl: 452 code('#include "mem/protocol/AccessPermission.hh"') 453 454 if self.isMachineType: 455 code('#include "base/misc.hh"') 456 code('#include "mem/ruby/common/Address.hh"') 457 code('struct MachineID;') 458 459 code(''' 460 461// Class definition 462/** \\enum ${{self.c_ident}} 463 * \\brief ${{self.desc}} 464 */ 465enum ${{self.c_ident}} { 466 ${{self.c_ident}}_FIRST, 467''') 468 469 code.indent() 470 # For each field 471 for i,(ident,enum) in enumerate(self.enums.iteritems()): 472 desc = enum.get("desc", "No description avaliable") 473 if i == 0: 474 init = ' = %s_FIRST' % self.c_ident 475 else: 476 init = '' 477 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 478 code.dedent() 479 code(''' 480 ${{self.c_ident}}_NUM 481}; 482 483// Code to convert from a string to the enumeration 484${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 485 486// Code to convert state to a string 487std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 488 489// Code to increment an enumeration type 490${{self.c_ident}} &operator++(${{self.c_ident}} &e); 491''') 492 493 # MachineType hack used to set the base component id for each Machine 494 if self.isMachineType: 495 code(''' 496int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 497MachineType ${{self.c_ident}}_from_base_level(int); 498int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 499int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 500''') 501 502 for enum in self.enums.itervalues(): 503 if enum.ident == "DMA": 504 code(''' 505MachineID map_Address_to_DMA(const Address &addr); 506''') 507 code(''' 508 509MachineID get${{enum.ident}}MachineID(NodeID RubyNode); 510''') 511 512 if self.isStateDecl: 513 code(''' 514 515// Code to convert the current state to an access permission 516AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 517 518''') 519 520 # Trailer 521 code(''' 522std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 523 524#endif // __${{self.c_ident}}_HH__ 525''') 526 527 code.write(path, "%s.hh" % self.c_ident) 528 529 def printEnumCC(self, path): 530 code = self.symtab.codeFormatter() 531 code(''' 532/** \\file ${{self.c_ident}}.hh 533 * 534 * Auto generated C++ code started by $__file__:$__line__ 535 */ 536 537#include <cassert> 538#include <iostream> 539#include <string> 540 541#include "base/misc.hh" 542#include "mem/protocol/${{self.c_ident}}.hh" 543 544using namespace std; 545 546''') 547 548 if self.isStateDecl: 549 code(''' 550// Code to convert the current state to an access permission 551AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 552{ 553 switch(obj) { 554''') 555 # For each case 556 code.indent() 557 for statePerm in self.statePermPairs: 558 code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 559 code(' return AccessPermission_${{statePerm[1]}};') 560 code.dedent() 561 code (''' 562 default: 563 panic("Unknown state access permission converstion for ${{self.c_ident}}"); 564 } 565} 566 567''') 568 569 if self.isMachineType: 570 for enum in self.enums.itervalues(): 571 if enum.get("Primary"): 572 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 573 code('#include "mem/ruby/common/MachineID.hh"') 574 575 code(''' 576// Code for output operator 577ostream& 578operator<<(ostream& out, const ${{self.c_ident}}& obj) 579{ 580 out << ${{self.c_ident}}_to_string(obj); 581 out << flush; 582 return out; 583} 584 585// Code to convert state to a string 586string 587${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 588{ 589 switch(obj) { 590''') 591 592 # For each field 593 code.indent() 594 for enum in self.enums.itervalues(): 595 code(' case ${{self.c_ident}}_${{enum.ident}}:') 596 code(' return "${{enum.ident}}";') 597 code.dedent() 598 599 # Trailer 600 code(''' 601 default: 602 panic("Invalid range for type ${{self.c_ident}}"); 603 } 604} 605 606// Code to convert from a string to the enumeration 607${{self.c_ident}} 608string_to_${{self.c_ident}}(const string& str) 609{ 610''') 611 612 # For each field 613 start = "" 614 code.indent() 615 for enum in self.enums.itervalues(): 616 code('${start}if (str == "${{enum.ident}}") {') 617 code(' return ${{self.c_ident}}_${{enum.ident}};') 618 start = "} else " 619 code.dedent() 620 621 code(''' 622 } else { 623 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 624 } 625} 626 627// Code to increment an enumeration type 628${{self.c_ident}}& 629operator++(${{self.c_ident}}& e) 630{ 631 assert(e < ${{self.c_ident}}_NUM); 632 return e = ${{self.c_ident}}(e+1); 633} 634''') 635 636 # MachineType hack used to set the base level and number of 637 # components for each Machine 638 if self.isMachineType: 639 code(''' 640/** \\brief returns the base vector index for each machine type to be 641 * used by NetDest 642 * 643 * \\return the base vector index for each machine type to be used by NetDest 644 * \\see NetDest.hh 645 */ 646int 647${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 648{ 649 switch(obj) { 650''') 651 652 # For each field 653 code.indent() 654 for i,enum in enumerate(self.enums.itervalues()): 655 code(' case ${{self.c_ident}}_${{enum.ident}}:') 656 code(' return $i;') 657 code.dedent() 658 659 # total num 660 code(''' 661 case ${{self.c_ident}}_NUM: 662 return ${{len(self.enums)}}; 663 664 default: 665 panic("Invalid range for type ${{self.c_ident}}"); 666 } 667} 668 669/** \\brief returns the machine type for each base vector index used by NetDest 670 * 671 * \\return the MachineType 672 */ 673MachineType 674${{self.c_ident}}_from_base_level(int type) 675{ 676 switch(type) { 677''') 678 679 # For each field 680 code.indent() 681 for i,enum in enumerate(self.enums.itervalues()): 682 code(' case $i:') 683 code(' return ${{self.c_ident}}_${{enum.ident}};') 684 code.dedent() 685 686 # Trailer 687 code(''' 688 default: 689 panic("Invalid range for type ${{self.c_ident}}"); 690 } 691} 692 693/** \\brief The return value indicates the number of components created 694 * before a particular machine\'s components 695 * 696 * \\return the base number of components for each machine 697 */ 698int 699${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 700{ 701 int base = 0; 702 switch(obj) { 703''') 704 705 # For each field 706 code.indent() 707 code(' case ${{self.c_ident}}_NUM:') 708 for enum in reversed(self.enums.values()): 709 # Check if there is a defined machine with this type 710 if enum.get("Primary"): 711 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 712 else: 713 code(' base += 0;') 714 code(' case ${{self.c_ident}}_${{enum.ident}}:') 715 code(' break;') 716 code.dedent() 717 718 code(''' 719 default: 720 panic("Invalid range for type ${{self.c_ident}}"); 721 } 722 723 return base; 724} 725 726/** \\brief returns the total number of components for each machine 727 * \\return the total number of components for each machine 728 */ 729int 730${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 731{ 732 switch(obj) { 733''') 734 735 # For each field 736 for enum in self.enums.itervalues(): 737 code('case ${{self.c_ident}}_${{enum.ident}}:') 738 if enum.get("Primary"): 739 code('return ${{enum.ident}}_Controller::getNumControllers();') 740 else: 741 code('return 0;') 742 743 # total num 744 code(''' 745 case ${{self.c_ident}}_NUM: 746 default: 747 panic("Invalid range for type ${{self.c_ident}}"); 748 } 749} 750''') 751 752 for enum in self.enums.itervalues(): 753 if enum.ident == "DMA": 754 code(''' 755MachineID 756map_Address_to_DMA(const Address &addr) 757{ 758 MachineID dma = {MachineType_DMA, 0}; 759 return dma; 760} 761''') 762 763 code(''' 764 765MachineID 766get${{enum.ident}}MachineID(NodeID RubyNode) 767{ 768 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 769 return mach; 770} 771''') 772 773 # Write the file 774 code.write(path, "%s.cc" % self.c_ident) 775 776__all__ = [ "Type" ] 777