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