Type.py (12392:e0dbdf30a2a5) | Type.py (12436:c56112090c61) |
---|---|
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(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 self.primary = False 46 47class Type(Symbol): 48 def __init__(self, table, ident, location, pairs, machine=None): 49 super(Type, self).__init__(table, ident, location, pairs) 50 self.c_ident = ident 51 self.abstract_ident = "" 52 if machine: 53 if self.isExternal or self.isPrimitive: 54 if "external_name" in self: 55 self.c_ident = self["external_name"] 56 else: 57 # Append with machine name 58 self.c_ident = "%s_%s" % (machine, ident) 59 60 self.pairs.setdefault("desc", "No description avaliable") 61 62 # check for interface that this Type implements 63 if "interface" in self: 64 interface = self["interface"] 65 if interface in ("Message"): 66 self["message"] = "yes" 67 68 # FIXME - all of the following id comparisons are fragile hacks 69 if self.ident in ("CacheMemory"): 70 self["cache"] = "yes" 71 72 if self.ident in ("TBETable"): 73 self["tbe"] = "yes" 74 75 if self.ident == "TimerTable": 76 self["timer"] = "yes" 77 78 if self.ident == "DirectoryMemory": 79 self["dir"] = "yes" 80 81 if self.ident == "PersistentTable": 82 self["persistent"] = "yes" 83 84 if self.ident == "Prefetcher": 85 self["prefetcher"] = "yes" 86 87 self.isMachineType = (ident == "MachineType") 88 89 self.isStateDecl = ("state_decl" in self) 90 self.statePermPairs = [] 91 92 self.data_members = orderdict() 93 self.methods = {} 94 self.enums = orderdict() 95 96 @property 97 def isPrimitive(self): 98 return "primitive" in self 99 100 @property 101 def isMessage(self): 102 return "message" in self 103 @property 104 def isBuffer(self): 105 return "buffer" in self 106 @property 107 def isInPort(self): 108 return "inport" in self 109 @property 110 def isOutPort(self): 111 return "outport" in self 112 @property 113 def isEnumeration(self): 114 return "enumeration" in self 115 @property 116 def isExternal(self): 117 return "external" in self 118 @property 119 def isGlobal(self): 120 return "global" in self 121 @property 122 def isInterface(self): 123 return "interface" in self 124 125 # Return false on error 126 def addDataMember(self, ident, type, pairs, init_code): 127 if ident in self.data_members: 128 return False 129 130 member = DataMember(self.symtab, ident, self.location, type, 131 "m_%s" % ident, pairs, None, init_code) 132 133 self.data_members[ident] = member 134 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 ## 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 <functional>') 463 code('#include "base/logging.hh"') 464 code('#include "mem/ruby/common/Address.hh"') 465 code('#include "mem/ruby/common/TypeDefines.hh"') 466 code('struct MachineID;') 467 468 code(''' 469 470// Class definition 471/** \\enum ${{self.c_ident}} 472 * \\brief ${{self.desc}} 473 */ 474enum ${{self.c_ident}} { 475 ${{self.c_ident}}_FIRST, 476''') 477 478 code.indent() 479 # For each field 480 for i,(ident,enum) in enumerate(self.enums.iteritems()): 481 desc = enum.get("desc", "No description avaliable") 482 if i == 0: 483 init = ' = %s_FIRST' % self.c_ident 484 else: 485 init = '' 486 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 487 code.dedent() 488 code(''' 489 ${{self.c_ident}}_NUM 490}; 491 492// Code to convert from a string to the enumeration 493${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 494 495// Code to convert state to a string 496std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 497 498// Code to increment an enumeration type 499${{self.c_ident}} &operator++(${{self.c_ident}} &e); 500''') 501 502 if self.isMachineType: 503 code(''' 504 505// define a hash function for the MachineType class 506namespace std { 507template<> 508struct hash<MachineType> { 509 std::size_t operator()(const MachineType &mtype) const { 510 return hash<size_t>()(static_cast<size_t>(mtype)); 511 } 512}; 513} 514 515''') 516 # MachineType hack used to set the base component id for each Machine 517 if self.isMachineType: 518 code(''' 519int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 520MachineType ${{self.c_ident}}_from_base_level(int); 521int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 522int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 523''') 524 525 for enum in self.enums.itervalues(): | 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(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 self.primary = False 46 47class Type(Symbol): 48 def __init__(self, table, ident, location, pairs, machine=None): 49 super(Type, self).__init__(table, ident, location, pairs) 50 self.c_ident = ident 51 self.abstract_ident = "" 52 if machine: 53 if self.isExternal or self.isPrimitive: 54 if "external_name" in self: 55 self.c_ident = self["external_name"] 56 else: 57 # Append with machine name 58 self.c_ident = "%s_%s" % (machine, ident) 59 60 self.pairs.setdefault("desc", "No description avaliable") 61 62 # check for interface that this Type implements 63 if "interface" in self: 64 interface = self["interface"] 65 if interface in ("Message"): 66 self["message"] = "yes" 67 68 # FIXME - all of the following id comparisons are fragile hacks 69 if self.ident in ("CacheMemory"): 70 self["cache"] = "yes" 71 72 if self.ident in ("TBETable"): 73 self["tbe"] = "yes" 74 75 if self.ident == "TimerTable": 76 self["timer"] = "yes" 77 78 if self.ident == "DirectoryMemory": 79 self["dir"] = "yes" 80 81 if self.ident == "PersistentTable": 82 self["persistent"] = "yes" 83 84 if self.ident == "Prefetcher": 85 self["prefetcher"] = "yes" 86 87 self.isMachineType = (ident == "MachineType") 88 89 self.isStateDecl = ("state_decl" in self) 90 self.statePermPairs = [] 91 92 self.data_members = orderdict() 93 self.methods = {} 94 self.enums = orderdict() 95 96 @property 97 def isPrimitive(self): 98 return "primitive" in self 99 100 @property 101 def isMessage(self): 102 return "message" in self 103 @property 104 def isBuffer(self): 105 return "buffer" in self 106 @property 107 def isInPort(self): 108 return "inport" in self 109 @property 110 def isOutPort(self): 111 return "outport" in self 112 @property 113 def isEnumeration(self): 114 return "enumeration" in self 115 @property 116 def isExternal(self): 117 return "external" in self 118 @property 119 def isGlobal(self): 120 return "global" in self 121 @property 122 def isInterface(self): 123 return "interface" in self 124 125 # Return false on error 126 def addDataMember(self, ident, type, pairs, init_code): 127 if ident in self.data_members: 128 return False 129 130 member = DataMember(self.symtab, ident, self.location, type, 131 "m_%s" % ident, pairs, None, init_code) 132 133 self.data_members[ident] = member 134 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 ## 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 <functional>') 463 code('#include "base/logging.hh"') 464 code('#include "mem/ruby/common/Address.hh"') 465 code('#include "mem/ruby/common/TypeDefines.hh"') 466 code('struct MachineID;') 467 468 code(''' 469 470// Class definition 471/** \\enum ${{self.c_ident}} 472 * \\brief ${{self.desc}} 473 */ 474enum ${{self.c_ident}} { 475 ${{self.c_ident}}_FIRST, 476''') 477 478 code.indent() 479 # For each field 480 for i,(ident,enum) in enumerate(self.enums.iteritems()): 481 desc = enum.get("desc", "No description avaliable") 482 if i == 0: 483 init = ' = %s_FIRST' % self.c_ident 484 else: 485 init = '' 486 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 487 code.dedent() 488 code(''' 489 ${{self.c_ident}}_NUM 490}; 491 492// Code to convert from a string to the enumeration 493${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 494 495// Code to convert state to a string 496std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 497 498// Code to increment an enumeration type 499${{self.c_ident}} &operator++(${{self.c_ident}} &e); 500''') 501 502 if self.isMachineType: 503 code(''' 504 505// define a hash function for the MachineType class 506namespace std { 507template<> 508struct hash<MachineType> { 509 std::size_t operator()(const MachineType &mtype) const { 510 return hash<size_t>()(static_cast<size_t>(mtype)); 511 } 512}; 513} 514 515''') 516 # MachineType hack used to set the base component id for each Machine 517 if self.isMachineType: 518 code(''' 519int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 520MachineType ${{self.c_ident}}_from_base_level(int); 521int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 522int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 523''') 524 525 for enum in self.enums.itervalues(): |
526 if enum.ident == "DMA": 527 code(''' 528MachineID map_Address_to_DMA(const Addr &addr); 529''') | |
530 code(''' 531 532MachineID get${{enum.ident}}MachineID(NodeID RubyNode); 533''') 534 535 if self.isStateDecl: 536 code(''' 537 538// Code to convert the current state to an access permission 539AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 540 541''') 542 543 # Trailer 544 code(''' 545std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 546 547#endif // __${{self.c_ident}}_HH__ 548''') 549 550 code.write(path, "%s.hh" % self.c_ident) 551 552 def printEnumCC(self, path): 553 code = self.symtab.codeFormatter() 554 code(''' 555/** \\file ${{self.c_ident}}.hh 556 * 557 * Auto generated C++ code started by $__file__:$__line__ 558 */ 559 560#include <cassert> 561#include <iostream> 562#include <string> 563 564#include "base/logging.hh" 565#include "mem/protocol/${{self.c_ident}}.hh" 566 567using namespace std; 568 569''') 570 571 if self.isStateDecl: 572 code(''' 573// Code to convert the current state to an access permission 574AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 575{ 576 switch(obj) { 577''') 578 # For each case 579 code.indent() 580 for statePerm in self.statePermPairs: 581 code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 582 code(' return AccessPermission_${{statePerm[1]}};') 583 code.dedent() 584 code (''' 585 default: 586 panic("Unknown state access permission converstion for ${{self.c_ident}}"); 587 } 588} 589 590''') 591 592 if self.isMachineType: 593 for enum in self.enums.itervalues(): 594 if enum.primary: 595 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 596 code('#include "mem/ruby/common/MachineID.hh"') 597 598 code(''' 599// Code for output operator 600ostream& 601operator<<(ostream& out, const ${{self.c_ident}}& obj) 602{ 603 out << ${{self.c_ident}}_to_string(obj); 604 out << flush; 605 return out; 606} 607 608// Code to convert state to a string 609string 610${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 611{ 612 switch(obj) { 613''') 614 615 # For each field 616 code.indent() 617 for enum in self.enums.itervalues(): 618 code(' case ${{self.c_ident}}_${{enum.ident}}:') 619 code(' return "${{enum.ident}}";') 620 code.dedent() 621 622 # Trailer 623 code(''' 624 default: 625 panic("Invalid range for type ${{self.c_ident}}"); 626 } 627} 628 629// Code to convert from a string to the enumeration 630${{self.c_ident}} 631string_to_${{self.c_ident}}(const string& str) 632{ 633''') 634 635 # For each field 636 start = "" 637 code.indent() 638 for enum in self.enums.itervalues(): 639 code('${start}if (str == "${{enum.ident}}") {') 640 code(' return ${{self.c_ident}}_${{enum.ident}};') 641 start = "} else " 642 code.dedent() 643 644 code(''' 645 } else { 646 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 647 } 648} 649 650// Code to increment an enumeration type 651${{self.c_ident}}& 652operator++(${{self.c_ident}}& e) 653{ 654 assert(e < ${{self.c_ident}}_NUM); 655 return e = ${{self.c_ident}}(e+1); 656} 657''') 658 659 # MachineType hack used to set the base level and number of 660 # components for each Machine 661 if self.isMachineType: 662 code(''' 663/** \\brief returns the base vector index for each machine type to be 664 * used by NetDest 665 * 666 * \\return the base vector index for each machine type to be used by NetDest 667 * \\see NetDest.hh 668 */ 669int 670${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 671{ 672 switch(obj) { 673''') 674 675 # For each field 676 code.indent() 677 for i,enum in enumerate(self.enums.itervalues()): 678 code(' case ${{self.c_ident}}_${{enum.ident}}:') 679 code(' return $i;') 680 code.dedent() 681 682 # total num 683 code(''' 684 case ${{self.c_ident}}_NUM: 685 return ${{len(self.enums)}}; 686 687 default: 688 panic("Invalid range for type ${{self.c_ident}}"); 689 } 690} 691 692/** \\brief returns the machine type for each base vector index used by NetDest 693 * 694 * \\return the MachineType 695 */ 696MachineType 697${{self.c_ident}}_from_base_level(int type) 698{ 699 switch(type) { 700''') 701 702 # For each field 703 code.indent() 704 for i,enum in enumerate(self.enums.itervalues()): 705 code(' case $i:') 706 code(' return ${{self.c_ident}}_${{enum.ident}};') 707 code.dedent() 708 709 # Trailer 710 code(''' 711 default: 712 panic("Invalid range for type ${{self.c_ident}}"); 713 } 714} 715 716/** \\brief The return value indicates the number of components created 717 * before a particular machine\'s components 718 * 719 * \\return the base number of components for each machine 720 */ 721int 722${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 723{ 724 int base = 0; 725 switch(obj) { 726''') 727 728 # For each field 729 code.indent() 730 code(' case ${{self.c_ident}}_NUM:') 731 for enum in reversed(self.enums.values()): 732 # Check if there is a defined machine with this type 733 if enum.primary: 734 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 735 else: 736 code(' base += 0;') 737 code(' M5_FALLTHROUGH;') 738 code(' case ${{self.c_ident}}_${{enum.ident}}:') 739 code(' break;') 740 code.dedent() 741 742 code(''' 743 default: 744 panic("Invalid range for type ${{self.c_ident}}"); 745 } 746 747 return base; 748} 749 750/** \\brief returns the total number of components for each machine 751 * \\return the total number of components for each machine 752 */ 753int 754${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 755{ 756 switch(obj) { 757''') 758 759 # For each field 760 for enum in self.enums.itervalues(): 761 code('case ${{self.c_ident}}_${{enum.ident}}:') 762 if enum.primary: 763 code('return ${{enum.ident}}_Controller::getNumControllers();') 764 else: 765 code('return 0;') 766 767 # total num 768 code(''' 769 case ${{self.c_ident}}_NUM: 770 default: 771 panic("Invalid range for type ${{self.c_ident}}"); 772 } 773} 774''') 775 776 for enum in self.enums.itervalues(): | 526 code(''' 527 528MachineID get${{enum.ident}}MachineID(NodeID RubyNode); 529''') 530 531 if self.isStateDecl: 532 code(''' 533 534// Code to convert the current state to an access permission 535AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 536 537''') 538 539 # Trailer 540 code(''' 541std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 542 543#endif // __${{self.c_ident}}_HH__ 544''') 545 546 code.write(path, "%s.hh" % self.c_ident) 547 548 def printEnumCC(self, path): 549 code = self.symtab.codeFormatter() 550 code(''' 551/** \\file ${{self.c_ident}}.hh 552 * 553 * Auto generated C++ code started by $__file__:$__line__ 554 */ 555 556#include <cassert> 557#include <iostream> 558#include <string> 559 560#include "base/logging.hh" 561#include "mem/protocol/${{self.c_ident}}.hh" 562 563using namespace std; 564 565''') 566 567 if self.isStateDecl: 568 code(''' 569// Code to convert the current state to an access permission 570AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 571{ 572 switch(obj) { 573''') 574 # For each case 575 code.indent() 576 for statePerm in self.statePermPairs: 577 code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 578 code(' return AccessPermission_${{statePerm[1]}};') 579 code.dedent() 580 code (''' 581 default: 582 panic("Unknown state access permission converstion for ${{self.c_ident}}"); 583 } 584} 585 586''') 587 588 if self.isMachineType: 589 for enum in self.enums.itervalues(): 590 if enum.primary: 591 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 592 code('#include "mem/ruby/common/MachineID.hh"') 593 594 code(''' 595// Code for output operator 596ostream& 597operator<<(ostream& out, const ${{self.c_ident}}& obj) 598{ 599 out << ${{self.c_ident}}_to_string(obj); 600 out << flush; 601 return out; 602} 603 604// Code to convert state to a string 605string 606${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 607{ 608 switch(obj) { 609''') 610 611 # For each field 612 code.indent() 613 for enum in self.enums.itervalues(): 614 code(' case ${{self.c_ident}}_${{enum.ident}}:') 615 code(' return "${{enum.ident}}";') 616 code.dedent() 617 618 # Trailer 619 code(''' 620 default: 621 panic("Invalid range for type ${{self.c_ident}}"); 622 } 623} 624 625// Code to convert from a string to the enumeration 626${{self.c_ident}} 627string_to_${{self.c_ident}}(const string& str) 628{ 629''') 630 631 # For each field 632 start = "" 633 code.indent() 634 for enum in self.enums.itervalues(): 635 code('${start}if (str == "${{enum.ident}}") {') 636 code(' return ${{self.c_ident}}_${{enum.ident}};') 637 start = "} else " 638 code.dedent() 639 640 code(''' 641 } else { 642 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 643 } 644} 645 646// Code to increment an enumeration type 647${{self.c_ident}}& 648operator++(${{self.c_ident}}& e) 649{ 650 assert(e < ${{self.c_ident}}_NUM); 651 return e = ${{self.c_ident}}(e+1); 652} 653''') 654 655 # MachineType hack used to set the base level and number of 656 # components for each Machine 657 if self.isMachineType: 658 code(''' 659/** \\brief returns the base vector index for each machine type to be 660 * used by NetDest 661 * 662 * \\return the base vector index for each machine type to be used by NetDest 663 * \\see NetDest.hh 664 */ 665int 666${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 667{ 668 switch(obj) { 669''') 670 671 # For each field 672 code.indent() 673 for i,enum in enumerate(self.enums.itervalues()): 674 code(' case ${{self.c_ident}}_${{enum.ident}}:') 675 code(' return $i;') 676 code.dedent() 677 678 # total num 679 code(''' 680 case ${{self.c_ident}}_NUM: 681 return ${{len(self.enums)}}; 682 683 default: 684 panic("Invalid range for type ${{self.c_ident}}"); 685 } 686} 687 688/** \\brief returns the machine type for each base vector index used by NetDest 689 * 690 * \\return the MachineType 691 */ 692MachineType 693${{self.c_ident}}_from_base_level(int type) 694{ 695 switch(type) { 696''') 697 698 # For each field 699 code.indent() 700 for i,enum in enumerate(self.enums.itervalues()): 701 code(' case $i:') 702 code(' return ${{self.c_ident}}_${{enum.ident}};') 703 code.dedent() 704 705 # Trailer 706 code(''' 707 default: 708 panic("Invalid range for type ${{self.c_ident}}"); 709 } 710} 711 712/** \\brief The return value indicates the number of components created 713 * before a particular machine\'s components 714 * 715 * \\return the base number of components for each machine 716 */ 717int 718${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 719{ 720 int base = 0; 721 switch(obj) { 722''') 723 724 # For each field 725 code.indent() 726 code(' case ${{self.c_ident}}_NUM:') 727 for enum in reversed(self.enums.values()): 728 # Check if there is a defined machine with this type 729 if enum.primary: 730 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 731 else: 732 code(' base += 0;') 733 code(' M5_FALLTHROUGH;') 734 code(' case ${{self.c_ident}}_${{enum.ident}}:') 735 code(' break;') 736 code.dedent() 737 738 code(''' 739 default: 740 panic("Invalid range for type ${{self.c_ident}}"); 741 } 742 743 return base; 744} 745 746/** \\brief returns the total number of components for each machine 747 * \\return the total number of components for each machine 748 */ 749int 750${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 751{ 752 switch(obj) { 753''') 754 755 # For each field 756 for enum in self.enums.itervalues(): 757 code('case ${{self.c_ident}}_${{enum.ident}}:') 758 if enum.primary: 759 code('return ${{enum.ident}}_Controller::getNumControllers();') 760 else: 761 code('return 0;') 762 763 # total num 764 code(''' 765 case ${{self.c_ident}}_NUM: 766 default: 767 panic("Invalid range for type ${{self.c_ident}}"); 768 } 769} 770''') 771 772 for enum in self.enums.itervalues(): |
777 if enum.ident == "DMA": 778 code(''' 779MachineID 780map_Address_to_DMA(const Addr &addr) 781{ 782 MachineID dma = {MachineType_DMA, 0}; 783 return dma; 784} 785''') 786 | |
787 code(''' 788 789MachineID 790get${{enum.ident}}MachineID(NodeID RubyNode) 791{ 792 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 793 return mach; 794} 795''') 796 797 # Write the file 798 code.write(path, "%s.cc" % self.c_ident) 799 800__all__ = [ "Type" ] | 773 code(''' 774 775MachineID 776get${{enum.ident}}MachineID(NodeID RubyNode) 777{ 778 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 779 return mach; 780} 781''') 782 783 # Write the file 784 code.write(path, "%s.cc" % self.c_ident) 785 786__all__ = [ "Type" ] |