1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 2# Copyright (c) 2009 The Hewlett-Packard Development Company 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28from m5.util import orderdict 29 30from slicc.util import PairContainer 31from slicc.symbols.Symbol import Symbol 32from slicc.symbols.Var import Var 33 34class DataMember(Var): 35 def __init__(self, symtab, ident, location, type, code, pairs, 36 machine, init_code): 37 super(DataMember, self).__init__(symtab, ident, location, type, 38 code, pairs, machine) 39 self.init_code = init_code 40 41class Enumeration(PairContainer): 42 def __init__(self, ident, pairs): 43 super(Enumeration, self).__init__(pairs) 44 self.ident = ident 45 self.primary = False 46 47class Type(Symbol): 48 def __init__(self, table, ident, location, pairs, machine=None): 49 super(Type, self).__init__(table, ident, location, pairs) 50 self.c_ident = ident 51 self.abstract_ident = "" 52 if machine: 53 if self.isExternal or self.isPrimitive: 54 if "external_name" in self: 55 self.c_ident = self["external_name"] 56 else: 57 # Append with machine name 58 self.c_ident = "%s_%s" % (machine, ident) 59 60 self.pairs.setdefault("desc", "No description avaliable") 61 62 # check for interface that this Type implements 63 if "interface" in self: 64 interface = self["interface"] 65 if interface in ("Message"): 66 self["message"] = "yes" 67 68 # FIXME - all of the following id comparisons are fragile hacks 69 if self.ident in ("CacheMemory"): 70 self["cache"] = "yes" 71 72 if self.ident in ("TBETable"): 73 self["tbe"] = "yes" 74 75 if self.ident == "TimerTable": 76 self["timer"] = "yes" 77 78 if self.ident == "DirectoryMemory": 79 self["dir"] = "yes" 80 81 if self.ident == "PersistentTable": 82 self["persistent"] = "yes" 83 84 if self.ident == "Prefetcher": 85 self["prefetcher"] = "yes" 86 87 self.isMachineType = (ident == "MachineType") 88 89 self.isStateDecl = ("state_decl" in self) 90 self.statePermPairs = [] 91 92 self.data_members = orderdict() 93 self.methods = {} 94 self.enums = orderdict() 95 96 @property 97 def isPrimitive(self): 98 return "primitive" in self 99 100 @property 101 def isMessage(self): 102 return "message" in self 103 @property 104 def isBuffer(self): 105 return "buffer" in self 106 @property 107 def isInPort(self): 108 return "inport" in self 109 @property 110 def isOutPort(self): 111 return "outport" in self 112 @property 113 def isEnumeration(self): 114 return "enumeration" in self 115 @property 116 def isExternal(self): 117 return "external" in self 118 @property 119 def isGlobal(self): 120 return "global" in self 121 @property 122 def isInterface(self): 123 return "interface" in self 124 125 # Return false on error 126 def addDataMember(self, ident, type, pairs, init_code): 127 if ident in self.data_members: 128 return False 129 130 member = DataMember(self.symtab, ident, self.location, type, 131 "m_%s" % ident, pairs, None, init_code) 132 133 self.data_members[ident] = member 134 self.symtab.registerSym(ident, member) 135 return True 136 137 def dataMemberType(self, ident): 138 return self.data_members[ident].type 139 140 def methodId(self, name, param_type_vec): 141 return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ]) 142 143 def methodIdAbstract(self, name, param_type_vec): 144 return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ]) 145 146 def statePermPairAdd(self, state_name, perm_name): 147 self.statePermPairs.append([state_name, perm_name]) 148 149 def addFunc(self, func): 150 ident = self.methodId(func.ident, func.param_types) 151 if ident in self.methods: 152 return False 153 154 self.methods[ident] = func 155 return True 156 157 def addEnum(self, ident, pairs): 158 if ident in self.enums: 159 return False 160 161 self.enums[ident] = Enumeration(ident, pairs) 162 163 # Add default 164 if "default" not in self: 165 self["default"] = "%s_NUM" % self.c_ident 166 167 return True 168 169 ## Used to check if an enum has been already used and therefore 170 ## should not be used again. 171 def checkEnum(self, ident): 172 if ident in self.enums and not self.enums[ident].primary: 173 self.enums[ident].primary = True 174 return True 175 return False 176 177 def writeCodeFiles(self, path, includes): 178 if self.isExternal: 179 # Do nothing 180 pass 181 elif self.isEnumeration: 182 self.printEnumHH(path) 183 self.printEnumCC(path) 184 else: 185 # User defined structs and messages 186 self.printTypeHH(path) 187 self.printTypeCC(path) 188 189 def printTypeHH(self, path): 190 code = self.symtab.codeFormatter() 191 code(''' 192/** \\file ${{self.c_ident}}.hh 193 * 194 * 195 * Auto generated C++ code started by $__file__:$__line__ 196 */ 197 198#ifndef __${{self.c_ident}}_HH__ 199#define __${{self.c_ident}}_HH__ 200 201#include <iostream> 202 203#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 204''') 205 206 for dm in self.data_members.values(): 207 if not dm.type.isPrimitive: 208 code('#include "mem/protocol/$0.hh"', dm.type.c_ident) 209 210 parent = "" 211 if "interface" in self: 212 code('#include "mem/protocol/$0.hh"', self["interface"]) 213 parent = " : public %s" % self["interface"] 214 215 code(''' 216$klass ${{self.c_ident}}$parent 217{ 218 public: 219 ${{self.c_ident}} 220''', klass="class") 221 222 if self.isMessage: 223 code('(Tick curTime) : %s(curTime) {' % self["interface"]) 224 else: 225 code('()\n\t\t{') 226 227 code.indent() 228 if not self.isGlobal: 229 code.indent() 230 for dm in self.data_members.values(): 231 ident = dm.ident 232 if "default" in dm: 233 # look for default value 234 code('m_$ident = ${{dm["default"]}}; // default for this field') 235 elif "default" in dm.type: 236 # Look for the type default 237 tid = dm.type.c_ident 238 code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') 239 else: 240 code('// m_$ident has no default') 241 code.dedent() 242 code('}') 243 244 # ******** Copy constructor ******** 245 if not self.isGlobal: 246 code('${{self.c_ident}}(const ${{self.c_ident}}&other)') 247 248 # Call superclass constructor 249 if "interface" in self: 250 code(' : ${{self["interface"]}}(other)') 251 252 code('{') 253 code.indent() 254 255 for dm in self.data_members.values(): 256 code('m_${{dm.ident}} = other.m_${{dm.ident}};') 257 258 code.dedent() 259 code('}') 260 261 # ******** Full init constructor ******** 262 if not self.isGlobal: 263 params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ 264 for dm in self.data_members.itervalues() ] 265 params = ', '.join(params) 266 267 if self.isMessage: 268 params = "const Tick curTime, " + params 269 270 code('${{self.c_ident}}($params)') 271 272 # Call superclass constructor 273 if "interface" in self: 274 if self.isMessage: 275 code(' : ${{self["interface"]}}(curTime)') 276 else: 277 code(' : ${{self["interface"]}}()') 278 279 code('{') 280 code.indent() 281 for dm in self.data_members.values(): 282 code('m_${{dm.ident}} = local_${{dm.ident}};') 283 284 code.dedent() 285 code('}') 286 287 # create a clone member 288 if self.isMessage: 289 code(''' 290MsgPtr 291clone() const 292{ 293 return std::shared_ptr<Message>(new ${{self.c_ident}}(*this)); 294} 295''') 296 else: 297 code(''' 298${{self.c_ident}}* 299clone() const 300{ 301 return new ${{self.c_ident}}(*this); 302} 303''') 304 305 if not self.isGlobal: 306 # const Get methods for each field 307 code('// Const accessors methods for each field') 308 for dm in self.data_members.values(): 309 code(''' 310/** \\brief Const accessor method for ${{dm.ident}} field. 311 * \\return ${{dm.ident}} field 312 */ 313const ${{dm.type.c_ident}}& 314get${{dm.ident}}() const 315{ 316 return m_${{dm.ident}}; 317} 318''') 319 320 # Non-const Get methods for each field 321 code('// Non const Accessors methods for each field') 322 for dm in self.data_members.values(): 323 code(''' 324/** \\brief Non-const accessor method for ${{dm.ident}} field. 325 * \\return ${{dm.ident}} field 326 */ 327${{dm.type.c_ident}}& 328get${{dm.ident}}() 329{ 330 return m_${{dm.ident}}; 331} 332''') 333 334 #Set methods for each field 335 code('// Mutator methods for each field') 336 for dm in self.data_members.values(): 337 code(''' 338/** \\brief Mutator method for ${{dm.ident}} field */ 339void 340set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) 341{ 342 m_${{dm.ident}} = local_${{dm.ident}}; 343} 344''') 345 346 code('void print(std::ostream& out) const;') 347 code.dedent() 348 code(' //private:') 349 code.indent() 350 351 # Data members for each field 352 for dm in self.data_members.values(): 353 if "abstract" not in dm: 354 const = "" 355 init = "" 356 357 # global structure 358 if self.isGlobal: 359 const = "static const " 360 361 # init value 362 if dm.init_code: 363 # only global structure can have init value here 364 assert self.isGlobal 365 init = " = %s" % (dm.init_code) 366 367 if "desc" in dm: 368 code('/** ${{dm["desc"]}} */') 369 370 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') 371 372 # Prototypes for methods defined for the Type 373 for item in self.methods: 374 proto = self.methods[item].prototype 375 if proto: 376 code('$proto') 377 378 code.dedent() 379 code('};') 380 381 code(''' 382inline std::ostream& 383operator<<(std::ostream& out, const ${{self.c_ident}}& obj) 384{ 385 obj.print(out); 386 out << std::flush; 387 return out; 388} 389 390#endif // __${{self.c_ident}}_HH__ 391''') 392 393 code.write(path, "%s.hh" % self.c_ident) 394 395 def printTypeCC(self, path): 396 code = self.symtab.codeFormatter() 397 398 code(''' 399/** \\file ${{self.c_ident}}.cc 400 * 401 * Auto generated C++ code started by $__file__:$__line__ 402 */ 403 404#include <iostream> 405#include <memory> 406 407#include "mem/protocol/${{self.c_ident}}.hh" 408#include "mem/ruby/system/RubySystem.hh" 409 410using namespace std; 411''') 412 413 code(''' 414/** \\brief Print the state of this object */ 415void 416${{self.c_ident}}::print(ostream& out) const 417{ 418 out << "[${{self.c_ident}}: "; 419''') 420 421 # For each field 422 code.indent() 423 for dm in self.data_members.values(): 424 if dm.type.c_ident == "Addr": 425 code(''' 426out << "${{dm.ident}} = " << printAddress(m_${{dm.ident}}) << " ";''') 427 else: 428 code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') 429 430 code.dedent() 431 432 # Trailer 433 code(''' 434 out << "]"; 435}''') 436 437 # print the code for the methods in the type 438 for item in self.methods: 439 code(self.methods[item].generateCode()) 440 441 code.write(path, "%s.cc" % self.c_ident) 442 443 def printEnumHH(self, path): 444 code = self.symtab.codeFormatter() 445 code(''' 446/** \\file ${{self.c_ident}}.hh 447 * 448 * Auto generated C++ code started by $__file__:$__line__ 449 */ 450 451#ifndef __${{self.c_ident}}_HH__ 452#define __${{self.c_ident}}_HH__ 453 454#include <iostream> 455#include <string> 456 457''') 458 if self.isStateDecl: 459 code('#include "mem/protocol/AccessPermission.hh"') 460 461 if self.isMachineType:
|