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