1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 2# Copyright (c) 2009 The Hewlett-Packard Development Company 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28from m5.util import orderdict 29 30from slicc.util import PairContainer 31from slicc.symbols.Symbol import Symbol 32from slicc.symbols.Var import Var 33
| 1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 2# Copyright (c) 2009 The Hewlett-Packard Development Company 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28from m5.util import orderdict 29 30from slicc.util import PairContainer 31from slicc.symbols.Symbol import Symbol 32from slicc.symbols.Var import Var 33
|
34class DataMember(PairContainer): 35 def __init__(self, ident, type, pairs, init_code): 36 super(DataMember, self).__init__(pairs) 37 self.ident = ident 38 self.type = type
| 34class DataMember(Var): 35 def __init__(self, symtab, ident, location, type, code, pairs, 36 machine, init_code): 37 super(DataMember, self).__init__(symtab, ident, location, type, 38 code, pairs, machine)
|
39 self.init_code = init_code 40 41class Enumeration(PairContainer): 42 def __init__(self, ident, pairs): 43 super(Enumeration, self).__init__(pairs) 44 self.ident = ident 45 46class Type(Symbol): 47 def __init__(self, table, ident, location, pairs, machine=None): 48 super(Type, self).__init__(table, ident, location, pairs) 49 self.c_ident = ident 50 self.abstract_ident = "" 51 if machine: 52 if self.isExternal or self.isPrimitive: 53 if "external_name" in self: 54 self.c_ident = self["external_name"] 55 else: 56 # Append with machine name 57 self.c_ident = "%s_%s" % (machine, ident) 58 59 self.pairs.setdefault("desc", "No description avaliable") 60 61 # check for interface that this Type implements 62 if "interface" in self: 63 interface = self["interface"] 64 if interface in ("Message"): 65 self["message"] = "yes" 66 67 # FIXME - all of the following id comparisons are fragile hacks 68 if self.ident in ("CacheMemory"): 69 self["cache"] = "yes" 70 71 if self.ident in ("TBETable"): 72 self["tbe"] = "yes" 73 74 if self.ident == "TimerTable": 75 self["timer"] = "yes" 76 77 if self.ident == "DirectoryMemory": 78 self["dir"] = "yes" 79 80 if self.ident == "PersistentTable": 81 self["persistent"] = "yes" 82 83 if self.ident == "Prefetcher": 84 self["prefetcher"] = "yes" 85 86 self.isMachineType = (ident == "MachineType") 87 88 self.isStateDecl = ("state_decl" in self) 89 self.statePermPairs = [] 90 91 self.data_members = orderdict() 92 self.methods = {} 93 self.enums = orderdict() 94 95 @property 96 def isPrimitive(self): 97 return "primitive" in self 98 99 @property 100 def isMessage(self): 101 return "message" in self 102 @property 103 def isBuffer(self): 104 return "buffer" in self 105 @property 106 def isInPort(self): 107 return "inport" in self 108 @property 109 def isOutPort(self): 110 return "outport" in self 111 @property 112 def isEnumeration(self): 113 return "enumeration" in self 114 @property 115 def isExternal(self): 116 return "external" in self 117 @property 118 def isGlobal(self): 119 return "global" in self 120 @property 121 def isInterface(self): 122 return "interface" in self 123 124 # Return false on error 125 def addDataMember(self, ident, type, pairs, init_code): 126 if ident in self.data_members: 127 return False 128
| 39 self.init_code = init_code 40 41class Enumeration(PairContainer): 42 def __init__(self, ident, pairs): 43 super(Enumeration, self).__init__(pairs) 44 self.ident = ident 45 46class Type(Symbol): 47 def __init__(self, table, ident, location, pairs, machine=None): 48 super(Type, self).__init__(table, ident, location, pairs) 49 self.c_ident = ident 50 self.abstract_ident = "" 51 if machine: 52 if self.isExternal or self.isPrimitive: 53 if "external_name" in self: 54 self.c_ident = self["external_name"] 55 else: 56 # Append with machine name 57 self.c_ident = "%s_%s" % (machine, ident) 58 59 self.pairs.setdefault("desc", "No description avaliable") 60 61 # check for interface that this Type implements 62 if "interface" in self: 63 interface = self["interface"] 64 if interface in ("Message"): 65 self["message"] = "yes" 66 67 # FIXME - all of the following id comparisons are fragile hacks 68 if self.ident in ("CacheMemory"): 69 self["cache"] = "yes" 70 71 if self.ident in ("TBETable"): 72 self["tbe"] = "yes" 73 74 if self.ident == "TimerTable": 75 self["timer"] = "yes" 76 77 if self.ident == "DirectoryMemory": 78 self["dir"] = "yes" 79 80 if self.ident == "PersistentTable": 81 self["persistent"] = "yes" 82 83 if self.ident == "Prefetcher": 84 self["prefetcher"] = "yes" 85 86 self.isMachineType = (ident == "MachineType") 87 88 self.isStateDecl = ("state_decl" in self) 89 self.statePermPairs = [] 90 91 self.data_members = orderdict() 92 self.methods = {} 93 self.enums = orderdict() 94 95 @property 96 def isPrimitive(self): 97 return "primitive" in self 98 99 @property 100 def isMessage(self): 101 return "message" in self 102 @property 103 def isBuffer(self): 104 return "buffer" in self 105 @property 106 def isInPort(self): 107 return "inport" in self 108 @property 109 def isOutPort(self): 110 return "outport" in self 111 @property 112 def isEnumeration(self): 113 return "enumeration" in self 114 @property 115 def isExternal(self): 116 return "external" in self 117 @property 118 def isGlobal(self): 119 return "global" in self 120 @property 121 def isInterface(self): 122 return "interface" in self 123 124 # Return false on error 125 def addDataMember(self, ident, type, pairs, init_code): 126 if ident in self.data_members: 127 return False 128
|
129 member = DataMember(ident, type, pairs, init_code) 130 self.data_members[ident] = member
| 129 member = DataMember(self.symtab, ident, self.location, type, 130 "m_%s" % ident, pairs, None, init_code)
|
131
| 131
|
132 var = Var(self.symtab, ident, self.location, type, 133 "m_%s" % ident, {}, None) 134 self.symtab.registerSym(ident, var)
| 132 self.data_members[ident] = member 133 self.symtab.registerSym(ident, member)
|
135 return True 136 137 def dataMemberType(self, ident): 138 return self.data_members[ident].type 139 140 def methodId(self, name, param_type_vec): 141 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 142 143 def methodIdAbstract(self, name, param_type_vec): 144 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 145 146 def statePermPairAdd(self, state_name, perm_name): 147 self.statePermPairs.append([state_name, perm_name]) 148 149 def addFunc(self, func): 150 ident = self.methodId(func.ident, func.param_types) 151 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 def writeCodeFiles(self, path, includes): 170 if self.isExternal: 171 # Do nothing 172 pass 173 elif self.isEnumeration: 174 self.printEnumHH(path) 175 self.printEnumCC(path) 176 else: 177 # User defined structs and messages 178 self.printTypeHH(path) 179 self.printTypeCC(path) 180 181 def printTypeHH(self, path): 182 code = self.symtab.codeFormatter() 183 code(''' 184/** \\file ${{self.c_ident}}.hh 185 * 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 276 code.dedent() 277 code('}') 278 279 # create a clone member 280 if self.isMessage: 281 code(''' 282MsgPtr 283clone() const 284{ 285 return std::shared_ptr<Message>(new ${{self.c_ident}}(*this)); 286} 287''') 288 else: 289 code(''' 290${{self.c_ident}}* 291clone() const 292{ 293 return new ${{self.c_ident}}(*this); 294} 295''') 296 297 if not self.isGlobal: 298 # const Get methods for each field 299 code('// Const accessors methods for each field') 300 for dm in self.data_members.values(): 301 code(''' 302/** \\brief Const accessor method for ${{dm.ident}} field. 303 * \\return ${{dm.ident}} field 304 */ 305const ${{dm.type.c_ident}}& 306get${{dm.ident}}() const 307{ 308 return m_${{dm.ident}}; 309} 310''') 311 312 # Non-const Get methods for each field 313 code('// Non const Accessors methods for each field') 314 for dm in self.data_members.values(): 315 code(''' 316/** \\brief Non-const accessor method for ${{dm.ident}} field. 317 * \\return ${{dm.ident}} field 318 */ 319${{dm.type.c_ident}}& 320get${{dm.ident}}() 321{ 322 return m_${{dm.ident}}; 323} 324''') 325 326 #Set methods for each field 327 code('// Mutator methods for each field') 328 for dm in self.data_members.values(): 329 code(''' 330/** \\brief Mutator method for ${{dm.ident}} field */ 331void 332set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 333{ 334 m_${{dm.ident}} = local_${{dm.ident}}; 335} 336''') 337 338 code('void print(std::ostream& out) const;') 339 code.dedent() 340 code(' //private:') 341 code.indent() 342 343 # Data members for each field 344 for dm in self.data_members.values(): 345 if "abstract" not in dm: 346 const = "" 347 init = "" 348 349 # global structure 350 if self.isGlobal: 351 const = "static const " 352 353 # init value 354 if dm.init_code: 355 # only global structure can have init value here 356 assert self.isGlobal 357 init = " = %s" % (dm.init_code) 358 359 if "desc" in dm: 360 code('/** ${{dm["desc"]}} */') 361 362 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 363 364 # Prototypes for methods defined for the Type 365 for item in self.methods: 366 proto = self.methods[item].prototype 367 if proto: 368 code('$proto') 369 370 code.dedent() 371 code('};') 372 373 code(''' 374inline std::ostream& 375operator<<(std::ostream& out, const ${{self.c_ident}}& obj) 376{ 377 obj.print(out); 378 out << std::flush; 379 return out; 380} 381 382#endif // __${{self.c_ident}}_HH__ 383''') 384 385 code.write(path, "%s.hh" % self.c_ident) 386 387 def printTypeCC(self, path): 388 code = self.symtab.codeFormatter() 389 390 code(''' 391/** \\file ${{self.c_ident}}.cc 392 * 393 * Auto generated C++ code started by $__file__:$__line__ 394 */ 395 396#include <iostream> 397#include <memory> 398 399#include "mem/protocol/${{self.c_ident}}.hh" 400#include "mem/ruby/system/RubySystem.hh" 401 402using namespace std; 403''') 404 405 code(''' 406/** \\brief Print the state of this object */ 407void 408${{self.c_ident}}::print(ostream& out) const 409{ 410 out << "[${{self.c_ident}}: "; 411''') 412 413 # For each field 414 code.indent() 415 for dm in self.data_members.values(): 416 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 417 418 code.dedent() 419 420 # Trailer 421 code(''' 422 out << "]"; 423}''') 424 425 # print the code for the methods in the type 426 for item in self.methods: 427 code(self.methods[item].generateCode()) 428 429 code.write(path, "%s.cc" % self.c_ident) 430 431 def printEnumHH(self, path): 432 code = self.symtab.codeFormatter() 433 code(''' 434/** \\file ${{self.c_ident}}.hh 435 * 436 * Auto generated C++ code started by $__file__:$__line__ 437 */ 438 439#ifndef __${{self.c_ident}}_HH__ 440#define __${{self.c_ident}}_HH__ 441 442#include <iostream> 443#include <string> 444 445''') 446 if self.isStateDecl: 447 code('#include "mem/protocol/AccessPermission.hh"') 448 449 if self.isMachineType: 450 code('#include "base/misc.hh"') 451 code('#include "mem/ruby/common/Address.hh"') 452 code('#include "mem/ruby/common/TypeDefines.hh"') 453 code('struct MachineID;') 454 455 code(''' 456 457// Class definition 458/** \\enum ${{self.c_ident}} 459 * \\brief ${{self.desc}} 460 */ 461enum ${{self.c_ident}} { 462 ${{self.c_ident}}_FIRST, 463''') 464 465 code.indent() 466 # For each field 467 for i,(ident,enum) in enumerate(self.enums.iteritems()): 468 desc = enum.get("desc", "No description avaliable") 469 if i == 0: 470 init = ' = %s_FIRST' % self.c_ident 471 else: 472 init = '' 473 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 474 code.dedent() 475 code(''' 476 ${{self.c_ident}}_NUM 477}; 478 479// Code to convert from a string to the enumeration 480${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 481 482// Code to convert state to a string 483std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 484 485// Code to increment an enumeration type 486${{self.c_ident}} &operator++(${{self.c_ident}} &e); 487''') 488 489 # MachineType hack used to set the base component id for each Machine 490 if self.isMachineType: 491 code(''' 492int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 493MachineType ${{self.c_ident}}_from_base_level(int); 494int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 495int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 496''') 497 498 for enum in self.enums.itervalues(): 499 if enum.ident == "DMA": 500 code(''' 501MachineID map_Address_to_DMA(const Addr &addr); 502''') 503 code(''' 504 505MachineID get${{enum.ident}}MachineID(NodeID RubyNode); 506''') 507 508 if self.isStateDecl: 509 code(''' 510 511// Code to convert the current state to an access permission 512AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 513 514''') 515 516 # Trailer 517 code(''' 518std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 519 520#endif // __${{self.c_ident}}_HH__ 521''') 522 523 code.write(path, "%s.hh" % self.c_ident) 524 525 def printEnumCC(self, path): 526 code = self.symtab.codeFormatter() 527 code(''' 528/** \\file ${{self.c_ident}}.hh 529 * 530 * Auto generated C++ code started by $__file__:$__line__ 531 */ 532 533#include <cassert> 534#include <iostream> 535#include <string> 536 537#include "base/misc.hh" 538#include "mem/protocol/${{self.c_ident}}.hh" 539 540using namespace std; 541 542''') 543 544 if self.isStateDecl: 545 code(''' 546// Code to convert the current state to an access permission 547AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 548{ 549 switch(obj) { 550''') 551 # For each case 552 code.indent() 553 for statePerm in self.statePermPairs: 554 code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 555 code(' return AccessPermission_${{statePerm[1]}};') 556 code.dedent() 557 code (''' 558 default: 559 panic("Unknown state access permission converstion for ${{self.c_ident}}"); 560 } 561} 562 563''') 564 565 if self.isMachineType: 566 for enum in self.enums.itervalues(): 567 if enum.get("Primary"): 568 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 569 code('#include "mem/ruby/common/MachineID.hh"') 570 571 code(''' 572// Code for output operator 573ostream& 574operator<<(ostream& out, const ${{self.c_ident}}& obj) 575{ 576 out << ${{self.c_ident}}_to_string(obj); 577 out << flush; 578 return out; 579} 580 581// Code to convert state to a string 582string 583${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 584{ 585 switch(obj) { 586''') 587 588 # For each field 589 code.indent() 590 for enum in self.enums.itervalues(): 591 code(' case ${{self.c_ident}}_${{enum.ident}}:') 592 code(' return "${{enum.ident}}";') 593 code.dedent() 594 595 # Trailer 596 code(''' 597 default: 598 panic("Invalid range for type ${{self.c_ident}}"); 599 } 600} 601 602// Code to convert from a string to the enumeration 603${{self.c_ident}} 604string_to_${{self.c_ident}}(const string& str) 605{ 606''') 607 608 # For each field 609 start = "" 610 code.indent() 611 for enum in self.enums.itervalues(): 612 code('${start}if (str == "${{enum.ident}}") {') 613 code(' return ${{self.c_ident}}_${{enum.ident}};') 614 start = "} else " 615 code.dedent() 616 617 code(''' 618 } else { 619 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 620 } 621} 622 623// Code to increment an enumeration type 624${{self.c_ident}}& 625operator++(${{self.c_ident}}& e) 626{ 627 assert(e < ${{self.c_ident}}_NUM); 628 return e = ${{self.c_ident}}(e+1); 629} 630''') 631 632 # MachineType hack used to set the base level and number of 633 # components for each Machine 634 if self.isMachineType: 635 code(''' 636/** \\brief returns the base vector index for each machine type to be 637 * used by NetDest 638 * 639 * \\return the base vector index for each machine type to be used by NetDest 640 * \\see NetDest.hh 641 */ 642int 643${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 644{ 645 switch(obj) { 646''') 647 648 # For each field 649 code.indent() 650 for i,enum in enumerate(self.enums.itervalues()): 651 code(' case ${{self.c_ident}}_${{enum.ident}}:') 652 code(' return $i;') 653 code.dedent() 654 655 # total num 656 code(''' 657 case ${{self.c_ident}}_NUM: 658 return ${{len(self.enums)}}; 659 660 default: 661 panic("Invalid range for type ${{self.c_ident}}"); 662 } 663} 664 665/** \\brief returns the machine type for each base vector index used by NetDest 666 * 667 * \\return the MachineType 668 */ 669MachineType 670${{self.c_ident}}_from_base_level(int type) 671{ 672 switch(type) { 673''') 674 675 # For each field 676 code.indent() 677 for i,enum in enumerate(self.enums.itervalues()): 678 code(' case $i:') 679 code(' return ${{self.c_ident}}_${{enum.ident}};') 680 code.dedent() 681 682 # Trailer 683 code(''' 684 default: 685 panic("Invalid range for type ${{self.c_ident}}"); 686 } 687} 688 689/** \\brief The return value indicates the number of components created 690 * before a particular machine\'s components 691 * 692 * \\return the base number of components for each machine 693 */ 694int 695${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 696{ 697 int base = 0; 698 switch(obj) { 699''') 700 701 # For each field 702 code.indent() 703 code(' case ${{self.c_ident}}_NUM:') 704 for enum in reversed(self.enums.values()): 705 # Check if there is a defined machine with this type 706 if enum.get("Primary"): 707 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 708 else: 709 code(' base += 0;') 710 code(' case ${{self.c_ident}}_${{enum.ident}}:') 711 code(' break;') 712 code.dedent() 713 714 code(''' 715 default: 716 panic("Invalid range for type ${{self.c_ident}}"); 717 } 718 719 return base; 720} 721 722/** \\brief returns the total number of components for each machine 723 * \\return the total number of components for each machine 724 */ 725int 726${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 727{ 728 switch(obj) { 729''') 730 731 # For each field 732 for enum in self.enums.itervalues(): 733 code('case ${{self.c_ident}}_${{enum.ident}}:') 734 if enum.get("Primary"): 735 code('return ${{enum.ident}}_Controller::getNumControllers();') 736 else: 737 code('return 0;') 738 739 # total num 740 code(''' 741 case ${{self.c_ident}}_NUM: 742 default: 743 panic("Invalid range for type ${{self.c_ident}}"); 744 } 745} 746''') 747 748 for enum in self.enums.itervalues(): 749 if enum.ident == "DMA": 750 code(''' 751MachineID 752map_Address_to_DMA(const Addr &addr) 753{ 754 MachineID dma = {MachineType_DMA, 0}; 755 return dma; 756} 757''') 758 759 code(''' 760 761MachineID 762get${{enum.ident}}MachineID(NodeID RubyNode) 763{ 764 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 765 return mach; 766} 767''') 768 769 # Write the file 770 code.write(path, "%s.cc" % self.c_ident) 771 772__all__ = [ "Type" ]
| 134 return True 135 136 def dataMemberType(self, ident): 137 return self.data_members[ident].type 138 139 def methodId(self, name, param_type_vec): 140 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 141 142 def methodIdAbstract(self, name, param_type_vec): 143 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 144 145 def statePermPairAdd(self, state_name, perm_name): 146 self.statePermPairs.append([state_name, perm_name]) 147 148 def addFunc(self, func): 149 ident = self.methodId(func.ident, func.param_types) 150 if ident in self.methods: 151 return False 152 153 self.methods[ident] = func 154 return True 155 156 def addEnum(self, ident, pairs): 157 if ident in self.enums: 158 return False 159 160 self.enums[ident] = Enumeration(ident, pairs) 161 162 # Add default 163 if "default" not in self: 164 self["default"] = "%s_NUM" % self.c_ident 165 166 return True 167 168 def writeCodeFiles(self, path, includes): 169 if self.isExternal: 170 # Do nothing 171 pass 172 elif self.isEnumeration: 173 self.printEnumHH(path) 174 self.printEnumCC(path) 175 else: 176 # User defined structs and messages 177 self.printTypeHH(path) 178 self.printTypeCC(path) 179 180 def printTypeHH(self, path): 181 code = self.symtab.codeFormatter() 182 code(''' 183/** \\file ${{self.c_ident}}.hh 184 * 185 * 186 * Auto generated C++ code started by $__file__:$__line__ 187 */ 188 189#ifndef __${{self.c_ident}}_HH__ 190#define __${{self.c_ident}}_HH__ 191 192#include <iostream> 193 194#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 195''') 196 197 for dm in self.data_members.values(): 198 if not dm.type.isPrimitive: 199 code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 200 201 parent = "" 202 if "interface" in self: 203 code('#include "mem/protocol/$0.hh"', self["interface"]) 204 parent = " : public %s" % self["interface"] 205 206 code(''' 207$klass ${{self.c_ident}}$parent 208{ 209 public: 210 ${{self.c_ident}} 211''', klass="class") 212 213 if self.isMessage: 214 code('(Tick curTime) : %s(curTime) {' % self["interface"]) 215 else: 216 code('()\n\t\t{') 217 218 code.indent() 219 if not self.isGlobal: 220 code.indent() 221 for dm in self.data_members.values(): 222 ident = dm.ident 223 if "default" in dm: 224 # look for default value 225 code('m_$ident = ${{dm["default"]}}; // default for this field') 226 elif "default" in dm.type: 227 # Look for the type default 228 tid = dm.type.c_ident 229 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 230 else: 231 code('// m_$ident has no default') 232 code.dedent() 233 code('}') 234 235 # ******** Copy constructor ******** 236 if not self.isGlobal: 237 code('${{self.c_ident}}(const ${{self.c_ident}}&other)') 238 239 # Call superclass constructor 240 if "interface" in self: 241 code(' : ${{self["interface"]}}(other)') 242 243 code('{') 244 code.indent() 245 246 for dm in self.data_members.values(): 247 code('m_${{dm.ident}} = other.m_${{dm.ident}};') 248 249 code.dedent() 250 code('}') 251 252 # ******** Full init constructor ******** 253 if not self.isGlobal: 254 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 255 for dm in self.data_members.itervalues() ] 256 params = ', '.join(params) 257 258 if self.isMessage: 259 params = "const Tick curTime, " + params 260 261 code('${{self.c_ident}}($params)') 262 263 # Call superclass constructor 264 if "interface" in self: 265 if self.isMessage: 266 code(' : ${{self["interface"]}}(curTime)') 267 else: 268 code(' : ${{self["interface"]}}()') 269 270 code('{') 271 code.indent() 272 for dm in self.data_members.values(): 273 code('m_${{dm.ident}} = local_${{dm.ident}};') 274 275 code.dedent() 276 code('}') 277 278 # create a clone member 279 if self.isMessage: 280 code(''' 281MsgPtr 282clone() const 283{ 284 return std::shared_ptr<Message>(new ${{self.c_ident}}(*this)); 285} 286''') 287 else: 288 code(''' 289${{self.c_ident}}* 290clone() const 291{ 292 return new ${{self.c_ident}}(*this); 293} 294''') 295 296 if not self.isGlobal: 297 # const Get methods for each field 298 code('// Const accessors methods for each field') 299 for dm in self.data_members.values(): 300 code(''' 301/** \\brief Const accessor method for ${{dm.ident}} field. 302 * \\return ${{dm.ident}} field 303 */ 304const ${{dm.type.c_ident}}& 305get${{dm.ident}}() const 306{ 307 return m_${{dm.ident}}; 308} 309''') 310 311 # Non-const Get methods for each field 312 code('// Non const Accessors methods for each field') 313 for dm in self.data_members.values(): 314 code(''' 315/** \\brief Non-const accessor method for ${{dm.ident}} field. 316 * \\return ${{dm.ident}} field 317 */ 318${{dm.type.c_ident}}& 319get${{dm.ident}}() 320{ 321 return m_${{dm.ident}}; 322} 323''') 324 325 #Set methods for each field 326 code('// Mutator methods for each field') 327 for dm in self.data_members.values(): 328 code(''' 329/** \\brief Mutator method for ${{dm.ident}} field */ 330void 331set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 332{ 333 m_${{dm.ident}} = local_${{dm.ident}}; 334} 335''') 336 337 code('void print(std::ostream& out) const;') 338 code.dedent() 339 code(' //private:') 340 code.indent() 341 342 # Data members for each field 343 for dm in self.data_members.values(): 344 if "abstract" not in dm: 345 const = "" 346 init = "" 347 348 # global structure 349 if self.isGlobal: 350 const = "static const " 351 352 # init value 353 if dm.init_code: 354 # only global structure can have init value here 355 assert self.isGlobal 356 init = " = %s" % (dm.init_code) 357 358 if "desc" in dm: 359 code('/** ${{dm["desc"]}} */') 360 361 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 362 363 # Prototypes for methods defined for the Type 364 for item in self.methods: 365 proto = self.methods[item].prototype 366 if proto: 367 code('$proto') 368 369 code.dedent() 370 code('};') 371 372 code(''' 373inline std::ostream& 374operator<<(std::ostream& out, const ${{self.c_ident}}& obj) 375{ 376 obj.print(out); 377 out << std::flush; 378 return out; 379} 380 381#endif // __${{self.c_ident}}_HH__ 382''') 383 384 code.write(path, "%s.hh" % self.c_ident) 385 386 def printTypeCC(self, path): 387 code = self.symtab.codeFormatter() 388 389 code(''' 390/** \\file ${{self.c_ident}}.cc 391 * 392 * Auto generated C++ code started by $__file__:$__line__ 393 */ 394 395#include <iostream> 396#include <memory> 397 398#include "mem/protocol/${{self.c_ident}}.hh" 399#include "mem/ruby/system/RubySystem.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 code.dedent() 418 419 # Trailer 420 code(''' 421 out << "]"; 422}''') 423 424 # print the code for the methods in the type 425 for item in self.methods: 426 code(self.methods[item].generateCode()) 427 428 code.write(path, "%s.cc" % self.c_ident) 429 430 def printEnumHH(self, path): 431 code = self.symtab.codeFormatter() 432 code(''' 433/** \\file ${{self.c_ident}}.hh 434 * 435 * Auto generated C++ code started by $__file__:$__line__ 436 */ 437 438#ifndef __${{self.c_ident}}_HH__ 439#define __${{self.c_ident}}_HH__ 440 441#include <iostream> 442#include <string> 443 444''') 445 if self.isStateDecl: 446 code('#include "mem/protocol/AccessPermission.hh"') 447 448 if self.isMachineType: 449 code('#include "base/misc.hh"') 450 code('#include "mem/ruby/common/Address.hh"') 451 code('#include "mem/ruby/common/TypeDefines.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 Addr &addr); 501''') 502 code(''' 503 504MachineID get${{enum.ident}}MachineID(NodeID RubyNode); 505''') 506 507 if self.isStateDecl: 508 code(''' 509 510// Code to convert the current state to an access permission 511AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 512 513''') 514 515 # Trailer 516 code(''' 517std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 518 519#endif // __${{self.c_ident}}_HH__ 520''') 521 522 code.write(path, "%s.hh" % self.c_ident) 523 524 def printEnumCC(self, path): 525 code = self.symtab.codeFormatter() 526 code(''' 527/** \\file ${{self.c_ident}}.hh 528 * 529 * Auto generated C++ code started by $__file__:$__line__ 530 */ 531 532#include <cassert> 533#include <iostream> 534#include <string> 535 536#include "base/misc.hh" 537#include "mem/protocol/${{self.c_ident}}.hh" 538 539using namespace std; 540 541''') 542 543 if self.isStateDecl: 544 code(''' 545// Code to convert the current state to an access permission 546AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 547{ 548 switch(obj) { 549''') 550 # For each case 551 code.indent() 552 for statePerm in self.statePermPairs: 553 code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 554 code(' return AccessPermission_${{statePerm[1]}};') 555 code.dedent() 556 code (''' 557 default: 558 panic("Unknown state access permission converstion for ${{self.c_ident}}"); 559 } 560} 561 562''') 563 564 if self.isMachineType: 565 for enum in self.enums.itervalues(): 566 if enum.get("Primary"): 567 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 568 code('#include "mem/ruby/common/MachineID.hh"') 569 570 code(''' 571// Code for output operator 572ostream& 573operator<<(ostream& out, const ${{self.c_ident}}& obj) 574{ 575 out << ${{self.c_ident}}_to_string(obj); 576 out << flush; 577 return out; 578} 579 580// Code to convert state to a string 581string 582${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 583{ 584 switch(obj) { 585''') 586 587 # For each field 588 code.indent() 589 for enum in self.enums.itervalues(): 590 code(' case ${{self.c_ident}}_${{enum.ident}}:') 591 code(' return "${{enum.ident}}";') 592 code.dedent() 593 594 # Trailer 595 code(''' 596 default: 597 panic("Invalid range for type ${{self.c_ident}}"); 598 } 599} 600 601// Code to convert from a string to the enumeration 602${{self.c_ident}} 603string_to_${{self.c_ident}}(const string& str) 604{ 605''') 606 607 # For each field 608 start = "" 609 code.indent() 610 for enum in self.enums.itervalues(): 611 code('${start}if (str == "${{enum.ident}}") {') 612 code(' return ${{self.c_ident}}_${{enum.ident}};') 613 start = "} else " 614 code.dedent() 615 616 code(''' 617 } else { 618 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 619 } 620} 621 622// Code to increment an enumeration type 623${{self.c_ident}}& 624operator++(${{self.c_ident}}& e) 625{ 626 assert(e < ${{self.c_ident}}_NUM); 627 return e = ${{self.c_ident}}(e+1); 628} 629''') 630 631 # MachineType hack used to set the base level and number of 632 # components for each Machine 633 if self.isMachineType: 634 code(''' 635/** \\brief returns the base vector index for each machine type to be 636 * used by NetDest 637 * 638 * \\return the base vector index for each machine type to be used by NetDest 639 * \\see NetDest.hh 640 */ 641int 642${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 643{ 644 switch(obj) { 645''') 646 647 # For each field 648 code.indent() 649 for i,enum in enumerate(self.enums.itervalues()): 650 code(' case ${{self.c_ident}}_${{enum.ident}}:') 651 code(' return $i;') 652 code.dedent() 653 654 # total num 655 code(''' 656 case ${{self.c_ident}}_NUM: 657 return ${{len(self.enums)}}; 658 659 default: 660 panic("Invalid range for type ${{self.c_ident}}"); 661 } 662} 663 664/** \\brief returns the machine type for each base vector index used by NetDest 665 * 666 * \\return the MachineType 667 */ 668MachineType 669${{self.c_ident}}_from_base_level(int type) 670{ 671 switch(type) { 672''') 673 674 # For each field 675 code.indent() 676 for i,enum in enumerate(self.enums.itervalues()): 677 code(' case $i:') 678 code(' return ${{self.c_ident}}_${{enum.ident}};') 679 code.dedent() 680 681 # Trailer 682 code(''' 683 default: 684 panic("Invalid range for type ${{self.c_ident}}"); 685 } 686} 687 688/** \\brief The return value indicates the number of components created 689 * before a particular machine\'s components 690 * 691 * \\return the base number of components for each machine 692 */ 693int 694${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 695{ 696 int base = 0; 697 switch(obj) { 698''') 699 700 # For each field 701 code.indent() 702 code(' case ${{self.c_ident}}_NUM:') 703 for enum in reversed(self.enums.values()): 704 # Check if there is a defined machine with this type 705 if enum.get("Primary"): 706 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 707 else: 708 code(' base += 0;') 709 code(' case ${{self.c_ident}}_${{enum.ident}}:') 710 code(' break;') 711 code.dedent() 712 713 code(''' 714 default: 715 panic("Invalid range for type ${{self.c_ident}}"); 716 } 717 718 return base; 719} 720 721/** \\brief returns the total number of components for each machine 722 * \\return the total number of components for each machine 723 */ 724int 725${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 726{ 727 switch(obj) { 728''') 729 730 # For each field 731 for enum in self.enums.itervalues(): 732 code('case ${{self.c_ident}}_${{enum.ident}}:') 733 if enum.get("Primary"): 734 code('return ${{enum.ident}}_Controller::getNumControllers();') 735 else: 736 code('return 0;') 737 738 # total num 739 code(''' 740 case ${{self.c_ident}}_NUM: 741 default: 742 panic("Invalid range for type ${{self.c_ident}}"); 743 } 744} 745''') 746 747 for enum in self.enums.itervalues(): 748 if enum.ident == "DMA": 749 code(''' 750MachineID 751map_Address_to_DMA(const Addr &addr) 752{ 753 MachineID dma = {MachineType_DMA, 0}; 754 return dma; 755} 756''') 757 758 code(''' 759 760MachineID 761get${{enum.ident}}MachineID(NodeID RubyNode) 762{ 763 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 764 return mach; 765} 766''') 767 768 # Write the file 769 code.write(path, "%s.cc" % self.c_ident) 770 771__all__ = [ "Type" ]
|