Type.py revision 11283:4cc8b312f026
14679Sgblack@eecs.umich.edu# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 24679Sgblack@eecs.umich.edu# Copyright (c) 2009 The Hewlett-Packard Development Company 34679Sgblack@eecs.umich.edu# All rights reserved. 44679Sgblack@eecs.umich.edu# 54679Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 64679Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 74679Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 84679Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 94679Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 104679Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 114679Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 124679Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 134679Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 144679Sgblack@eecs.umich.edu# this software without specific prior written permission. 154679Sgblack@eecs.umich.edu# 164679Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174679Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184679Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194679Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204679Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214679Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224679Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234679Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244679Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254679Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264679Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274679Sgblack@eecs.umich.edu 284679Sgblack@eecs.umich.edufrom m5.util import orderdict 294679Sgblack@eecs.umich.edu 304679Sgblack@eecs.umich.edufrom slicc.util import PairContainer 314679Sgblack@eecs.umich.edufrom slicc.symbols.Symbol import Symbol 324679Sgblack@eecs.umich.edufrom slicc.symbols.Var import Var 334679Sgblack@eecs.umich.edu 344679Sgblack@eecs.umich.educlass DataMember(Var): 354679Sgblack@eecs.umich.edu def __init__(self, symtab, ident, location, type, code, pairs, 364679Sgblack@eecs.umich.edu machine, init_code): 374679Sgblack@eecs.umich.edu super(DataMember, self).__init__(symtab, ident, location, type, 384679Sgblack@eecs.umich.edu code, pairs, machine) 394679Sgblack@eecs.umich.edu self.init_code = init_code 404679Sgblack@eecs.umich.edu 414679Sgblack@eecs.umich.educlass Enumeration(PairContainer): 424679Sgblack@eecs.umich.edu def __init__(self, ident, pairs): 434679Sgblack@eecs.umich.edu super(Enumeration, self).__init__(pairs) 444679Sgblack@eecs.umich.edu self.ident = ident 454679Sgblack@eecs.umich.edu self.primary = False 464679Sgblack@eecs.umich.edu 474679Sgblack@eecs.umich.educlass Type(Symbol): 484679Sgblack@eecs.umich.edu def __init__(self, table, ident, location, pairs, machine=None): 494679Sgblack@eecs.umich.edu super(Type, self).__init__(table, ident, location, pairs) 504679Sgblack@eecs.umich.edu self.c_ident = ident 514679Sgblack@eecs.umich.edu self.abstract_ident = "" 524679Sgblack@eecs.umich.edu if machine: 534679Sgblack@eecs.umich.edu if self.isExternal or self.isPrimitive: 544679Sgblack@eecs.umich.edu if "external_name" in self: 554679Sgblack@eecs.umich.edu self.c_ident = self["external_name"] 564679Sgblack@eecs.umich.edu else: 574679Sgblack@eecs.umich.edu # Append with machine name 584679Sgblack@eecs.umich.edu self.c_ident = "%s_%s" % (machine, ident) 594679Sgblack@eecs.umich.edu 604679Sgblack@eecs.umich.edu self.pairs.setdefault("desc", "No description avaliable") 614679Sgblack@eecs.umich.edu 624679Sgblack@eecs.umich.edu # check for interface that this Type implements 634679Sgblack@eecs.umich.edu if "interface" in self: 644679Sgblack@eecs.umich.edu interface = self["interface"] 654679Sgblack@eecs.umich.edu if interface in ("Message"): 664679Sgblack@eecs.umich.edu self["message"] = "yes" 674679Sgblack@eecs.umich.edu 684688Sgblack@eecs.umich.edu # FIXME - all of the following id comparisons are fragile hacks 694679Sgblack@eecs.umich.edu if self.ident in ("CacheMemory"): 704679Sgblack@eecs.umich.edu self["cache"] = "yes" 714679Sgblack@eecs.umich.edu 724688Sgblack@eecs.umich.edu if self.ident in ("TBETable"): 734688Sgblack@eecs.umich.edu self["tbe"] = "yes" 744688Sgblack@eecs.umich.edu 754804Sgblack@eecs.umich.edu if self.ident == "TimerTable": 764688Sgblack@eecs.umich.edu self["timer"] = "yes" 774688Sgblack@eecs.umich.edu 784688Sgblack@eecs.umich.edu if self.ident == "DirectoryMemory": 794688Sgblack@eecs.umich.edu self["dir"] = "yes" 804688Sgblack@eecs.umich.edu 814688Sgblack@eecs.umich.edu if self.ident == "PersistentTable": 826345Sgblack@eecs.umich.edu self["persistent"] = "yes" 834688Sgblack@eecs.umich.edu 844688Sgblack@eecs.umich.edu if self.ident == "Prefetcher": 854688Sgblack@eecs.umich.edu self["prefetcher"] = "yes" 864688Sgblack@eecs.umich.edu 874688Sgblack@eecs.umich.edu self.isMachineType = (ident == "MachineType") 886345Sgblack@eecs.umich.edu 894688Sgblack@eecs.umich.edu self.isStateDecl = ("state_decl" in self) 904688Sgblack@eecs.umich.edu self.statePermPairs = [] 914804Sgblack@eecs.umich.edu 924688Sgblack@eecs.umich.edu self.data_members = orderdict() 934688Sgblack@eecs.umich.edu self.methods = {} 944688Sgblack@eecs.umich.edu self.enums = orderdict() 954688Sgblack@eecs.umich.edu 964713Sgblack@eecs.umich.edu @property 974713Sgblack@eecs.umich.edu def isPrimitive(self): 984688Sgblack@eecs.umich.edu return "primitive" in self 994688Sgblack@eecs.umich.edu 1004688Sgblack@eecs.umich.edu @property 1014688Sgblack@eecs.umich.edu def isMessage(self): 1024688Sgblack@eecs.umich.edu return "message" in self 1034679Sgblack@eecs.umich.edu @property 1044679Sgblack@eecs.umich.edu def isBuffer(self): 1054679Sgblack@eecs.umich.edu return "buffer" in self 1064679Sgblack@eecs.umich.edu @property 1074679Sgblack@eecs.umich.edu def isInPort(self): 1084679Sgblack@eecs.umich.edu return "inport" in self 1094679Sgblack@eecs.umich.edu @property 1106345Sgblack@eecs.umich.edu def isOutPort(self): 1114688Sgblack@eecs.umich.edu return "outport" in self 1124679Sgblack@eecs.umich.edu @property 1134688Sgblack@eecs.umich.edu def isEnumeration(self): 1144679Sgblack@eecs.umich.edu return "enumeration" in self 1154688Sgblack@eecs.umich.edu @property 1164679Sgblack@eecs.umich.edu def isExternal(self): 1176345Sgblack@eecs.umich.edu return "external" in self 1184679Sgblack@eecs.umich.edu @property 1194679Sgblack@eecs.umich.edu def isGlobal(self): 1204679Sgblack@eecs.umich.edu return "global" in self 1214679Sgblack@eecs.umich.edu @property 1224679Sgblack@eecs.umich.edu def isInterface(self): 1234679Sgblack@eecs.umich.edu return "interface" in self 1244679Sgblack@eecs.umich.edu 1254688Sgblack@eecs.umich.edu # Return false on error 1264679Sgblack@eecs.umich.edu def addDataMember(self, ident, type, pairs, init_code): 1274679Sgblack@eecs.umich.edu if ident in self.data_members: 1284679Sgblack@eecs.umich.edu return False 1294679Sgblack@eecs.umich.edu 1304679Sgblack@eecs.umich.edu member = DataMember(self.symtab, ident, self.location, type, 1314679Sgblack@eecs.umich.edu "m_%s" % ident, pairs, None, init_code) 1324679Sgblack@eecs.umich.edu 1334679Sgblack@eecs.umich.edu self.data_members[ident] = member 1344679Sgblack@eecs.umich.edu self.symtab.registerSym(ident, member) 1356345Sgblack@eecs.umich.edu return True 1364688Sgblack@eecs.umich.edu 1374679Sgblack@eecs.umich.edu def dataMemberType(self, ident): 1384688Sgblack@eecs.umich.edu return self.data_members[ident].type 1394679Sgblack@eecs.umich.edu 1404688Sgblack@eecs.umich.edu def methodId(self, name, param_type_vec): 1414679Sgblack@eecs.umich.edu return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 1424688Sgblack@eecs.umich.edu 1434679Sgblack@eecs.umich.edu def methodIdAbstract(self, name, param_type_vec): 1444679Sgblack@eecs.umich.edu return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 1454679Sgblack@eecs.umich.edu 1464679Sgblack@eecs.umich.edu def statePermPairAdd(self, state_name, perm_name): 1474679Sgblack@eecs.umich.edu self.statePermPairs.append([state_name, perm_name]) 1484679Sgblack@eecs.umich.edu 1494679Sgblack@eecs.umich.edu def addFunc(self, func): 1504679Sgblack@eecs.umich.edu ident = self.methodId(func.ident, func.param_types) 1514679Sgblack@eecs.umich.edu if ident in self.methods: 152 return False 153 154 self.methods[ident] = func 155 return True 156 157 def addEnum(self, ident, pairs): 158 if ident in self.enums: 159 return False 160 161 self.enums[ident] = Enumeration(ident, pairs) 162 163 # Add default 164 if "default" not in self: 165 self["default"] = "%s_NUM" % self.c_ident 166 167 return True 168 169 ## Used to check if an enum has been already used and therefore 170 ## should not be used again. 171 def checkEnum(self, ident): 172 if ident in self.enums and not self.enums[ident].primary: 173 self.enums[ident].primary = True 174 return True 175 return False 176 177 def writeCodeFiles(self, path, includes): 178 if self.isExternal: 179 # Do nothing 180 pass 181 elif self.isEnumeration: 182 self.printEnumHH(path) 183 self.printEnumCC(path) 184 else: 185 # User defined structs and messages 186 self.printTypeHH(path) 187 self.printTypeCC(path) 188 189 def printTypeHH(self, path): 190 code = self.symtab.codeFormatter() 191 code(''' 192/** \\file ${{self.c_ident}}.hh 193 * 194 * 195 * Auto generated C++ code started by $__file__:$__line__ 196 */ 197 198#ifndef __${{self.c_ident}}_HH__ 199#define __${{self.c_ident}}_HH__ 200 201#include <iostream> 202 203#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 204''') 205 206 for dm in self.data_members.values(): 207 if not dm.type.isPrimitive: 208 code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 209 210 parent = "" 211 if "interface" in self: 212 code('#include "mem/protocol/$0.hh"', self["interface"]) 213 parent = " : public %s" % self["interface"] 214 215 code(''' 216$klass ${{self.c_ident}}$parent 217{ 218 public: 219 ${{self.c_ident}} 220''', klass="class") 221 222 if self.isMessage: 223 code('(Tick curTime) : %s(curTime) {' % self["interface"]) 224 else: 225 code('()\n\t\t{') 226 227 code.indent() 228 if not self.isGlobal: 229 code.indent() 230 for dm in self.data_members.values(): 231 ident = dm.ident 232 if "default" in dm: 233 # look for default value 234 code('m_$ident = ${{dm["default"]}}; // default for this field') 235 elif "default" in dm.type: 236 # Look for the type default 237 tid = dm.type.c_ident 238 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 239 else: 240 code('// m_$ident has no default') 241 code.dedent() 242 code('}') 243 244 # ******** Copy constructor ******** 245 if not self.isGlobal: 246 code('${{self.c_ident}}(const ${{self.c_ident}}&other)') 247 248 # Call superclass constructor 249 if "interface" in self: 250 code(' : ${{self["interface"]}}(other)') 251 252 code('{') 253 code.indent() 254 255 for dm in self.data_members.values(): 256 code('m_${{dm.ident}} = other.m_${{dm.ident}};') 257 258 code.dedent() 259 code('}') 260 261 # ******** Full init constructor ******** 262 if not self.isGlobal: 263 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 264 for dm in self.data_members.itervalues() ] 265 params = ', '.join(params) 266 267 if self.isMessage: 268 params = "const Tick curTime, " + params 269 270 code('${{self.c_ident}}($params)') 271 272 # Call superclass constructor 273 if "interface" in self: 274 if self.isMessage: 275 code(' : ${{self["interface"]}}(curTime)') 276 else: 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 284 code.dedent() 285 code('}') 286 287 # create a clone member 288 if self.isMessage: 289 code(''' 290MsgPtr 291clone() const 292{ 293 return std::shared_ptr<Message>(new ${{self.c_ident}}(*this)); 294} 295''') 296 else: 297 code(''' 298${{self.c_ident}}* 299clone() const 300{ 301 return new ${{self.c_ident}}(*this); 302} 303''') 304 305 if not self.isGlobal: 306 # const Get methods for each field 307 code('// Const accessors methods for each field') 308 for dm in self.data_members.values(): 309 code(''' 310/** \\brief Const accessor method for ${{dm.ident}} field. 311 * \\return ${{dm.ident}} field 312 */ 313const ${{dm.type.c_ident}}& 314get${{dm.ident}}() const 315{ 316 return m_${{dm.ident}}; 317} 318''') 319 320 # Non-const Get methods for each field 321 code('// Non const Accessors methods for each field') 322 for dm in self.data_members.values(): 323 code(''' 324/** \\brief Non-const accessor method for ${{dm.ident}} field. 325 * \\return ${{dm.ident}} field 326 */ 327${{dm.type.c_ident}}& 328get${{dm.ident}}() 329{ 330 return m_${{dm.ident}}; 331} 332''') 333 334 #Set methods for each field 335 code('// Mutator methods for each field') 336 for dm in self.data_members.values(): 337 code(''' 338/** \\brief Mutator method for ${{dm.ident}} field */ 339void 340set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 341{ 342 m_${{dm.ident}} = local_${{dm.ident}}; 343} 344''') 345 346 code('void print(std::ostream& out) const;') 347 code.dedent() 348 code(' //private:') 349 code.indent() 350 351 # Data members for each field 352 for dm in self.data_members.values(): 353 if "abstract" not in dm: 354 const = "" 355 init = "" 356 357 # global structure 358 if self.isGlobal: 359 const = "static const " 360 361 # init value 362 if dm.init_code: 363 # only global structure can have init value here 364 assert self.isGlobal 365 init = " = %s" % (dm.init_code) 366 367 if "desc" in dm: 368 code('/** ${{dm["desc"]}} */') 369 370 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 371 372 # Prototypes for methods defined for the Type 373 for item in self.methods: 374 proto = self.methods[item].prototype 375 if proto: 376 code('$proto') 377 378 code.dedent() 379 code('};') 380 381 code(''' 382inline std::ostream& 383operator<<(std::ostream& out, const ${{self.c_ident}}& obj) 384{ 385 obj.print(out); 386 out << std::flush; 387 return out; 388} 389 390#endif // __${{self.c_ident}}_HH__ 391''') 392 393 code.write(path, "%s.hh" % self.c_ident) 394 395 def printTypeCC(self, path): 396 code = self.symtab.codeFormatter() 397 398 code(''' 399/** \\file ${{self.c_ident}}.cc 400 * 401 * Auto generated C++ code started by $__file__:$__line__ 402 */ 403 404#include <iostream> 405#include <memory> 406 407#include "mem/protocol/${{self.c_ident}}.hh" 408#include "mem/ruby/system/RubySystem.hh" 409 410using namespace std; 411''') 412 413 code(''' 414/** \\brief Print the state of this object */ 415void 416${{self.c_ident}}::print(ostream& out) const 417{ 418 out << "[${{self.c_ident}}: "; 419''') 420 421 # For each field 422 code.indent() 423 for dm in self.data_members.values(): 424 if dm.type.c_ident == "Addr": 425 code(''' 426out << "${{dm.ident}} = " << printAddress(m_${{dm.ident}}) << " ";''') 427 else: 428 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 429 430 code.dedent() 431 432 # Trailer 433 code(''' 434 out << "]"; 435}''') 436 437 # print the code for the methods in the type 438 for item in self.methods: 439 code(self.methods[item].generateCode()) 440 441 code.write(path, "%s.cc" % self.c_ident) 442 443 def printEnumHH(self, path): 444 code = self.symtab.codeFormatter() 445 code(''' 446/** \\file ${{self.c_ident}}.hh 447 * 448 * Auto generated C++ code started by $__file__:$__line__ 449 */ 450 451#ifndef __${{self.c_ident}}_HH__ 452#define __${{self.c_ident}}_HH__ 453 454#include <iostream> 455#include <string> 456 457''') 458 if self.isStateDecl: 459 code('#include "mem/protocol/AccessPermission.hh"') 460 461 if self.isMachineType: 462 code('#include "base/misc.hh"') 463 code('#include "mem/ruby/common/Address.hh"') 464 code('#include "mem/ruby/common/TypeDefines.hh"') 465 code('struct MachineID;') 466 467 code(''' 468 469// Class definition 470/** \\enum ${{self.c_ident}} 471 * \\brief ${{self.desc}} 472 */ 473enum ${{self.c_ident}} { 474 ${{self.c_ident}}_FIRST, 475''') 476 477 code.indent() 478 # For each field 479 for i,(ident,enum) in enumerate(self.enums.iteritems()): 480 desc = enum.get("desc", "No description avaliable") 481 if i == 0: 482 init = ' = %s_FIRST' % self.c_ident 483 else: 484 init = '' 485 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 486 code.dedent() 487 code(''' 488 ${{self.c_ident}}_NUM 489}; 490 491// Code to convert from a string to the enumeration 492${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 493 494// Code to convert state to a string 495std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 496 497// Code to increment an enumeration type 498${{self.c_ident}} &operator++(${{self.c_ident}} &e); 499''') 500 501 # MachineType hack used to set the base component id for each Machine 502 if self.isMachineType: 503 code(''' 504int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 505MachineType ${{self.c_ident}}_from_base_level(int); 506int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 507int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 508''') 509 510 for enum in self.enums.itervalues(): 511 if enum.ident == "DMA": 512 code(''' 513MachineID map_Address_to_DMA(const Addr &addr); 514''') 515 code(''' 516 517MachineID get${{enum.ident}}MachineID(NodeID RubyNode); 518''') 519 520 if self.isStateDecl: 521 code(''' 522 523// Code to convert the current state to an access permission 524AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 525 526''') 527 528 # Trailer 529 code(''' 530std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 531 532#endif // __${{self.c_ident}}_HH__ 533''') 534 535 code.write(path, "%s.hh" % self.c_ident) 536 537 def printEnumCC(self, path): 538 code = self.symtab.codeFormatter() 539 code(''' 540/** \\file ${{self.c_ident}}.hh 541 * 542 * Auto generated C++ code started by $__file__:$__line__ 543 */ 544 545#include <cassert> 546#include <iostream> 547#include <string> 548 549#include "base/misc.hh" 550#include "mem/protocol/${{self.c_ident}}.hh" 551 552using namespace std; 553 554''') 555 556 if self.isStateDecl: 557 code(''' 558// Code to convert the current state to an access permission 559AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 560{ 561 switch(obj) { 562''') 563 # For each case 564 code.indent() 565 for statePerm in self.statePermPairs: 566 code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 567 code(' return AccessPermission_${{statePerm[1]}};') 568 code.dedent() 569 code (''' 570 default: 571 panic("Unknown state access permission converstion for ${{self.c_ident}}"); 572 } 573} 574 575''') 576 577 if self.isMachineType: 578 for enum in self.enums.itervalues(): 579 if enum.primary: 580 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 581 code('#include "mem/ruby/common/MachineID.hh"') 582 583 code(''' 584// Code for output operator 585ostream& 586operator<<(ostream& out, const ${{self.c_ident}}& obj) 587{ 588 out << ${{self.c_ident}}_to_string(obj); 589 out << flush; 590 return out; 591} 592 593// Code to convert state to a string 594string 595${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 596{ 597 switch(obj) { 598''') 599 600 # For each field 601 code.indent() 602 for enum in self.enums.itervalues(): 603 code(' case ${{self.c_ident}}_${{enum.ident}}:') 604 code(' return "${{enum.ident}}";') 605 code.dedent() 606 607 # Trailer 608 code(''' 609 default: 610 panic("Invalid range for type ${{self.c_ident}}"); 611 } 612} 613 614// Code to convert from a string to the enumeration 615${{self.c_ident}} 616string_to_${{self.c_ident}}(const string& str) 617{ 618''') 619 620 # For each field 621 start = "" 622 code.indent() 623 for enum in self.enums.itervalues(): 624 code('${start}if (str == "${{enum.ident}}") {') 625 code(' return ${{self.c_ident}}_${{enum.ident}};') 626 start = "} else " 627 code.dedent() 628 629 code(''' 630 } else { 631 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 632 } 633} 634 635// Code to increment an enumeration type 636${{self.c_ident}}& 637operator++(${{self.c_ident}}& e) 638{ 639 assert(e < ${{self.c_ident}}_NUM); 640 return e = ${{self.c_ident}}(e+1); 641} 642''') 643 644 # MachineType hack used to set the base level and number of 645 # components for each Machine 646 if self.isMachineType: 647 code(''' 648/** \\brief returns the base vector index for each machine type to be 649 * used by NetDest 650 * 651 * \\return the base vector index for each machine type to be used by NetDest 652 * \\see NetDest.hh 653 */ 654int 655${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 656{ 657 switch(obj) { 658''') 659 660 # For each field 661 code.indent() 662 for i,enum in enumerate(self.enums.itervalues()): 663 code(' case ${{self.c_ident}}_${{enum.ident}}:') 664 code(' return $i;') 665 code.dedent() 666 667 # total num 668 code(''' 669 case ${{self.c_ident}}_NUM: 670 return ${{len(self.enums)}}; 671 672 default: 673 panic("Invalid range for type ${{self.c_ident}}"); 674 } 675} 676 677/** \\brief returns the machine type for each base vector index used by NetDest 678 * 679 * \\return the MachineType 680 */ 681MachineType 682${{self.c_ident}}_from_base_level(int type) 683{ 684 switch(type) { 685''') 686 687 # For each field 688 code.indent() 689 for i,enum in enumerate(self.enums.itervalues()): 690 code(' case $i:') 691 code(' return ${{self.c_ident}}_${{enum.ident}};') 692 code.dedent() 693 694 # Trailer 695 code(''' 696 default: 697 panic("Invalid range for type ${{self.c_ident}}"); 698 } 699} 700 701/** \\brief The return value indicates the number of components created 702 * before a particular machine\'s components 703 * 704 * \\return the base number of components for each machine 705 */ 706int 707${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 708{ 709 int base = 0; 710 switch(obj) { 711''') 712 713 # For each field 714 code.indent() 715 code(' case ${{self.c_ident}}_NUM:') 716 for enum in reversed(self.enums.values()): 717 # Check if there is a defined machine with this type 718 if enum.primary: 719 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 720 else: 721 code(' base += 0;') 722 code(' case ${{self.c_ident}}_${{enum.ident}}:') 723 code(' break;') 724 code.dedent() 725 726 code(''' 727 default: 728 panic("Invalid range for type ${{self.c_ident}}"); 729 } 730 731 return base; 732} 733 734/** \\brief returns the total number of components for each machine 735 * \\return the total number of components for each machine 736 */ 737int 738${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 739{ 740 switch(obj) { 741''') 742 743 # For each field 744 for enum in self.enums.itervalues(): 745 code('case ${{self.c_ident}}_${{enum.ident}}:') 746 if enum.primary: 747 code('return ${{enum.ident}}_Controller::getNumControllers();') 748 else: 749 code('return 0;') 750 751 # total num 752 code(''' 753 case ${{self.c_ident}}_NUM: 754 default: 755 panic("Invalid range for type ${{self.c_ident}}"); 756 } 757} 758''') 759 760 for enum in self.enums.itervalues(): 761 if enum.ident == "DMA": 762 code(''' 763MachineID 764map_Address_to_DMA(const Addr &addr) 765{ 766 MachineID dma = {MachineType_DMA, 0}; 767 return dma; 768} 769''') 770 771 code(''' 772 773MachineID 774get${{enum.ident}}MachineID(NodeID RubyNode) 775{ 776 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 777 return mach; 778} 779''') 780 781 # Write the file 782 code.write(path, "%s.cc" % self.c_ident) 783 784__all__ = [ "Type" ] 785