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