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 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 Method(object): 47 def __init__(self, return_type, param_types): 48 self.return_type = return_type 49 self.param_types = param_types 50 51class Type(Symbol): 52 def __init__(self, table, ident, location, pairs, machine=None): 53 super(Type, self).__init__(table, ident, location, pairs) 54 self.c_ident = ident 55 self.abstract_ident = "" 56 if machine: 57 if self.isExternal or self.isPrimitive: 58 if "external_name" in self: 59 self.c_ident = self["external_name"] 60 else: 61 # Append with machine name 62 self.c_ident = "%s_%s" % (machine, ident) 63 64 self.pairs.setdefault("desc", "No description avaliable") 65 66 # check for interface that this Type implements 67 if "interface" in self: 68 interface = self["interface"] 69 if interface in ("Message", "NetworkMessage"): 70 self["message"] = "yes" 71 if interface == "NetworkMessage": 72 self["networkmessage"] = "yes" 73 74 # FIXME - all of the following id comparisons are fragile hacks 75 if self.ident in ("CacheMemory", "NewCacheMemory", 76 "TLCCacheMemory", "DNUCACacheMemory", 77 "DNUCABankCacheMemory", "L2BankCacheMemory", 78 "CompressedCacheMemory", "PrefetchCacheMemory"): 79 self["cache"] = "yes" 80 81 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"): 82 self["tbe"] = "yes" 83 84 if self.ident == "NewTBETable": 85 self["newtbe"] = "yes" 86 87 if self.ident == "TimerTable": 88 self["timer"] = "yes" 89 90 if self.ident == "DirectoryMemory": 91 self["dir"] = "yes" 92 93 if self.ident == "PersistentTable": 94 self["persistent"] = "yes" 95 96 if self.ident == "Prefetcher": 97 self["prefetcher"] = "yes" 98 99 if self.ident == "DNUCA_Movement": 100 self["mover"] = "yes" 101 102 self.isMachineType = (ident == "MachineType") 103 104 self.isStateDecl = ("state_decl" in self) 105 self.statePermPairs = [] 106 107 self.data_members = orderdict() 108 109 # Methods 110 self.methods = {} 111 self.functions = {} 112 113 # Enums 114 self.enums = orderdict() 115 116 @property 117 def isPrimitive(self): 118 return "primitive" in self 119 @property 120 def isNetworkMessage(self): 121 return "networkmessage" in self 122 @property 123 def isMessage(self): 124 return "message" in self 125 @property 126 def isBuffer(self): 127 return "buffer" in self 128 @property 129 def isInPort(self): 130 return "inport" in self 131 @property 132 def isOutPort(self): 133 return "outport" in self 134 @property 135 def isEnumeration(self): 136 return "enumeration" in self 137 @property 138 def isExternal(self): 139 return "external" in self 140 @property 141 def isGlobal(self): 142 return "global" in self 143 @property 144 def isInterface(self): 145 return "interface" in self 146 147 # Return false on error 148 def addDataMember(self, ident, type, pairs, init_code): 149 if ident in self.data_members: 150 return False 151 152 member = DataMember(ident, type, pairs, init_code) 153 self.data_members[ident] = member 154 155 var = Var(self.symtab, ident, self.location, type, 156 "m_%s" % ident, {}, None) 157 self.symtab.registerSym(ident, var) 158 return True 159 160 def dataMemberType(self, ident): 161 return self.data_members[ident].type 162 163 def methodId(self, name, param_type_vec): 164 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 165 166 def methodIdAbstract(self, name, param_type_vec): 167 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 168 169 def statePermPairAdd(self, state_name, perm_name): 170 self.statePermPairs.append([state_name, perm_name]) 171 172 def addMethod(self, name, return_type, param_type_vec): 173 ident = self.methodId(name, param_type_vec) 174 if ident in self.methods: 175 return False 176 177 self.methods[ident] = Method(return_type, param_type_vec) 178 return True 179 180 # Ideally either this function or the one above should exist. But 181 # methods and functions have different structures right now. 182 # Hence, these are different, at least for the time being. 183 def addFunc(self, func): 184 ident = self.methodId(func.ident, func.param_types) 185 if ident in self.functions: 186 return False 187 188 self.functions[ident] = func 189 return True 190 191 def addEnum(self, ident, pairs): 192 if ident in self.enums: 193 return False 194 195 self.enums[ident] = Enumeration(ident, pairs) 196 197 # Add default 198 if "default" not in self: 199 self["default"] = "%s_NUM" % self.c_ident 200 201 return True 202 203 def writeCodeFiles(self, path, includes): 204 if self.isExternal: 205 # Do nothing 206 pass 207 elif self.isEnumeration: 208 self.printEnumHH(path) 209 self.printEnumCC(path) 210 else: 211 # User defined structs and messages 212 self.printTypeHH(path) 213 self.printTypeCC(path) 214 215 def printTypeHH(self, path): 216 code = self.symtab.codeFormatter() 217 code(''' 218/** \\file ${{self.c_ident}}.hh 219 * 220 * 221 * Auto generated C++ code started by $__file__:$__line__ 222 */ 223 224#ifndef __${{self.c_ident}}_HH__ 225#define __${{self.c_ident}}_HH__ 226 227#include <iostream> 228 229#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 230''') 231 232 for dm in self.data_members.values(): 233 if not dm.type.isPrimitive: 234 code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 235 236 parent = "" 237 if "interface" in self: 238 code('#include "mem/protocol/$0.hh"', self["interface"]) 239 parent = " : public %s" % self["interface"] 240 241 code(''' 242$klass ${{self.c_ident}}$parent 243{ 244 public: 245 ${{self.c_ident}} 246''', klass="class") 247 248 if self.isMessage: 249 code('(Time curTime) : %s(curTime) {' % self["interface"]) 250 else: 251 code('()\n\t\t{') 252 253 code.indent() 254 if not self.isGlobal: 255 code.indent() 256 for dm in self.data_members.values(): 257 ident = dm.ident 258 if "default" in dm: 259 # look for default value 260 code('m_$ident = ${{dm["default"]}}; // default for this field') 261 elif "default" in dm.type: 262 # Look for the type default 263 tid = dm.type.c_ident 264 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 265 else: 266 code('// m_$ident has no default') 267 code.dedent() 268 code('}') 269 270 # ******** Copy constructor ******** 271 if not self.isGlobal: 272 code('${{self.c_ident}}(const ${{self.c_ident}}&other)') 273 274 # Call superclass constructor 275 if "interface" in self: 276 code(' : ${{self["interface"]}}(other)') 277 278 code('{') 279 code.indent() 280 281 for dm in self.data_members.values(): 282 code('m_${{dm.ident}} = other.m_${{dm.ident}};') 283 284 code.dedent() 285 code('}') 286 287 # ******** Full init constructor ******** 288 if not self.isGlobal: 289 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 290 for dm in self.data_members.itervalues() ] 291 params = ', '.join(params) 292 293 if self.isMessage: 294 params = "const Time curTime, " + params 295 296 code('${{self.c_ident}}($params)') 297 298 # Call superclass constructor 299 if "interface" in self: 300 if self.isMessage: 301 code(' : ${{self["interface"]}}(curTime)') 302 else: 303 code(' : ${{self["interface"]}}()') 304 305 code('{') 306 code.indent() 307 for dm in self.data_members.values(): 308 code('m_${{dm.ident}} = local_${{dm.ident}};') 309 if "nextLineCallHack" in dm: 310 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};') 311 312 code.dedent() 313 code('}') 314 315 # create a clone member 316 code(''' 317${{self.c_ident}}* 318clone() const 319{ 320 return new ${{self.c_ident}}(*this); 321} 322''') 323 324 if not self.isGlobal: 325 # const Get methods for each field 326 code('// Const accessors methods for each field') 327 for dm in self.data_members.values(): 328 code(''' 329/** \\brief Const accessor method for ${{dm.ident}} field. 330 * \\return ${{dm.ident}} field 331 */ 332const ${{dm.type.c_ident}}& 333get${{dm.ident}}() const 334{ 335 return m_${{dm.ident}}; 336} 337''') 338 339 # Non-const Get methods for each field 340 code('// Non const Accessors methods for each field') 341 for dm in self.data_members.values(): 342 code(''' 343/** \\brief Non-const accessor method for ${{dm.ident}} field. 344 * \\return ${{dm.ident}} field 345 */ 346${{dm.type.c_ident}}& 347get${{dm.ident}}() 348{ 349 return m_${{dm.ident}}; 350} 351''') 352 353 #Set methods for each field 354 code('// Mutator methods for each field') 355 for dm in self.data_members.values(): 356 code(''' 357/** \\brief Mutator method for ${{dm.ident}} field */ 358void 359set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 360{ 361 m_${{dm.ident}} = local_${{dm.ident}}; 362} 363''') 364 365 code('void print(std::ostream& out) const;') 366 code.dedent() 367 code(' //private:') 368 code.indent() 369 370 # Data members for each field 371 for dm in self.data_members.values(): 372 if "abstract" not in dm: 373 const = "" 374 init = "" 375 376 # global structure 377 if self.isGlobal: 378 const = "static const " 379 380 # init value 381 if dm.init_code: 382 # only global structure can have init value here 383 assert self.isGlobal 384 init = " = %s" % (dm.init_code) 385 386 if "desc" in dm: 387 code('/** ${{dm["desc"]}} */') 388 389 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 390 391 # Prototypes for functions defined for the Type 392 for item in self.functions: 393 proto = self.functions[item].prototype 394 if proto: 395 code('$proto') 396 397 code.dedent() 398 code('};') 399 400 code(''' 401inline std::ostream& 402operator<<(std::ostream& out, const ${{self.c_ident}}& obj) 403{ 404 obj.print(out); 405 out << std::flush; 406 return out; 407} 408 409#endif // __${{self.c_ident}}_HH__ 410''') 411 412 code.write(path, "%s.hh" % self.c_ident) 413 414 def printTypeCC(self, path): 415 code = self.symtab.codeFormatter() 416 417 code(''' 418/** \\file ${{self.c_ident}}.cc 419 * 420 * Auto generated C++ code started by $__file__:$__line__ 421 */ 422 423#include <iostream> 424 425#include "mem/protocol/${{self.c_ident}}.hh"
| 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 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 Method(object): 47 def __init__(self, return_type, param_types): 48 self.return_type = return_type 49 self.param_types = param_types 50 51class Type(Symbol): 52 def __init__(self, table, ident, location, pairs, machine=None): 53 super(Type, self).__init__(table, ident, location, pairs) 54 self.c_ident = ident 55 self.abstract_ident = "" 56 if machine: 57 if self.isExternal or self.isPrimitive: 58 if "external_name" in self: 59 self.c_ident = self["external_name"] 60 else: 61 # Append with machine name 62 self.c_ident = "%s_%s" % (machine, ident) 63 64 self.pairs.setdefault("desc", "No description avaliable") 65 66 # check for interface that this Type implements 67 if "interface" in self: 68 interface = self["interface"] 69 if interface in ("Message", "NetworkMessage"): 70 self["message"] = "yes" 71 if interface == "NetworkMessage": 72 self["networkmessage"] = "yes" 73 74 # FIXME - all of the following id comparisons are fragile hacks 75 if self.ident in ("CacheMemory", "NewCacheMemory", 76 "TLCCacheMemory", "DNUCACacheMemory", 77 "DNUCABankCacheMemory", "L2BankCacheMemory", 78 "CompressedCacheMemory", "PrefetchCacheMemory"): 79 self["cache"] = "yes" 80 81 if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"): 82 self["tbe"] = "yes" 83 84 if self.ident == "NewTBETable": 85 self["newtbe"] = "yes" 86 87 if self.ident == "TimerTable": 88 self["timer"] = "yes" 89 90 if self.ident == "DirectoryMemory": 91 self["dir"] = "yes" 92 93 if self.ident == "PersistentTable": 94 self["persistent"] = "yes" 95 96 if self.ident == "Prefetcher": 97 self["prefetcher"] = "yes" 98 99 if self.ident == "DNUCA_Movement": 100 self["mover"] = "yes" 101 102 self.isMachineType = (ident == "MachineType") 103 104 self.isStateDecl = ("state_decl" in self) 105 self.statePermPairs = [] 106 107 self.data_members = orderdict() 108 109 # Methods 110 self.methods = {} 111 self.functions = {} 112 113 # Enums 114 self.enums = orderdict() 115 116 @property 117 def isPrimitive(self): 118 return "primitive" in self 119 @property 120 def isNetworkMessage(self): 121 return "networkmessage" in self 122 @property 123 def isMessage(self): 124 return "message" in self 125 @property 126 def isBuffer(self): 127 return "buffer" in self 128 @property 129 def isInPort(self): 130 return "inport" in self 131 @property 132 def isOutPort(self): 133 return "outport" in self 134 @property 135 def isEnumeration(self): 136 return "enumeration" in self 137 @property 138 def isExternal(self): 139 return "external" in self 140 @property 141 def isGlobal(self): 142 return "global" in self 143 @property 144 def isInterface(self): 145 return "interface" in self 146 147 # Return false on error 148 def addDataMember(self, ident, type, pairs, init_code): 149 if ident in self.data_members: 150 return False 151 152 member = DataMember(ident, type, pairs, init_code) 153 self.data_members[ident] = member 154 155 var = Var(self.symtab, ident, self.location, type, 156 "m_%s" % ident, {}, None) 157 self.symtab.registerSym(ident, var) 158 return True 159 160 def dataMemberType(self, ident): 161 return self.data_members[ident].type 162 163 def methodId(self, name, param_type_vec): 164 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 165 166 def methodIdAbstract(self, name, param_type_vec): 167 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 168 169 def statePermPairAdd(self, state_name, perm_name): 170 self.statePermPairs.append([state_name, perm_name]) 171 172 def addMethod(self, name, return_type, param_type_vec): 173 ident = self.methodId(name, param_type_vec) 174 if ident in self.methods: 175 return False 176 177 self.methods[ident] = Method(return_type, param_type_vec) 178 return True 179 180 # Ideally either this function or the one above should exist. But 181 # methods and functions have different structures right now. 182 # Hence, these are different, at least for the time being. 183 def addFunc(self, func): 184 ident = self.methodId(func.ident, func.param_types) 185 if ident in self.functions: 186 return False 187 188 self.functions[ident] = func 189 return True 190 191 def addEnum(self, ident, pairs): 192 if ident in self.enums: 193 return False 194 195 self.enums[ident] = Enumeration(ident, pairs) 196 197 # Add default 198 if "default" not in self: 199 self["default"] = "%s_NUM" % self.c_ident 200 201 return True 202 203 def writeCodeFiles(self, path, includes): 204 if self.isExternal: 205 # Do nothing 206 pass 207 elif self.isEnumeration: 208 self.printEnumHH(path) 209 self.printEnumCC(path) 210 else: 211 # User defined structs and messages 212 self.printTypeHH(path) 213 self.printTypeCC(path) 214 215 def printTypeHH(self, path): 216 code = self.symtab.codeFormatter() 217 code(''' 218/** \\file ${{self.c_ident}}.hh 219 * 220 * 221 * Auto generated C++ code started by $__file__:$__line__ 222 */ 223 224#ifndef __${{self.c_ident}}_HH__ 225#define __${{self.c_ident}}_HH__ 226 227#include <iostream> 228 229#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 230''') 231 232 for dm in self.data_members.values(): 233 if not dm.type.isPrimitive: 234 code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 235 236 parent = "" 237 if "interface" in self: 238 code('#include "mem/protocol/$0.hh"', self["interface"]) 239 parent = " : public %s" % self["interface"] 240 241 code(''' 242$klass ${{self.c_ident}}$parent 243{ 244 public: 245 ${{self.c_ident}} 246''', klass="class") 247 248 if self.isMessage: 249 code('(Time curTime) : %s(curTime) {' % self["interface"]) 250 else: 251 code('()\n\t\t{') 252 253 code.indent() 254 if not self.isGlobal: 255 code.indent() 256 for dm in self.data_members.values(): 257 ident = dm.ident 258 if "default" in dm: 259 # look for default value 260 code('m_$ident = ${{dm["default"]}}; // default for this field') 261 elif "default" in dm.type: 262 # Look for the type default 263 tid = dm.type.c_ident 264 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 265 else: 266 code('// m_$ident has no default') 267 code.dedent() 268 code('}') 269 270 # ******** Copy constructor ******** 271 if not self.isGlobal: 272 code('${{self.c_ident}}(const ${{self.c_ident}}&other)') 273 274 # Call superclass constructor 275 if "interface" in self: 276 code(' : ${{self["interface"]}}(other)') 277 278 code('{') 279 code.indent() 280 281 for dm in self.data_members.values(): 282 code('m_${{dm.ident}} = other.m_${{dm.ident}};') 283 284 code.dedent() 285 code('}') 286 287 # ******** Full init constructor ******** 288 if not self.isGlobal: 289 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 290 for dm in self.data_members.itervalues() ] 291 params = ', '.join(params) 292 293 if self.isMessage: 294 params = "const Time curTime, " + params 295 296 code('${{self.c_ident}}($params)') 297 298 # Call superclass constructor 299 if "interface" in self: 300 if self.isMessage: 301 code(' : ${{self["interface"]}}(curTime)') 302 else: 303 code(' : ${{self["interface"]}}()') 304 305 code('{') 306 code.indent() 307 for dm in self.data_members.values(): 308 code('m_${{dm.ident}} = local_${{dm.ident}};') 309 if "nextLineCallHack" in dm: 310 code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};') 311 312 code.dedent() 313 code('}') 314 315 # create a clone member 316 code(''' 317${{self.c_ident}}* 318clone() const 319{ 320 return new ${{self.c_ident}}(*this); 321} 322''') 323 324 if not self.isGlobal: 325 # const Get methods for each field 326 code('// Const accessors methods for each field') 327 for dm in self.data_members.values(): 328 code(''' 329/** \\brief Const accessor method for ${{dm.ident}} field. 330 * \\return ${{dm.ident}} field 331 */ 332const ${{dm.type.c_ident}}& 333get${{dm.ident}}() const 334{ 335 return m_${{dm.ident}}; 336} 337''') 338 339 # Non-const Get methods for each field 340 code('// Non const Accessors methods for each field') 341 for dm in self.data_members.values(): 342 code(''' 343/** \\brief Non-const accessor method for ${{dm.ident}} field. 344 * \\return ${{dm.ident}} field 345 */ 346${{dm.type.c_ident}}& 347get${{dm.ident}}() 348{ 349 return m_${{dm.ident}}; 350} 351''') 352 353 #Set methods for each field 354 code('// Mutator methods for each field') 355 for dm in self.data_members.values(): 356 code(''' 357/** \\brief Mutator method for ${{dm.ident}} field */ 358void 359set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 360{ 361 m_${{dm.ident}} = local_${{dm.ident}}; 362} 363''') 364 365 code('void print(std::ostream& out) const;') 366 code.dedent() 367 code(' //private:') 368 code.indent() 369 370 # Data members for each field 371 for dm in self.data_members.values(): 372 if "abstract" not in dm: 373 const = "" 374 init = "" 375 376 # global structure 377 if self.isGlobal: 378 const = "static const " 379 380 # init value 381 if dm.init_code: 382 # only global structure can have init value here 383 assert self.isGlobal 384 init = " = %s" % (dm.init_code) 385 386 if "desc" in dm: 387 code('/** ${{dm["desc"]}} */') 388 389 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 390 391 # Prototypes for functions defined for the Type 392 for item in self.functions: 393 proto = self.functions[item].prototype 394 if proto: 395 code('$proto') 396 397 code.dedent() 398 code('};') 399 400 code(''' 401inline std::ostream& 402operator<<(std::ostream& out, const ${{self.c_ident}}& obj) 403{ 404 obj.print(out); 405 out << std::flush; 406 return out; 407} 408 409#endif // __${{self.c_ident}}_HH__ 410''') 411 412 code.write(path, "%s.hh" % self.c_ident) 413 414 def printTypeCC(self, path): 415 code = self.symtab.codeFormatter() 416 417 code(''' 418/** \\file ${{self.c_ident}}.cc 419 * 420 * Auto generated C++ code started by $__file__:$__line__ 421 */ 422 423#include <iostream> 424 425#include "mem/protocol/${{self.c_ident}}.hh"
|
426 427using namespace std; 428''') 429 430 code(''' 431/** \\brief Print the state of this object */ 432void 433${{self.c_ident}}::print(ostream& out) const 434{ 435 out << "[${{self.c_ident}}: "; 436''') 437 438 # For each field 439 code.indent() 440 for dm in self.data_members.values(): 441 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 442 443 if self.isMessage: 444 code('out << "Time = " << g_system_ptr->clockPeriod() * getTime() << " ";') 445 code.dedent() 446 447 # Trailer 448 code(''' 449 out << "]"; 450}''') 451 452 # print the code for the functions in the type 453 for item in self.functions: 454 code(self.functions[item].generateCode()) 455 456 code.write(path, "%s.cc" % self.c_ident) 457 458 def printEnumHH(self, path): 459 code = self.symtab.codeFormatter() 460 code(''' 461/** \\file ${{self.c_ident}}.hh 462 * 463 * Auto generated C++ code started by $__file__:$__line__ 464 */ 465 466#ifndef __${{self.c_ident}}_HH__ 467#define __${{self.c_ident}}_HH__ 468 469#include <iostream> 470#include <string> 471 472''') 473 if self.isStateDecl: 474 code('#include "mem/protocol/AccessPermission.hh"') 475 476 if self.isMachineType: 477 code('#include "base/misc.hh"') 478 code('#include "mem/protocol/GenericMachineType.hh"') 479 code('#include "mem/ruby/common/Address.hh"') 480 code('struct MachineID;') 481 482 code(''' 483 484// Class definition 485/** \\enum ${{self.c_ident}} 486 * \\brief ${{self.desc}} 487 */ 488enum ${{self.c_ident}} { 489 ${{self.c_ident}}_FIRST, 490''') 491 492 code.indent() 493 # For each field 494 for i,(ident,enum) in enumerate(self.enums.iteritems()): 495 desc = enum.get("desc", "No description avaliable") 496 if i == 0: 497 init = ' = %s_FIRST' % self.c_ident 498 else: 499 init = '' 500 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 501 code.dedent() 502 code(''' 503 ${{self.c_ident}}_NUM 504}; 505 506// Code to convert from a string to the enumeration 507${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 508 509// Code to convert state to a string 510std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 511 512// Code to increment an enumeration type 513${{self.c_ident}} &operator++(${{self.c_ident}} &e); 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 Address &addr); 529''') 530 code(''' 531 532MachineID get${{enum.ident}}MachineID(NodeID RubyNode); 533''') 534 535 code(''' 536inline GenericMachineType 537ConvertMachToGenericMach(MachineType machType) 538{ 539''') 540 for enum in self.enums.itervalues(): 541 code(''' 542 if (machType == MachineType_${{enum.ident}}) 543 return GenericMachineType_${{enum.ident}}; 544''') 545 code(''' 546 panic("cannot convert to a GenericMachineType"); 547} 548''') 549 550 if self.isStateDecl: 551 code(''' 552 553// Code to convert the current state to an access permission 554AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 555 556''') 557 558 # Trailer 559 code(''' 560std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 561 562#endif // __${{self.c_ident}}_HH__ 563''') 564 565 code.write(path, "%s.hh" % self.c_ident) 566 567 def printEnumCC(self, path): 568 code = self.symtab.codeFormatter() 569 code(''' 570/** \\file ${{self.c_ident}}.hh 571 * 572 * Auto generated C++ code started by $__file__:$__line__ 573 */ 574 575#include <cassert> 576#include <iostream> 577#include <string> 578 579#include "base/misc.hh" 580#include "mem/protocol/${{self.c_ident}}.hh" 581 582using namespace std; 583 584''') 585 586 if self.isStateDecl: 587 code(''' 588// Code to convert the current state to an access permission 589AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 590{ 591 switch(obj) { 592''') 593 # For each case 594 code.indent() 595 for statePerm in self.statePermPairs: 596 code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 597 code(' return AccessPermission_${{statePerm[1]}};') 598 code.dedent() 599 code (''' 600 default: 601 panic("Unknown state access permission converstion for ${{self.c_ident}}"); 602 } 603} 604 605''') 606 607 if self.isMachineType: 608 for enum in self.enums.itervalues(): 609 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 610 code('#include "mem/ruby/system/MachineID.hh"') 611 612 code(''' 613// Code for output operator 614ostream& 615operator<<(ostream& out, const ${{self.c_ident}}& obj) 616{ 617 out << ${{self.c_ident}}_to_string(obj); 618 out << flush; 619 return out; 620} 621 622// Code to convert state to a string 623string 624${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 625{ 626 switch(obj) { 627''') 628 629 # For each field 630 code.indent() 631 for enum in self.enums.itervalues(): 632 code(' case ${{self.c_ident}}_${{enum.ident}}:') 633 code(' return "${{enum.ident}}";') 634 code.dedent() 635 636 # Trailer 637 code(''' 638 default: 639 panic("Invalid range for type ${{self.c_ident}}"); 640 } 641} 642 643// Code to convert from a string to the enumeration 644${{self.c_ident}} 645string_to_${{self.c_ident}}(const string& str) 646{ 647''') 648 649 # For each field 650 start = "" 651 code.indent() 652 for enum in self.enums.itervalues(): 653 code('${start}if (str == "${{enum.ident}}") {') 654 code(' return ${{self.c_ident}}_${{enum.ident}};') 655 start = "} else " 656 code.dedent() 657 658 code(''' 659 } else { 660 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 661 } 662} 663 664// Code to increment an enumeration type 665${{self.c_ident}}& 666operator++(${{self.c_ident}}& e) 667{ 668 assert(e < ${{self.c_ident}}_NUM); 669 return e = ${{self.c_ident}}(e+1); 670} 671''') 672 673 # MachineType hack used to set the base level and number of 674 # components for each Machine 675 if self.isMachineType: 676 code(''' 677/** \\brief returns the base vector index for each machine type to be 678 * used by NetDest 679 * 680 * \\return the base vector index for each machine type to be used by NetDest 681 * \\see NetDest.hh 682 */ 683int 684${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 685{ 686 switch(obj) { 687''') 688 689 # For each field 690 code.indent() 691 for i,enum in enumerate(self.enums.itervalues()): 692 code(' case ${{self.c_ident}}_${{enum.ident}}:') 693 code(' return $i;') 694 code.dedent() 695 696 # total num 697 code(''' 698 case ${{self.c_ident}}_NUM: 699 return ${{len(self.enums)}}; 700 701 default: 702 panic("Invalid range for type ${{self.c_ident}}"); 703 } 704} 705 706/** \\brief returns the machine type for each base vector index used by NetDest 707 * 708 * \\return the MachineType 709 */ 710MachineType 711${{self.c_ident}}_from_base_level(int type) 712{ 713 switch(type) { 714''') 715 716 # For each field 717 code.indent() 718 for i,enum in enumerate(self.enums.itervalues()): 719 code(' case $i:') 720 code(' return ${{self.c_ident}}_${{enum.ident}};') 721 code.dedent() 722 723 # Trailer 724 code(''' 725 default: 726 panic("Invalid range for type ${{self.c_ident}}"); 727 } 728} 729 730/** \\brief The return value indicates the number of components created 731 * before a particular machine\'s components 732 * 733 * \\return the base number of components for each machine 734 */ 735int 736${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 737{ 738 int base = 0; 739 switch(obj) { 740''') 741 742 # For each field 743 code.indent() 744 code(' case ${{self.c_ident}}_NUM:') 745 for enum in reversed(self.enums.values()): 746 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 747 code(' case ${{self.c_ident}}_${{enum.ident}}:') 748 code(' break;') 749 code.dedent() 750 751 code(''' 752 default: 753 panic("Invalid range for type ${{self.c_ident}}"); 754 } 755 756 return base; 757} 758 759/** \\brief returns the total number of components for each machine 760 * \\return the total number of components for each machine 761 */ 762int 763${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 764{ 765 switch(obj) { 766''') 767 768 # For each field 769 for enum in self.enums.itervalues(): 770 code(''' 771 case ${{self.c_ident}}_${{enum.ident}}: 772 return ${{enum.ident}}_Controller::getNumControllers(); 773''') 774 775 # total num 776 code(''' 777 case ${{self.c_ident}}_NUM: 778 default: 779 panic("Invalid range for type ${{self.c_ident}}"); 780 } 781} 782''') 783 784 for enum in self.enums.itervalues(): 785 if enum.ident == "DMA": 786 code(''' 787MachineID 788map_Address_to_DMA(const Address &addr) 789{ 790 MachineID dma = {MachineType_DMA, 0}; 791 return dma; 792} 793''') 794 795 code(''' 796 797MachineID 798get${{enum.ident}}MachineID(NodeID RubyNode) 799{ 800 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 801 return mach; 802} 803''') 804 805 # Write the file 806 code.write(path, "%s.cc" % self.c_ident) 807 808__all__ = [ "Type" ]
| 428 429using namespace std; 430''') 431 432 code(''' 433/** \\brief Print the state of this object */ 434void 435${{self.c_ident}}::print(ostream& out) const 436{ 437 out << "[${{self.c_ident}}: "; 438''') 439 440 # For each field 441 code.indent() 442 for dm in self.data_members.values(): 443 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 444 445 if self.isMessage: 446 code('out << "Time = " << g_system_ptr->clockPeriod() * getTime() << " ";') 447 code.dedent() 448 449 # Trailer 450 code(''' 451 out << "]"; 452}''') 453 454 # print the code for the functions in the type 455 for item in self.functions: 456 code(self.functions[item].generateCode()) 457 458 code.write(path, "%s.cc" % self.c_ident) 459 460 def printEnumHH(self, path): 461 code = self.symtab.codeFormatter() 462 code(''' 463/** \\file ${{self.c_ident}}.hh 464 * 465 * Auto generated C++ code started by $__file__:$__line__ 466 */ 467 468#ifndef __${{self.c_ident}}_HH__ 469#define __${{self.c_ident}}_HH__ 470 471#include <iostream> 472#include <string> 473 474''') 475 if self.isStateDecl: 476 code('#include "mem/protocol/AccessPermission.hh"') 477 478 if self.isMachineType: 479 code('#include "base/misc.hh"') 480 code('#include "mem/protocol/GenericMachineType.hh"') 481 code('#include "mem/ruby/common/Address.hh"') 482 code('struct MachineID;') 483 484 code(''' 485 486// Class definition 487/** \\enum ${{self.c_ident}} 488 * \\brief ${{self.desc}} 489 */ 490enum ${{self.c_ident}} { 491 ${{self.c_ident}}_FIRST, 492''') 493 494 code.indent() 495 # For each field 496 for i,(ident,enum) in enumerate(self.enums.iteritems()): 497 desc = enum.get("desc", "No description avaliable") 498 if i == 0: 499 init = ' = %s_FIRST' % self.c_ident 500 else: 501 init = '' 502 code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') 503 code.dedent() 504 code(''' 505 ${{self.c_ident}}_NUM 506}; 507 508// Code to convert from a string to the enumeration 509${{self.c_ident}} string_to_${{self.c_ident}}(const std::string& str); 510 511// Code to convert state to a string 512std::string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); 513 514// Code to increment an enumeration type 515${{self.c_ident}} &operator++(${{self.c_ident}} &e); 516''') 517 518 # MachineType hack used to set the base component id for each Machine 519 if self.isMachineType: 520 code(''' 521int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); 522MachineType ${{self.c_ident}}_from_base_level(int); 523int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); 524int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); 525''') 526 527 for enum in self.enums.itervalues(): 528 if enum.ident == "DMA": 529 code(''' 530MachineID map_Address_to_DMA(const Address &addr); 531''') 532 code(''' 533 534MachineID get${{enum.ident}}MachineID(NodeID RubyNode); 535''') 536 537 code(''' 538inline GenericMachineType 539ConvertMachToGenericMach(MachineType machType) 540{ 541''') 542 for enum in self.enums.itervalues(): 543 code(''' 544 if (machType == MachineType_${{enum.ident}}) 545 return GenericMachineType_${{enum.ident}}; 546''') 547 code(''' 548 panic("cannot convert to a GenericMachineType"); 549} 550''') 551 552 if self.isStateDecl: 553 code(''' 554 555// Code to convert the current state to an access permission 556AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj); 557 558''') 559 560 # Trailer 561 code(''' 562std::ostream& operator<<(std::ostream& out, const ${{self.c_ident}}& obj); 563 564#endif // __${{self.c_ident}}_HH__ 565''') 566 567 code.write(path, "%s.hh" % self.c_ident) 568 569 def printEnumCC(self, path): 570 code = self.symtab.codeFormatter() 571 code(''' 572/** \\file ${{self.c_ident}}.hh 573 * 574 * Auto generated C++ code started by $__file__:$__line__ 575 */ 576 577#include <cassert> 578#include <iostream> 579#include <string> 580 581#include "base/misc.hh" 582#include "mem/protocol/${{self.c_ident}}.hh" 583 584using namespace std; 585 586''') 587 588 if self.isStateDecl: 589 code(''' 590// Code to convert the current state to an access permission 591AccessPermission ${{self.c_ident}}_to_permission(const ${{self.c_ident}}& obj) 592{ 593 switch(obj) { 594''') 595 # For each case 596 code.indent() 597 for statePerm in self.statePermPairs: 598 code(' case ${{self.c_ident}}_${{statePerm[0]}}:') 599 code(' return AccessPermission_${{statePerm[1]}};') 600 code.dedent() 601 code (''' 602 default: 603 panic("Unknown state access permission converstion for ${{self.c_ident}}"); 604 } 605} 606 607''') 608 609 if self.isMachineType: 610 for enum in self.enums.itervalues(): 611 code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') 612 code('#include "mem/ruby/system/MachineID.hh"') 613 614 code(''' 615// Code for output operator 616ostream& 617operator<<(ostream& out, const ${{self.c_ident}}& obj) 618{ 619 out << ${{self.c_ident}}_to_string(obj); 620 out << flush; 621 return out; 622} 623 624// Code to convert state to a string 625string 626${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) 627{ 628 switch(obj) { 629''') 630 631 # For each field 632 code.indent() 633 for enum in self.enums.itervalues(): 634 code(' case ${{self.c_ident}}_${{enum.ident}}:') 635 code(' return "${{enum.ident}}";') 636 code.dedent() 637 638 # Trailer 639 code(''' 640 default: 641 panic("Invalid range for type ${{self.c_ident}}"); 642 } 643} 644 645// Code to convert from a string to the enumeration 646${{self.c_ident}} 647string_to_${{self.c_ident}}(const string& str) 648{ 649''') 650 651 # For each field 652 start = "" 653 code.indent() 654 for enum in self.enums.itervalues(): 655 code('${start}if (str == "${{enum.ident}}") {') 656 code(' return ${{self.c_ident}}_${{enum.ident}};') 657 start = "} else " 658 code.dedent() 659 660 code(''' 661 } else { 662 panic("Invalid string conversion for %s, type ${{self.c_ident}}", str); 663 } 664} 665 666// Code to increment an enumeration type 667${{self.c_ident}}& 668operator++(${{self.c_ident}}& e) 669{ 670 assert(e < ${{self.c_ident}}_NUM); 671 return e = ${{self.c_ident}}(e+1); 672} 673''') 674 675 # MachineType hack used to set the base level and number of 676 # components for each Machine 677 if self.isMachineType: 678 code(''' 679/** \\brief returns the base vector index for each machine type to be 680 * used by NetDest 681 * 682 * \\return the base vector index for each machine type to be used by NetDest 683 * \\see NetDest.hh 684 */ 685int 686${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) 687{ 688 switch(obj) { 689''') 690 691 # For each field 692 code.indent() 693 for i,enum in enumerate(self.enums.itervalues()): 694 code(' case ${{self.c_ident}}_${{enum.ident}}:') 695 code(' return $i;') 696 code.dedent() 697 698 # total num 699 code(''' 700 case ${{self.c_ident}}_NUM: 701 return ${{len(self.enums)}}; 702 703 default: 704 panic("Invalid range for type ${{self.c_ident}}"); 705 } 706} 707 708/** \\brief returns the machine type for each base vector index used by NetDest 709 * 710 * \\return the MachineType 711 */ 712MachineType 713${{self.c_ident}}_from_base_level(int type) 714{ 715 switch(type) { 716''') 717 718 # For each field 719 code.indent() 720 for i,enum in enumerate(self.enums.itervalues()): 721 code(' case $i:') 722 code(' return ${{self.c_ident}}_${{enum.ident}};') 723 code.dedent() 724 725 # Trailer 726 code(''' 727 default: 728 panic("Invalid range for type ${{self.c_ident}}"); 729 } 730} 731 732/** \\brief The return value indicates the number of components created 733 * before a particular machine\'s components 734 * 735 * \\return the base number of components for each machine 736 */ 737int 738${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) 739{ 740 int base = 0; 741 switch(obj) { 742''') 743 744 # For each field 745 code.indent() 746 code(' case ${{self.c_ident}}_NUM:') 747 for enum in reversed(self.enums.values()): 748 code(' base += ${{enum.ident}}_Controller::getNumControllers();') 749 code(' case ${{self.c_ident}}_${{enum.ident}}:') 750 code(' break;') 751 code.dedent() 752 753 code(''' 754 default: 755 panic("Invalid range for type ${{self.c_ident}}"); 756 } 757 758 return base; 759} 760 761/** \\brief returns the total number of components for each machine 762 * \\return the total number of components for each machine 763 */ 764int 765${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) 766{ 767 switch(obj) { 768''') 769 770 # For each field 771 for enum in self.enums.itervalues(): 772 code(''' 773 case ${{self.c_ident}}_${{enum.ident}}: 774 return ${{enum.ident}}_Controller::getNumControllers(); 775''') 776 777 # total num 778 code(''' 779 case ${{self.c_ident}}_NUM: 780 default: 781 panic("Invalid range for type ${{self.c_ident}}"); 782 } 783} 784''') 785 786 for enum in self.enums.itervalues(): 787 if enum.ident == "DMA": 788 code(''' 789MachineID 790map_Address_to_DMA(const Address &addr) 791{ 792 MachineID dma = {MachineType_DMA, 0}; 793 return dma; 794} 795''') 796 797 code(''' 798 799MachineID 800get${{enum.ident}}MachineID(NodeID RubyNode) 801{ 802 MachineID mach = {MachineType_${{enum.ident}}, RubyNode}; 803 return mach; 804} 805''') 806 807 # Write the file 808 code.write(path, "%s.cc" % self.c_ident) 809 810__all__ = [ "Type" ]
|