47 48class StateMachine(Symbol): 49 def __init__(self, symtab, ident, location, pairs, config_parameters): 50 super(StateMachine, self).__init__(symtab, ident, location, pairs) 51 self.table = None 52 self.config_parameters = config_parameters 53 self.prefetchers = [] 54 55 for param in config_parameters: 56 if param.pointer: 57 var = Var(symtab, param.name, location, param.type_ast.type, 58 "(*m_%s_ptr)" % param.name, {}, self) 59 else: 60 var = Var(symtab, param.name, location, param.type_ast.type, 61 "m_%s" % param.name, {}, self) 62 self.symtab.registerSym(param.name, var) 63 if str(param.type_ast.type) == "Prefetcher": 64 self.prefetchers.append(var) 65 66 self.states = orderdict() 67 self.events = orderdict() 68 self.actions = orderdict() 69 self.request_types = orderdict() 70 self.transitions = [] 71 self.in_ports = [] 72 self.functions = [] 73 self.objects = [] 74 self.TBEType = None 75 self.EntryType = None 76 self.message_buffer_names = [] 77 78 79 def __repr__(self): 80 return "[StateMachine: %s]" % self.ident 81 82 def addState(self, state): 83 assert self.table is None 84 self.states[state.ident] = state 85 86 def addEvent(self, event): 87 assert self.table is None 88 self.events[event.ident] = event 89 90 def addAction(self, action): 91 assert self.table is None 92 93 # Check for duplicate action 94 for other in self.actions.itervalues(): 95 if action.ident == other.ident: 96 action.warning("Duplicate action definition: %s" % action.ident) 97 action.error("Duplicate action definition: %s" % action.ident) 98 if action.short == other.short: 99 other.warning("Duplicate action shorthand: %s" % other.ident) 100 other.warning(" shorthand = %s" % other.short) 101 action.warning("Duplicate action shorthand: %s" % action.ident) 102 action.error(" shorthand = %s" % action.short) 103 104 self.actions[action.ident] = action 105 106 def addRequestType(self, request_type): 107 assert self.table is None 108 self.request_types[request_type.ident] = request_type 109 110 def addTransition(self, trans): 111 assert self.table is None 112 self.transitions.append(trans) 113 114 def addInPort(self, var): 115 self.in_ports.append(var) 116 117 def addFunc(self, func): 118 # register func in the symbol table 119 self.symtab.registerSym(str(func), func) 120 self.functions.append(func) 121 122 def addObject(self, obj): 123 self.objects.append(obj) 124 125 def addType(self, type): 126 type_ident = '%s' % type.c_ident 127 128 if type_ident == "%s_TBE" %self.ident: 129 if self.TBEType != None: 130 self.error("Multiple Transaction Buffer types in a " \ 131 "single machine."); 132 self.TBEType = type 133 134 elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 135 if self.EntryType != None: 136 self.error("Multiple AbstractCacheEntry types in a " \ 137 "single machine."); 138 self.EntryType = type 139 140 # Needs to be called before accessing the table 141 def buildTable(self): 142 assert self.table is None 143 144 table = {} 145 146 for trans in self.transitions: 147 # Track which actions we touch so we know if we use them 148 # all -- really this should be done for all symbols as 149 # part of the symbol table, then only trigger it for 150 # Actions, States, Events, etc. 151 152 for action in trans.actions: 153 action.used = True 154 155 index = (trans.state, trans.event) 156 if index in table: 157 table[index].warning("Duplicate transition: %s" % table[index]) 158 trans.error("Duplicate transition: %s" % trans) 159 table[index] = trans 160 161 # Look at all actions to make sure we used them all 162 for action in self.actions.itervalues(): 163 if not action.used: 164 error_msg = "Unused action: %s" % action.ident 165 if "desc" in action: 166 error_msg += ", " + action.desc 167 action.warning(error_msg) 168 self.table = table 169 170 def writeCodeFiles(self, path, includes): 171 self.printControllerPython(path) 172 self.printControllerHH(path) 173 self.printControllerCC(path, includes) 174 self.printCSwitch(path) 175 self.printCWakeup(path, includes) 176 self.printProfilerCC(path) 177 self.printProfilerHH(path) 178 self.printProfileDumperCC(path) 179 self.printProfileDumperHH(path) 180 181 def printControllerPython(self, path): 182 code = self.symtab.codeFormatter() 183 ident = self.ident 184 py_ident = "%s_Controller" % ident 185 c_ident = "%s_Controller" % self.ident 186 code(''' 187from m5.params import * 188from m5.SimObject import SimObject 189from Controller import RubyController 190 191class $py_ident(RubyController): 192 type = '$py_ident' 193 cxx_header = 'mem/protocol/${c_ident}.hh' 194''') 195 code.indent() 196 for param in self.config_parameters: 197 dflt_str = '' 198 if param.default is not None: 199 dflt_str = str(param.default) + ', ' 200 if python_class_map.has_key(param.type_ast.type.c_ident): 201 python_type = python_class_map[param.type_ast.type.c_ident] 202 code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")') 203 else: 204 self.error("Unknown c++ to python class conversion for c++ " \ 205 "type: '%s'. Please update the python_class_map " \ 206 "in StateMachine.py", param.type_ast.type.c_ident) 207 code.dedent() 208 code.write(path, '%s.py' % py_ident) 209 210 211 def printControllerHH(self, path): 212 '''Output the method declarations for the class declaration''' 213 code = self.symtab.codeFormatter() 214 ident = self.ident 215 c_ident = "%s_Controller" % self.ident 216 217 self.message_buffer_names = [] 218 219 code(''' 220/** \\file $c_ident.hh 221 * 222 * Auto generated C++ code started by $__file__:$__line__ 223 * Created by slicc definition of Module "${{self.short}}" 224 */ 225 226#ifndef __${ident}_CONTROLLER_HH__ 227#define __${ident}_CONTROLLER_HH__ 228 229#include <iostream> 230#include <sstream> 231#include <string> 232 233#include "mem/protocol/${ident}_ProfileDumper.hh" 234#include "mem/protocol/${ident}_Profiler.hh" 235#include "mem/protocol/TransitionResult.hh" 236#include "mem/protocol/Types.hh" 237#include "mem/ruby/common/Consumer.hh" 238#include "mem/ruby/common/Global.hh" 239#include "mem/ruby/slicc_interface/AbstractController.hh" 240#include "params/$c_ident.hh" 241''') 242 243 seen_types = set() 244 for var in self.objects: 245 if var.type.ident not in seen_types and not var.type.isPrimitive: 246 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 247 seen_types.add(var.type.ident) 248 249 # for adding information to the protocol debug trace 250 code(''' 251extern std::stringstream ${ident}_transitionComment; 252 253class $c_ident : public AbstractController 254{ 255 public: 256 typedef ${c_ident}Params Params; 257 $c_ident(const Params *p); 258 static int getNumControllers(); 259 void init(); 260 MessageBuffer* getMandatoryQueue() const; 261 const int & getVersion() const; 262 const std::string toString() const; 263 const std::string getName() const; 264 void stallBuffer(MessageBuffer* buf, Address addr); 265 void wakeUpBuffers(Address addr); 266 void wakeUpAllBuffers(); 267 void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; } 268 void print(std::ostream& out) const; 269 void wakeup(); 270 void printStats(std::ostream& out) const; 271 void clearStats(); 272 void blockOnQueue(Address addr, MessageBuffer* port); 273 void unblock(Address addr); 274 void recordCacheTrace(int cntrl, CacheRecorder* tr); 275 Sequencer* getSequencer() const; 276 277 bool functionalReadBuffers(PacketPtr&); 278 uint32_t functionalWriteBuffers(PacketPtr&); 279 280private: 281''') 282 283 code.indent() 284 # added by SS 285 for param in self.config_parameters: 286 if param.pointer: 287 code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 288 else: 289 code('${{param.type_ast.type}} m_${{param.ident}};') 290 291 code(''' 292TransitionResult doTransition(${ident}_Event event, 293''') 294 295 if self.EntryType != None: 296 code(''' 297 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 298''') 299 if self.TBEType != None: 300 code(''' 301 ${{self.TBEType.c_ident}}* m_tbe_ptr, 302''') 303 304 code(''' 305 const Address& addr); 306 307TransitionResult doTransitionWorker(${ident}_Event event, 308 ${ident}_State state, 309 ${ident}_State& next_state, 310''') 311 312 if self.TBEType != None: 313 code(''' 314 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 315''') 316 if self.EntryType != None: 317 code(''' 318 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 319''') 320 321 code(''' 322 const Address& addr); 323 324static ${ident}_ProfileDumper s_profileDumper; 325${ident}_Profiler m_profiler; 326static int m_num_controllers; 327 328// Internal functions 329''') 330 331 for func in self.functions: 332 proto = func.prototype 333 if proto: 334 code('$proto') 335 336 if self.EntryType != None: 337 code(''' 338 339// Set and Reset for cache_entry variable 340void set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 341void unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 342''') 343 344 if self.TBEType != None: 345 code(''' 346 347// Set and Reset for tbe variable 348void set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 349void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 350''') 351 352 code(''' 353 354// Actions 355''') 356 if self.TBEType != None and self.EntryType != None: 357 for action in self.actions.itervalues(): 358 code('/** \\brief ${{action.desc}} */') 359 code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 360 elif self.TBEType != None: 361 for action in self.actions.itervalues(): 362 code('/** \\brief ${{action.desc}} */') 363 code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr);') 364 elif self.EntryType != None: 365 for action in self.actions.itervalues(): 366 code('/** \\brief ${{action.desc}} */') 367 code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 368 else: 369 for action in self.actions.itervalues(): 370 code('/** \\brief ${{action.desc}} */') 371 code('void ${{action.ident}}(const Address& addr);') 372 373 # the controller internal variables 374 code(''' 375 376// Objects 377''') 378 for var in self.objects: 379 th = var.get("template", "") 380 code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') 381 382 if var.type.ident == "MessageBuffer": 383 self.message_buffer_names.append("m_%s_ptr" % var.c_ident) 384 385 code.dedent() 386 code('};') 387 code('#endif // __${ident}_CONTROLLER_H__') 388 code.write(path, '%s.hh' % c_ident) 389 390 def printControllerCC(self, path, includes): 391 '''Output the actions for performing the actions''' 392 393 code = self.symtab.codeFormatter() 394 ident = self.ident 395 c_ident = "%s_Controller" % self.ident 396 397 code(''' 398/** \\file $c_ident.cc 399 * 400 * Auto generated C++ code started by $__file__:$__line__ 401 * Created by slicc definition of Module "${{self.short}}" 402 */ 403 404#include <sys/types.h> 405#include <unistd.h> 406 407#include <cassert> 408#include <sstream> 409#include <string> 410 411#include "base/compiler.hh" 412#include "base/cprintf.hh" 413#include "debug/RubyGenerated.hh" 414#include "debug/RubySlicc.hh" 415#include "mem/protocol/${ident}_Controller.hh" 416#include "mem/protocol/${ident}_Event.hh" 417#include "mem/protocol/${ident}_State.hh" 418#include "mem/protocol/Types.hh" 419#include "mem/ruby/common/Global.hh" 420#include "mem/ruby/system/System.hh" 421''') 422 for include_path in includes: 423 code('#include "${{include_path}}"') 424 425 code(''' 426 427using namespace std; 428''') 429 430 # include object classes 431 seen_types = set() 432 for var in self.objects: 433 if var.type.ident not in seen_types and not var.type.isPrimitive: 434 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 435 seen_types.add(var.type.ident) 436 437 code(''' 438$c_ident * 439${c_ident}Params::create() 440{ 441 return new $c_ident(this); 442} 443 444int $c_ident::m_num_controllers = 0; 445${ident}_ProfileDumper $c_ident::s_profileDumper; 446 447// for adding information to the protocol debug trace 448stringstream ${ident}_transitionComment; 449#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 450 451/** \\brief constructor */ 452$c_ident::$c_ident(const Params *p) 453 : AbstractController(p) 454{ 455 m_name = "${ident}"; 456''') 457 # 458 # max_port_rank is used to size vectors and thus should be one plus the 459 # largest port rank 460 # 461 max_port_rank = self.in_ports[0].pairs["max_port_rank"] + 1 462 code(' m_max_in_port_rank = $max_port_rank;') 463 code.indent() 464 465 # 466 # After initializing the universal machine parameters, initialize the 467 # this machines config parameters. Also detemine if these configuration 468 # params include a sequencer. This information will be used later for 469 # contecting the sequencer back to the L1 cache controller. 470 # 471 contains_dma_sequencer = False 472 sequencers = [] 473 for param in self.config_parameters: 474 if param.name == "dma_sequencer": 475 contains_dma_sequencer = True 476 elif re.compile("sequencer").search(param.name): 477 sequencers.append(param.name) 478 if param.pointer: 479 code('m_${{param.name}}_ptr = p->${{param.name}};') 480 else: 481 code('m_${{param.name}} = p->${{param.name}};') 482 483 # 484 # For the l1 cache controller, add the special atomic support which 485 # includes passing the sequencer a pointer to the controller. 486 # 487 if self.ident == "L1Cache": 488 if not sequencers: 489 self.error("The L1Cache controller must include the sequencer " \ 490 "configuration parameter") 491 492 for seq in sequencers: 493 code(''' 494m_${{seq}}_ptr->setController(this); 495 ''') 496 497 else: 498 for seq in sequencers: 499 code(''' 500m_${{seq}}_ptr->setController(this); 501 ''') 502 503 # 504 # For the DMA controller, pass the sequencer a pointer to the 505 # controller. 506 # 507 if self.ident == "DMA": 508 if not contains_dma_sequencer: 509 self.error("The DMA controller must include the sequencer " \ 510 "configuration parameter") 511 512 code(''' 513m_dma_sequencer_ptr->setController(this); 514''') 515 516 code('m_num_controllers++;') 517 for var in self.objects: 518 if var.ident.find("mandatoryQueue") >= 0: 519 code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();') 520 521 code.dedent() 522 code(''' 523} 524 525void 526$c_ident::init() 527{ 528 MachineType machine_type; 529 int base; 530 machine_type = string_to_MachineType("${{var.machine.ident}}"); 531 base = MachineType_base_number(machine_type); 532 533 m_machineID.type = MachineType_${ident}; 534 m_machineID.num = m_version; 535 536 // initialize objects 537 m_profiler.setVersion(m_version); 538 s_profileDumper.registerProfiler(&m_profiler); 539 540''') 541 542 code.indent() 543 for var in self.objects: 544 vtype = var.type 545 vid = "m_%s_ptr" % var.c_ident 546 if "network" not in var: 547 # Not a network port object 548 if "primitive" in vtype: 549 code('$vid = new ${{vtype.c_ident}};') 550 if "default" in var: 551 code('(*$vid) = ${{var["default"]}};') 552 else: 553 # Normal Object 554 # added by SS 555 if "factory" in var: 556 code('$vid = ${{var["factory"]}};') 557 elif var.ident.find("mandatoryQueue") < 0: 558 th = var.get("template", "") 559 expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 560 args = "" 561 if "non_obj" not in vtype and not vtype.isEnumeration: 562 args = var.get("constructor", "") 563 code('$expr($args);') 564 565 code('assert($vid != NULL);') 566 567 if "default" in var: 568 code('*$vid = ${{var["default"]}}; // Object default') 569 elif "default" in vtype: 570 comment = "Type %s default" % vtype.ident 571 code('*$vid = ${{vtype["default"]}}; // $comment') 572 573 # Set ordering 574 if "ordered" in var and "trigger_queue" not in var: 575 # A buffer 576 code('$vid->setOrdering(${{var["ordered"]}});') 577 578 # Set randomization 579 if "random" in var: 580 # A buffer 581 code('$vid->setRandomization(${{var["random"]}});') 582 583 # Set Priority 584 if vtype.isBuffer and \ 585 "rank" in var and "trigger_queue" not in var: 586 code('$vid->setPriority(${{var["rank"]}});') 587 588 else: 589 # Network port object 590 network = var["network"] 591 ordered = var["ordered"] 592 vnet = var["virtual_network"] 593 vnet_type = var["vnet_type"] 594 595 assert var.machine is not None 596 code(''' 597$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type"); 598''') 599 600 code('assert($vid != NULL);') 601 602 # Set ordering 603 if "ordered" in var: 604 # A buffer 605 code('$vid->setOrdering(${{var["ordered"]}});') 606 607 # Set randomization 608 if "random" in var: 609 # A buffer 610 code('$vid->setRandomization(${{var["random"]}});') 611 612 # Set Priority 613 if "rank" in var: 614 code('$vid->setPriority(${{var["rank"]}})') 615 616 # Set buffer size 617 if vtype.isBuffer: 618 code(''' 619if (m_buffer_size > 0) { 620 $vid->resize(m_buffer_size); 621} 622''') 623 624 # set description (may be overriden later by port def) 625 code(''' 626$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]"); 627 628''') 629 630 if vtype.isBuffer: 631 if "recycle_latency" in var:
| 49 50class StateMachine(Symbol): 51 def __init__(self, symtab, ident, location, pairs, config_parameters): 52 super(StateMachine, self).__init__(symtab, ident, location, pairs) 53 self.table = None 54 self.config_parameters = config_parameters 55 self.prefetchers = [] 56 57 for param in config_parameters: 58 if param.pointer: 59 var = Var(symtab, param.name, location, param.type_ast.type, 60 "(*m_%s_ptr)" % param.name, {}, self) 61 else: 62 var = Var(symtab, param.name, location, param.type_ast.type, 63 "m_%s" % param.name, {}, self) 64 self.symtab.registerSym(param.name, var) 65 if str(param.type_ast.type) == "Prefetcher": 66 self.prefetchers.append(var) 67 68 self.states = orderdict() 69 self.events = orderdict() 70 self.actions = orderdict() 71 self.request_types = orderdict() 72 self.transitions = [] 73 self.in_ports = [] 74 self.functions = [] 75 self.objects = [] 76 self.TBEType = None 77 self.EntryType = None 78 self.message_buffer_names = [] 79 80 81 def __repr__(self): 82 return "[StateMachine: %s]" % self.ident 83 84 def addState(self, state): 85 assert self.table is None 86 self.states[state.ident] = state 87 88 def addEvent(self, event): 89 assert self.table is None 90 self.events[event.ident] = event 91 92 def addAction(self, action): 93 assert self.table is None 94 95 # Check for duplicate action 96 for other in self.actions.itervalues(): 97 if action.ident == other.ident: 98 action.warning("Duplicate action definition: %s" % action.ident) 99 action.error("Duplicate action definition: %s" % action.ident) 100 if action.short == other.short: 101 other.warning("Duplicate action shorthand: %s" % other.ident) 102 other.warning(" shorthand = %s" % other.short) 103 action.warning("Duplicate action shorthand: %s" % action.ident) 104 action.error(" shorthand = %s" % action.short) 105 106 self.actions[action.ident] = action 107 108 def addRequestType(self, request_type): 109 assert self.table is None 110 self.request_types[request_type.ident] = request_type 111 112 def addTransition(self, trans): 113 assert self.table is None 114 self.transitions.append(trans) 115 116 def addInPort(self, var): 117 self.in_ports.append(var) 118 119 def addFunc(self, func): 120 # register func in the symbol table 121 self.symtab.registerSym(str(func), func) 122 self.functions.append(func) 123 124 def addObject(self, obj): 125 self.objects.append(obj) 126 127 def addType(self, type): 128 type_ident = '%s' % type.c_ident 129 130 if type_ident == "%s_TBE" %self.ident: 131 if self.TBEType != None: 132 self.error("Multiple Transaction Buffer types in a " \ 133 "single machine."); 134 self.TBEType = type 135 136 elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 137 if self.EntryType != None: 138 self.error("Multiple AbstractCacheEntry types in a " \ 139 "single machine."); 140 self.EntryType = type 141 142 # Needs to be called before accessing the table 143 def buildTable(self): 144 assert self.table is None 145 146 table = {} 147 148 for trans in self.transitions: 149 # Track which actions we touch so we know if we use them 150 # all -- really this should be done for all symbols as 151 # part of the symbol table, then only trigger it for 152 # Actions, States, Events, etc. 153 154 for action in trans.actions: 155 action.used = True 156 157 index = (trans.state, trans.event) 158 if index in table: 159 table[index].warning("Duplicate transition: %s" % table[index]) 160 trans.error("Duplicate transition: %s" % trans) 161 table[index] = trans 162 163 # Look at all actions to make sure we used them all 164 for action in self.actions.itervalues(): 165 if not action.used: 166 error_msg = "Unused action: %s" % action.ident 167 if "desc" in action: 168 error_msg += ", " + action.desc 169 action.warning(error_msg) 170 self.table = table 171 172 def writeCodeFiles(self, path, includes): 173 self.printControllerPython(path) 174 self.printControllerHH(path) 175 self.printControllerCC(path, includes) 176 self.printCSwitch(path) 177 self.printCWakeup(path, includes) 178 self.printProfilerCC(path) 179 self.printProfilerHH(path) 180 self.printProfileDumperCC(path) 181 self.printProfileDumperHH(path) 182 183 def printControllerPython(self, path): 184 code = self.symtab.codeFormatter() 185 ident = self.ident 186 py_ident = "%s_Controller" % ident 187 c_ident = "%s_Controller" % self.ident 188 code(''' 189from m5.params import * 190from m5.SimObject import SimObject 191from Controller import RubyController 192 193class $py_ident(RubyController): 194 type = '$py_ident' 195 cxx_header = 'mem/protocol/${c_ident}.hh' 196''') 197 code.indent() 198 for param in self.config_parameters: 199 dflt_str = '' 200 if param.default is not None: 201 dflt_str = str(param.default) + ', ' 202 if python_class_map.has_key(param.type_ast.type.c_ident): 203 python_type = python_class_map[param.type_ast.type.c_ident] 204 code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")') 205 else: 206 self.error("Unknown c++ to python class conversion for c++ " \ 207 "type: '%s'. Please update the python_class_map " \ 208 "in StateMachine.py", param.type_ast.type.c_ident) 209 code.dedent() 210 code.write(path, '%s.py' % py_ident) 211 212 213 def printControllerHH(self, path): 214 '''Output the method declarations for the class declaration''' 215 code = self.symtab.codeFormatter() 216 ident = self.ident 217 c_ident = "%s_Controller" % self.ident 218 219 self.message_buffer_names = [] 220 221 code(''' 222/** \\file $c_ident.hh 223 * 224 * Auto generated C++ code started by $__file__:$__line__ 225 * Created by slicc definition of Module "${{self.short}}" 226 */ 227 228#ifndef __${ident}_CONTROLLER_HH__ 229#define __${ident}_CONTROLLER_HH__ 230 231#include <iostream> 232#include <sstream> 233#include <string> 234 235#include "mem/protocol/${ident}_ProfileDumper.hh" 236#include "mem/protocol/${ident}_Profiler.hh" 237#include "mem/protocol/TransitionResult.hh" 238#include "mem/protocol/Types.hh" 239#include "mem/ruby/common/Consumer.hh" 240#include "mem/ruby/common/Global.hh" 241#include "mem/ruby/slicc_interface/AbstractController.hh" 242#include "params/$c_ident.hh" 243''') 244 245 seen_types = set() 246 for var in self.objects: 247 if var.type.ident not in seen_types and not var.type.isPrimitive: 248 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 249 seen_types.add(var.type.ident) 250 251 # for adding information to the protocol debug trace 252 code(''' 253extern std::stringstream ${ident}_transitionComment; 254 255class $c_ident : public AbstractController 256{ 257 public: 258 typedef ${c_ident}Params Params; 259 $c_ident(const Params *p); 260 static int getNumControllers(); 261 void init(); 262 MessageBuffer* getMandatoryQueue() const; 263 const int & getVersion() const; 264 const std::string toString() const; 265 const std::string getName() const; 266 void stallBuffer(MessageBuffer* buf, Address addr); 267 void wakeUpBuffers(Address addr); 268 void wakeUpAllBuffers(); 269 void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; } 270 void print(std::ostream& out) const; 271 void wakeup(); 272 void printStats(std::ostream& out) const; 273 void clearStats(); 274 void blockOnQueue(Address addr, MessageBuffer* port); 275 void unblock(Address addr); 276 void recordCacheTrace(int cntrl, CacheRecorder* tr); 277 Sequencer* getSequencer() const; 278 279 bool functionalReadBuffers(PacketPtr&); 280 uint32_t functionalWriteBuffers(PacketPtr&); 281 282private: 283''') 284 285 code.indent() 286 # added by SS 287 for param in self.config_parameters: 288 if param.pointer: 289 code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 290 else: 291 code('${{param.type_ast.type}} m_${{param.ident}};') 292 293 code(''' 294TransitionResult doTransition(${ident}_Event event, 295''') 296 297 if self.EntryType != None: 298 code(''' 299 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 300''') 301 if self.TBEType != None: 302 code(''' 303 ${{self.TBEType.c_ident}}* m_tbe_ptr, 304''') 305 306 code(''' 307 const Address& addr); 308 309TransitionResult doTransitionWorker(${ident}_Event event, 310 ${ident}_State state, 311 ${ident}_State& next_state, 312''') 313 314 if self.TBEType != None: 315 code(''' 316 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 317''') 318 if self.EntryType != None: 319 code(''' 320 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 321''') 322 323 code(''' 324 const Address& addr); 325 326static ${ident}_ProfileDumper s_profileDumper; 327${ident}_Profiler m_profiler; 328static int m_num_controllers; 329 330// Internal functions 331''') 332 333 for func in self.functions: 334 proto = func.prototype 335 if proto: 336 code('$proto') 337 338 if self.EntryType != None: 339 code(''' 340 341// Set and Reset for cache_entry variable 342void set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 343void unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 344''') 345 346 if self.TBEType != None: 347 code(''' 348 349// Set and Reset for tbe variable 350void set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 351void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 352''') 353 354 code(''' 355 356// Actions 357''') 358 if self.TBEType != None and self.EntryType != None: 359 for action in self.actions.itervalues(): 360 code('/** \\brief ${{action.desc}} */') 361 code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 362 elif self.TBEType != None: 363 for action in self.actions.itervalues(): 364 code('/** \\brief ${{action.desc}} */') 365 code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr);') 366 elif self.EntryType != None: 367 for action in self.actions.itervalues(): 368 code('/** \\brief ${{action.desc}} */') 369 code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 370 else: 371 for action in self.actions.itervalues(): 372 code('/** \\brief ${{action.desc}} */') 373 code('void ${{action.ident}}(const Address& addr);') 374 375 # the controller internal variables 376 code(''' 377 378// Objects 379''') 380 for var in self.objects: 381 th = var.get("template", "") 382 code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') 383 384 if var.type.ident == "MessageBuffer": 385 self.message_buffer_names.append("m_%s_ptr" % var.c_ident) 386 387 code.dedent() 388 code('};') 389 code('#endif // __${ident}_CONTROLLER_H__') 390 code.write(path, '%s.hh' % c_ident) 391 392 def printControllerCC(self, path, includes): 393 '''Output the actions for performing the actions''' 394 395 code = self.symtab.codeFormatter() 396 ident = self.ident 397 c_ident = "%s_Controller" % self.ident 398 399 code(''' 400/** \\file $c_ident.cc 401 * 402 * Auto generated C++ code started by $__file__:$__line__ 403 * Created by slicc definition of Module "${{self.short}}" 404 */ 405 406#include <sys/types.h> 407#include <unistd.h> 408 409#include <cassert> 410#include <sstream> 411#include <string> 412 413#include "base/compiler.hh" 414#include "base/cprintf.hh" 415#include "debug/RubyGenerated.hh" 416#include "debug/RubySlicc.hh" 417#include "mem/protocol/${ident}_Controller.hh" 418#include "mem/protocol/${ident}_Event.hh" 419#include "mem/protocol/${ident}_State.hh" 420#include "mem/protocol/Types.hh" 421#include "mem/ruby/common/Global.hh" 422#include "mem/ruby/system/System.hh" 423''') 424 for include_path in includes: 425 code('#include "${{include_path}}"') 426 427 code(''' 428 429using namespace std; 430''') 431 432 # include object classes 433 seen_types = set() 434 for var in self.objects: 435 if var.type.ident not in seen_types and not var.type.isPrimitive: 436 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 437 seen_types.add(var.type.ident) 438 439 code(''' 440$c_ident * 441${c_ident}Params::create() 442{ 443 return new $c_ident(this); 444} 445 446int $c_ident::m_num_controllers = 0; 447${ident}_ProfileDumper $c_ident::s_profileDumper; 448 449// for adding information to the protocol debug trace 450stringstream ${ident}_transitionComment; 451#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 452 453/** \\brief constructor */ 454$c_ident::$c_ident(const Params *p) 455 : AbstractController(p) 456{ 457 m_name = "${ident}"; 458''') 459 # 460 # max_port_rank is used to size vectors and thus should be one plus the 461 # largest port rank 462 # 463 max_port_rank = self.in_ports[0].pairs["max_port_rank"] + 1 464 code(' m_max_in_port_rank = $max_port_rank;') 465 code.indent() 466 467 # 468 # After initializing the universal machine parameters, initialize the 469 # this machines config parameters. Also detemine if these configuration 470 # params include a sequencer. This information will be used later for 471 # contecting the sequencer back to the L1 cache controller. 472 # 473 contains_dma_sequencer = False 474 sequencers = [] 475 for param in self.config_parameters: 476 if param.name == "dma_sequencer": 477 contains_dma_sequencer = True 478 elif re.compile("sequencer").search(param.name): 479 sequencers.append(param.name) 480 if param.pointer: 481 code('m_${{param.name}}_ptr = p->${{param.name}};') 482 else: 483 code('m_${{param.name}} = p->${{param.name}};') 484 485 # 486 # For the l1 cache controller, add the special atomic support which 487 # includes passing the sequencer a pointer to the controller. 488 # 489 if self.ident == "L1Cache": 490 if not sequencers: 491 self.error("The L1Cache controller must include the sequencer " \ 492 "configuration parameter") 493 494 for seq in sequencers: 495 code(''' 496m_${{seq}}_ptr->setController(this); 497 ''') 498 499 else: 500 for seq in sequencers: 501 code(''' 502m_${{seq}}_ptr->setController(this); 503 ''') 504 505 # 506 # For the DMA controller, pass the sequencer a pointer to the 507 # controller. 508 # 509 if self.ident == "DMA": 510 if not contains_dma_sequencer: 511 self.error("The DMA controller must include the sequencer " \ 512 "configuration parameter") 513 514 code(''' 515m_dma_sequencer_ptr->setController(this); 516''') 517 518 code('m_num_controllers++;') 519 for var in self.objects: 520 if var.ident.find("mandatoryQueue") >= 0: 521 code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();') 522 523 code.dedent() 524 code(''' 525} 526 527void 528$c_ident::init() 529{ 530 MachineType machine_type; 531 int base; 532 machine_type = string_to_MachineType("${{var.machine.ident}}"); 533 base = MachineType_base_number(machine_type); 534 535 m_machineID.type = MachineType_${ident}; 536 m_machineID.num = m_version; 537 538 // initialize objects 539 m_profiler.setVersion(m_version); 540 s_profileDumper.registerProfiler(&m_profiler); 541 542''') 543 544 code.indent() 545 for var in self.objects: 546 vtype = var.type 547 vid = "m_%s_ptr" % var.c_ident 548 if "network" not in var: 549 # Not a network port object 550 if "primitive" in vtype: 551 code('$vid = new ${{vtype.c_ident}};') 552 if "default" in var: 553 code('(*$vid) = ${{var["default"]}};') 554 else: 555 # Normal Object 556 # added by SS 557 if "factory" in var: 558 code('$vid = ${{var["factory"]}};') 559 elif var.ident.find("mandatoryQueue") < 0: 560 th = var.get("template", "") 561 expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 562 args = "" 563 if "non_obj" not in vtype and not vtype.isEnumeration: 564 args = var.get("constructor", "") 565 code('$expr($args);') 566 567 code('assert($vid != NULL);') 568 569 if "default" in var: 570 code('*$vid = ${{var["default"]}}; // Object default') 571 elif "default" in vtype: 572 comment = "Type %s default" % vtype.ident 573 code('*$vid = ${{vtype["default"]}}; // $comment') 574 575 # Set ordering 576 if "ordered" in var and "trigger_queue" not in var: 577 # A buffer 578 code('$vid->setOrdering(${{var["ordered"]}});') 579 580 # Set randomization 581 if "random" in var: 582 # A buffer 583 code('$vid->setRandomization(${{var["random"]}});') 584 585 # Set Priority 586 if vtype.isBuffer and \ 587 "rank" in var and "trigger_queue" not in var: 588 code('$vid->setPriority(${{var["rank"]}});') 589 590 else: 591 # Network port object 592 network = var["network"] 593 ordered = var["ordered"] 594 vnet = var["virtual_network"] 595 vnet_type = var["vnet_type"] 596 597 assert var.machine is not None 598 code(''' 599$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type"); 600''') 601 602 code('assert($vid != NULL);') 603 604 # Set ordering 605 if "ordered" in var: 606 # A buffer 607 code('$vid->setOrdering(${{var["ordered"]}});') 608 609 # Set randomization 610 if "random" in var: 611 # A buffer 612 code('$vid->setRandomization(${{var["random"]}});') 613 614 # Set Priority 615 if "rank" in var: 616 code('$vid->setPriority(${{var["rank"]}})') 617 618 # Set buffer size 619 if vtype.isBuffer: 620 code(''' 621if (m_buffer_size > 0) { 622 $vid->resize(m_buffer_size); 623} 624''') 625 626 # set description (may be overriden later by port def) 627 code(''' 628$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]"); 629 630''') 631 632 if vtype.isBuffer: 633 if "recycle_latency" in var:
|
1059 break; 1060 } 1061''') 1062 1063 code.indent() 1064 code.indent() 1065 1066 # InPorts 1067 # 1068 for port in self.in_ports: 1069 code.indent() 1070 code('// ${ident}InPort $port') 1071 if port.pairs.has_key("rank"): 1072 code('m_cur_in_port_rank = ${{port.pairs["rank"]}};') 1073 else: 1074 code('m_cur_in_port_rank = 0;') 1075 code('${{port["c_code_in_port"]}}') 1076 code.dedent() 1077 1078 code('') 1079 1080 code.dedent() 1081 code.dedent() 1082 code(''' 1083 break; // If we got this far, we have nothing left todo 1084 } 1085} 1086''') 1087 1088 code.write(path, "%s_Wakeup.cc" % self.ident) 1089 1090 def printCSwitch(self, path): 1091 '''Output switch statement for transition table''' 1092 1093 code = self.symtab.codeFormatter() 1094 ident = self.ident 1095 1096 code(''' 1097// Auto generated C++ code started by $__file__:$__line__ 1098// ${ident}: ${{self.short}} 1099 1100#include <cassert> 1101 1102#include "base/misc.hh" 1103#include "base/trace.hh" 1104#include "debug/ProtocolTrace.hh" 1105#include "debug/RubyGenerated.hh" 1106#include "mem/protocol/${ident}_Controller.hh" 1107#include "mem/protocol/${ident}_Event.hh" 1108#include "mem/protocol/${ident}_State.hh" 1109#include "mem/protocol/Types.hh" 1110#include "mem/ruby/common/Global.hh" 1111#include "mem/ruby/system/System.hh" 1112 1113#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 1114 1115#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 1116#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 1117 1118TransitionResult 1119${ident}_Controller::doTransition(${ident}_Event event, 1120''') 1121 if self.EntryType != None: 1122 code(''' 1123 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 1124''') 1125 if self.TBEType != None: 1126 code(''' 1127 ${{self.TBEType.c_ident}}* m_tbe_ptr, 1128''') 1129 code(''' 1130 const Address &addr) 1131{ 1132''') 1133 if self.TBEType != None and self.EntryType != None: 1134 code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 1135 elif self.TBEType != None: 1136 code('${ident}_State state = getState(m_tbe_ptr, addr);') 1137 elif self.EntryType != None: 1138 code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 1139 else: 1140 code('${ident}_State state = getState(addr);') 1141 1142 code(''' 1143 ${ident}_State next_state = state; 1144 1145 DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 1146 *this, curCycle(), ${ident}_State_to_string(state), 1147 ${ident}_Event_to_string(event), addr); 1148 1149 TransitionResult result = 1150''') 1151 if self.TBEType != None and self.EntryType != None: 1152 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 1153 elif self.TBEType != None: 1154 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 1155 elif self.EntryType != None: 1156 code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 1157 else: 1158 code('doTransitionWorker(event, state, next_state, addr);') 1159 1160 code(''' 1161 if (result == TransitionResult_Valid) { 1162 DPRINTF(RubyGenerated, "next_state: %s\\n", 1163 ${ident}_State_to_string(next_state)); 1164 m_profiler.countTransition(state, event); 1165 DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 1166 curTick(), m_version, "${ident}", 1167 ${ident}_Event_to_string(event), 1168 ${ident}_State_to_string(state), 1169 ${ident}_State_to_string(next_state), 1170 addr, GET_TRANSITION_COMMENT()); 1171 1172 CLEAR_TRANSITION_COMMENT(); 1173''') 1174 if self.TBEType != None and self.EntryType != None: 1175 code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 1176 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1177 elif self.TBEType != None: 1178 code('setState(m_tbe_ptr, addr, next_state);') 1179 code('setAccessPermission(addr, next_state);') 1180 elif self.EntryType != None: 1181 code('setState(m_cache_entry_ptr, addr, next_state);') 1182 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1183 else: 1184 code('setState(addr, next_state);') 1185 code('setAccessPermission(addr, next_state);') 1186 1187 code(''' 1188 } else if (result == TransitionResult_ResourceStall) { 1189 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1190 curTick(), m_version, "${ident}", 1191 ${ident}_Event_to_string(event), 1192 ${ident}_State_to_string(state), 1193 ${ident}_State_to_string(next_state), 1194 addr, "Resource Stall"); 1195 } else if (result == TransitionResult_ProtocolStall) { 1196 DPRINTF(RubyGenerated, "stalling\\n"); 1197 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1198 curTick(), m_version, "${ident}", 1199 ${ident}_Event_to_string(event), 1200 ${ident}_State_to_string(state), 1201 ${ident}_State_to_string(next_state), 1202 addr, "Protocol Stall"); 1203 } 1204 1205 return result; 1206} 1207 1208TransitionResult 1209${ident}_Controller::doTransitionWorker(${ident}_Event event, 1210 ${ident}_State state, 1211 ${ident}_State& next_state, 1212''') 1213 1214 if self.TBEType != None: 1215 code(''' 1216 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 1217''') 1218 if self.EntryType != None: 1219 code(''' 1220 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 1221''') 1222 code(''' 1223 const Address& addr) 1224{ 1225 switch(HASH_FUN(state, event)) { 1226''') 1227 1228 # This map will allow suppress generating duplicate code 1229 cases = orderdict() 1230 1231 for trans in self.transitions: 1232 case_string = "%s_State_%s, %s_Event_%s" % \ 1233 (self.ident, trans.state.ident, self.ident, trans.event.ident) 1234 1235 case = self.symtab.codeFormatter() 1236 # Only set next_state if it changes 1237 if trans.state != trans.nextState: 1238 ns_ident = trans.nextState.ident 1239 case('next_state = ${ident}_State_${ns_ident};') 1240 1241 actions = trans.actions 1242 request_types = trans.request_types 1243 1244 # Check for resources 1245 case_sorter = [] 1246 res = trans.resources 1247 for key,val in res.iteritems(): 1248 if key.type.ident != "DNUCAStopTable": 1249 val = ''' 1250if (!%s.areNSlotsAvailable(%s)) 1251 return TransitionResult_ResourceStall; 1252''' % (key.code, val) 1253 case_sorter.append(val) 1254 1255 # Check all of the request_types for resource constraints 1256 for request_type in request_types: 1257 val = ''' 1258if (!checkResourceAvailable(%s_RequestType_%s, addr)) { 1259 return TransitionResult_ResourceStall; 1260} 1261''' % (self.ident, request_type.ident) 1262 case_sorter.append(val) 1263 1264 # Emit the code sequences in a sorted order. This makes the 1265 # output deterministic (without this the output order can vary 1266 # since Map's keys() on a vector of pointers is not deterministic 1267 for c in sorted(case_sorter): 1268 case("$c") 1269 1270 # Record access types for this transition 1271 for request_type in request_types: 1272 case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);') 1273 1274 # Figure out if we stall 1275 stall = False 1276 for action in actions: 1277 if action.ident == "z_stall": 1278 stall = True 1279 break 1280 1281 if stall: 1282 case('return TransitionResult_ProtocolStall;') 1283 else: 1284 if self.TBEType != None and self.EntryType != None: 1285 for action in actions: 1286 case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 1287 elif self.TBEType != None: 1288 for action in actions: 1289 case('${{action.ident}}(m_tbe_ptr, addr);') 1290 elif self.EntryType != None: 1291 for action in actions: 1292 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1293 else: 1294 for action in actions: 1295 case('${{action.ident}}(addr);') 1296 case('return TransitionResult_Valid;') 1297 1298 case = str(case) 1299 1300 # Look to see if this transition code is unique. 1301 if case not in cases: 1302 cases[case] = [] 1303 1304 cases[case].append(case_string) 1305 1306 # Walk through all of the unique code blocks and spit out the 1307 # corresponding case statement elements 1308 for case,transitions in cases.iteritems(): 1309 # Iterative over all the multiple transitions that share 1310 # the same code 1311 for trans in transitions: 1312 code(' case HASH_FUN($trans):') 1313 code(' $case') 1314 1315 code(''' 1316 default: 1317 fatal("Invalid transition\\n" 1318 "%s time: %d addr: %s event: %s state: %s\\n", 1319 name(), curCycle(), addr, event, state); 1320 } 1321 return TransitionResult_Valid; 1322} 1323''') 1324 code.write(path, "%s_Transitions.cc" % self.ident) 1325 1326 def printProfileDumperHH(self, path): 1327 code = self.symtab.codeFormatter() 1328 ident = self.ident 1329 1330 code(''' 1331// Auto generated C++ code started by $__file__:$__line__ 1332// ${ident}: ${{self.short}} 1333 1334#ifndef __${ident}_PROFILE_DUMPER_HH__ 1335#define __${ident}_PROFILE_DUMPER_HH__ 1336 1337#include <cassert> 1338#include <iostream> 1339#include <vector> 1340 1341#include "${ident}_Event.hh" 1342#include "${ident}_Profiler.hh" 1343 1344typedef std::vector<${ident}_Profiler *> ${ident}_profilers; 1345 1346class ${ident}_ProfileDumper 1347{ 1348 public: 1349 ${ident}_ProfileDumper(); 1350 void registerProfiler(${ident}_Profiler* profiler); 1351 void dumpStats(std::ostream& out) const; 1352 1353 private: 1354 ${ident}_profilers m_profilers; 1355}; 1356 1357#endif // __${ident}_PROFILE_DUMPER_HH__ 1358''') 1359 code.write(path, "%s_ProfileDumper.hh" % self.ident) 1360 1361 def printProfileDumperCC(self, path): 1362 code = self.symtab.codeFormatter() 1363 ident = self.ident 1364 1365 code(''' 1366// Auto generated C++ code started by $__file__:$__line__ 1367// ${ident}: ${{self.short}} 1368 1369#include "mem/protocol/${ident}_ProfileDumper.hh" 1370 1371${ident}_ProfileDumper::${ident}_ProfileDumper() 1372{ 1373} 1374 1375void 1376${ident}_ProfileDumper::registerProfiler(${ident}_Profiler* profiler) 1377{ 1378 m_profilers.push_back(profiler); 1379} 1380 1381void 1382${ident}_ProfileDumper::dumpStats(std::ostream& out) const 1383{ 1384 out << " --- ${ident} ---\\n"; 1385 out << " - Event Counts -\\n"; 1386 for (${ident}_Event event = ${ident}_Event_FIRST; 1387 event < ${ident}_Event_NUM; 1388 ++event) { 1389 out << (${ident}_Event) event << " ["; 1390 uint64 total = 0; 1391 for (int i = 0; i < m_profilers.size(); i++) { 1392 out << m_profilers[i]->getEventCount(event) << " "; 1393 total += m_profilers[i]->getEventCount(event); 1394 } 1395 out << "] " << total << "\\n"; 1396 } 1397 out << "\\n"; 1398 out << " - Transitions -\\n"; 1399 for (${ident}_State state = ${ident}_State_FIRST; 1400 state < ${ident}_State_NUM; 1401 ++state) { 1402 for (${ident}_Event event = ${ident}_Event_FIRST; 1403 event < ${ident}_Event_NUM; 1404 ++event) { 1405 if (m_profilers[0]->isPossible(state, event)) { 1406 out << (${ident}_State) state << " " 1407 << (${ident}_Event) event << " ["; 1408 uint64 total = 0; 1409 for (int i = 0; i < m_profilers.size(); i++) { 1410 out << m_profilers[i]->getTransitionCount(state, event) << " "; 1411 total += m_profilers[i]->getTransitionCount(state, event); 1412 } 1413 out << "] " << total << "\\n"; 1414 } 1415 } 1416 out << "\\n"; 1417 } 1418} 1419''') 1420 code.write(path, "%s_ProfileDumper.cc" % self.ident) 1421 1422 def printProfilerHH(self, path): 1423 code = self.symtab.codeFormatter() 1424 ident = self.ident 1425 1426 code(''' 1427// Auto generated C++ code started by $__file__:$__line__ 1428// ${ident}: ${{self.short}} 1429 1430#ifndef __${ident}_PROFILER_HH__ 1431#define __${ident}_PROFILER_HH__ 1432 1433#include <cassert> 1434#include <iostream> 1435 1436#include "mem/protocol/${ident}_Event.hh" 1437#include "mem/protocol/${ident}_State.hh" 1438#include "mem/ruby/common/TypeDefines.hh" 1439 1440class ${ident}_Profiler 1441{ 1442 public: 1443 ${ident}_Profiler(); 1444 void setVersion(int version); 1445 void countTransition(${ident}_State state, ${ident}_Event event); 1446 void possibleTransition(${ident}_State state, ${ident}_Event event); 1447 uint64 getEventCount(${ident}_Event event); 1448 bool isPossible(${ident}_State state, ${ident}_Event event); 1449 uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); 1450 void clearStats(); 1451 1452 private: 1453 int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 1454 int m_event_counters[${ident}_Event_NUM]; 1455 bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 1456 int m_version; 1457}; 1458 1459#endif // __${ident}_PROFILER_HH__ 1460''') 1461 code.write(path, "%s_Profiler.hh" % self.ident) 1462 1463 def printProfilerCC(self, path): 1464 code = self.symtab.codeFormatter() 1465 ident = self.ident 1466 1467 code(''' 1468// Auto generated C++ code started by $__file__:$__line__ 1469// ${ident}: ${{self.short}} 1470 1471#include <cassert> 1472 1473#include "mem/protocol/${ident}_Profiler.hh" 1474 1475${ident}_Profiler::${ident}_Profiler() 1476{ 1477 for (int state = 0; state < ${ident}_State_NUM; state++) { 1478 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1479 m_possible[state][event] = false; 1480 m_counters[state][event] = 0; 1481 } 1482 } 1483 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1484 m_event_counters[event] = 0; 1485 } 1486} 1487 1488void 1489${ident}_Profiler::setVersion(int version) 1490{ 1491 m_version = version; 1492} 1493 1494void 1495${ident}_Profiler::clearStats() 1496{ 1497 for (int state = 0; state < ${ident}_State_NUM; state++) { 1498 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1499 m_counters[state][event] = 0; 1500 } 1501 } 1502 1503 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1504 m_event_counters[event] = 0; 1505 } 1506} 1507void 1508${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) 1509{ 1510 assert(m_possible[state][event]); 1511 m_counters[state][event]++; 1512 m_event_counters[event]++; 1513} 1514void 1515${ident}_Profiler::possibleTransition(${ident}_State state, 1516 ${ident}_Event event) 1517{ 1518 m_possible[state][event] = true; 1519} 1520 1521uint64 1522${ident}_Profiler::getEventCount(${ident}_Event event) 1523{ 1524 return m_event_counters[event]; 1525} 1526 1527bool 1528${ident}_Profiler::isPossible(${ident}_State state, ${ident}_Event event) 1529{ 1530 return m_possible[state][event]; 1531} 1532 1533uint64 1534${ident}_Profiler::getTransitionCount(${ident}_State state, 1535 ${ident}_Event event) 1536{ 1537 return m_counters[state][event]; 1538} 1539 1540''') 1541 code.write(path, "%s_Profiler.cc" % self.ident) 1542 1543 # ************************** 1544 # ******* HTML Files ******* 1545 # ************************** 1546 def frameRef(self, click_href, click_target, over_href, over_num, text): 1547 code = self.symtab.codeFormatter(fix_newlines=False) 1548 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1549 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1550 parent.frames[$over_num].location='$over_href' 1551 }\"> 1552 ${{html.formatShorthand(text)}} 1553 </A>""") 1554 return str(code) 1555 1556 def writeHTMLFiles(self, path): 1557 # Create table with no row hilighted 1558 self.printHTMLTransitions(path, None) 1559 1560 # Generate transition tables 1561 for state in self.states.itervalues(): 1562 self.printHTMLTransitions(path, state) 1563 1564 # Generate action descriptions 1565 for action in self.actions.itervalues(): 1566 name = "%s_action_%s.html" % (self.ident, action.ident) 1567 code = html.createSymbol(action, "Action") 1568 code.write(path, name) 1569 1570 # Generate state descriptions 1571 for state in self.states.itervalues(): 1572 name = "%s_State_%s.html" % (self.ident, state.ident) 1573 code = html.createSymbol(state, "State") 1574 code.write(path, name) 1575 1576 # Generate event descriptions 1577 for event in self.events.itervalues(): 1578 name = "%s_Event_%s.html" % (self.ident, event.ident) 1579 code = html.createSymbol(event, "Event") 1580 code.write(path, name) 1581 1582 def printHTMLTransitions(self, path, active_state): 1583 code = self.symtab.codeFormatter() 1584 1585 code(''' 1586<HTML> 1587<BODY link="blue" vlink="blue"> 1588 1589<H1 align="center">${{html.formatShorthand(self.short)}}: 1590''') 1591 code.indent() 1592 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1593 mid = machine.ident 1594 if i != 0: 1595 extra = " - " 1596 else: 1597 extra = "" 1598 if machine == self: 1599 code('$extra$mid') 1600 else: 1601 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1602 code.dedent() 1603 1604 code(""" 1605</H1> 1606 1607<TABLE border=1> 1608<TR> 1609 <TH> </TH> 1610""") 1611 1612 for event in self.events.itervalues(): 1613 href = "%s_Event_%s.html" % (self.ident, event.ident) 1614 ref = self.frameRef(href, "Status", href, "1", event.short) 1615 code('<TH bgcolor=white>$ref</TH>') 1616 1617 code('</TR>') 1618 # -- Body of table 1619 for state in self.states.itervalues(): 1620 # -- Each row 1621 if state == active_state: 1622 color = "yellow" 1623 else: 1624 color = "white" 1625 1626 click = "%s_table_%s.html" % (self.ident, state.ident) 1627 over = "%s_State_%s.html" % (self.ident, state.ident) 1628 text = html.formatShorthand(state.short) 1629 ref = self.frameRef(click, "Table", over, "1", state.short) 1630 code(''' 1631<TR> 1632 <TH bgcolor=$color>$ref</TH> 1633''') 1634 1635 # -- One column for each event 1636 for event in self.events.itervalues(): 1637 trans = self.table.get((state,event), None) 1638 if trans is None: 1639 # This is the no transition case 1640 if state == active_state: 1641 color = "#C0C000" 1642 else: 1643 color = "lightgrey" 1644 1645 code('<TD bgcolor=$color> </TD>') 1646 continue 1647 1648 next = trans.nextState 1649 stall_action = False 1650 1651 # -- Get the actions 1652 for action in trans.actions: 1653 if action.ident == "z_stall" or \ 1654 action.ident == "zz_recycleMandatoryQueue": 1655 stall_action = True 1656 1657 # -- Print out "actions/next-state" 1658 if stall_action: 1659 if state == active_state: 1660 color = "#C0C000" 1661 else: 1662 color = "lightgrey" 1663 1664 elif active_state and next.ident == active_state.ident: 1665 color = "aqua" 1666 elif state == active_state: 1667 color = "yellow" 1668 else: 1669 color = "white" 1670 1671 code('<TD bgcolor=$color>') 1672 for action in trans.actions: 1673 href = "%s_action_%s.html" % (self.ident, action.ident) 1674 ref = self.frameRef(href, "Status", href, "1", 1675 action.short) 1676 code(' $ref') 1677 if next != state: 1678 if trans.actions: 1679 code('/') 1680 click = "%s_table_%s.html" % (self.ident, next.ident) 1681 over = "%s_State_%s.html" % (self.ident, next.ident) 1682 ref = self.frameRef(click, "Table", over, "1", next.short) 1683 code("$ref") 1684 code("</TD>") 1685 1686 # -- Each row 1687 if state == active_state: 1688 color = "yellow" 1689 else: 1690 color = "white" 1691 1692 click = "%s_table_%s.html" % (self.ident, state.ident) 1693 over = "%s_State_%s.html" % (self.ident, state.ident) 1694 ref = self.frameRef(click, "Table", over, "1", state.short) 1695 code(''' 1696 <TH bgcolor=$color>$ref</TH> 1697</TR> 1698''') 1699 code(''' 1700<!- Column footer-> 1701<TR> 1702 <TH> </TH> 1703''') 1704 1705 for event in self.events.itervalues(): 1706 href = "%s_Event_%s.html" % (self.ident, event.ident) 1707 ref = self.frameRef(href, "Status", href, "1", event.short) 1708 code('<TH bgcolor=white>$ref</TH>') 1709 code(''' 1710</TR> 1711</TABLE> 1712</BODY></HTML> 1713''') 1714 1715 1716 if active_state: 1717 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1718 else: 1719 name = "%s_table.html" % self.ident 1720 code.write(path, name) 1721 1722__all__ = [ "StateMachine" ]
| 1062 break; 1063 } 1064''') 1065 1066 code.indent() 1067 code.indent() 1068 1069 # InPorts 1070 # 1071 for port in self.in_ports: 1072 code.indent() 1073 code('// ${ident}InPort $port') 1074 if port.pairs.has_key("rank"): 1075 code('m_cur_in_port_rank = ${{port.pairs["rank"]}};') 1076 else: 1077 code('m_cur_in_port_rank = 0;') 1078 code('${{port["c_code_in_port"]}}') 1079 code.dedent() 1080 1081 code('') 1082 1083 code.dedent() 1084 code.dedent() 1085 code(''' 1086 break; // If we got this far, we have nothing left todo 1087 } 1088} 1089''') 1090 1091 code.write(path, "%s_Wakeup.cc" % self.ident) 1092 1093 def printCSwitch(self, path): 1094 '''Output switch statement for transition table''' 1095 1096 code = self.symtab.codeFormatter() 1097 ident = self.ident 1098 1099 code(''' 1100// Auto generated C++ code started by $__file__:$__line__ 1101// ${ident}: ${{self.short}} 1102 1103#include <cassert> 1104 1105#include "base/misc.hh" 1106#include "base/trace.hh" 1107#include "debug/ProtocolTrace.hh" 1108#include "debug/RubyGenerated.hh" 1109#include "mem/protocol/${ident}_Controller.hh" 1110#include "mem/protocol/${ident}_Event.hh" 1111#include "mem/protocol/${ident}_State.hh" 1112#include "mem/protocol/Types.hh" 1113#include "mem/ruby/common/Global.hh" 1114#include "mem/ruby/system/System.hh" 1115 1116#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 1117 1118#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 1119#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 1120 1121TransitionResult 1122${ident}_Controller::doTransition(${ident}_Event event, 1123''') 1124 if self.EntryType != None: 1125 code(''' 1126 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 1127''') 1128 if self.TBEType != None: 1129 code(''' 1130 ${{self.TBEType.c_ident}}* m_tbe_ptr, 1131''') 1132 code(''' 1133 const Address &addr) 1134{ 1135''') 1136 if self.TBEType != None and self.EntryType != None: 1137 code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 1138 elif self.TBEType != None: 1139 code('${ident}_State state = getState(m_tbe_ptr, addr);') 1140 elif self.EntryType != None: 1141 code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 1142 else: 1143 code('${ident}_State state = getState(addr);') 1144 1145 code(''' 1146 ${ident}_State next_state = state; 1147 1148 DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 1149 *this, curCycle(), ${ident}_State_to_string(state), 1150 ${ident}_Event_to_string(event), addr); 1151 1152 TransitionResult result = 1153''') 1154 if self.TBEType != None and self.EntryType != None: 1155 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 1156 elif self.TBEType != None: 1157 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 1158 elif self.EntryType != None: 1159 code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 1160 else: 1161 code('doTransitionWorker(event, state, next_state, addr);') 1162 1163 code(''' 1164 if (result == TransitionResult_Valid) { 1165 DPRINTF(RubyGenerated, "next_state: %s\\n", 1166 ${ident}_State_to_string(next_state)); 1167 m_profiler.countTransition(state, event); 1168 DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 1169 curTick(), m_version, "${ident}", 1170 ${ident}_Event_to_string(event), 1171 ${ident}_State_to_string(state), 1172 ${ident}_State_to_string(next_state), 1173 addr, GET_TRANSITION_COMMENT()); 1174 1175 CLEAR_TRANSITION_COMMENT(); 1176''') 1177 if self.TBEType != None and self.EntryType != None: 1178 code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 1179 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1180 elif self.TBEType != None: 1181 code('setState(m_tbe_ptr, addr, next_state);') 1182 code('setAccessPermission(addr, next_state);') 1183 elif self.EntryType != None: 1184 code('setState(m_cache_entry_ptr, addr, next_state);') 1185 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1186 else: 1187 code('setState(addr, next_state);') 1188 code('setAccessPermission(addr, next_state);') 1189 1190 code(''' 1191 } else if (result == TransitionResult_ResourceStall) { 1192 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1193 curTick(), m_version, "${ident}", 1194 ${ident}_Event_to_string(event), 1195 ${ident}_State_to_string(state), 1196 ${ident}_State_to_string(next_state), 1197 addr, "Resource Stall"); 1198 } else if (result == TransitionResult_ProtocolStall) { 1199 DPRINTF(RubyGenerated, "stalling\\n"); 1200 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1201 curTick(), m_version, "${ident}", 1202 ${ident}_Event_to_string(event), 1203 ${ident}_State_to_string(state), 1204 ${ident}_State_to_string(next_state), 1205 addr, "Protocol Stall"); 1206 } 1207 1208 return result; 1209} 1210 1211TransitionResult 1212${ident}_Controller::doTransitionWorker(${ident}_Event event, 1213 ${ident}_State state, 1214 ${ident}_State& next_state, 1215''') 1216 1217 if self.TBEType != None: 1218 code(''' 1219 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 1220''') 1221 if self.EntryType != None: 1222 code(''' 1223 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 1224''') 1225 code(''' 1226 const Address& addr) 1227{ 1228 switch(HASH_FUN(state, event)) { 1229''') 1230 1231 # This map will allow suppress generating duplicate code 1232 cases = orderdict() 1233 1234 for trans in self.transitions: 1235 case_string = "%s_State_%s, %s_Event_%s" % \ 1236 (self.ident, trans.state.ident, self.ident, trans.event.ident) 1237 1238 case = self.symtab.codeFormatter() 1239 # Only set next_state if it changes 1240 if trans.state != trans.nextState: 1241 ns_ident = trans.nextState.ident 1242 case('next_state = ${ident}_State_${ns_ident};') 1243 1244 actions = trans.actions 1245 request_types = trans.request_types 1246 1247 # Check for resources 1248 case_sorter = [] 1249 res = trans.resources 1250 for key,val in res.iteritems(): 1251 if key.type.ident != "DNUCAStopTable": 1252 val = ''' 1253if (!%s.areNSlotsAvailable(%s)) 1254 return TransitionResult_ResourceStall; 1255''' % (key.code, val) 1256 case_sorter.append(val) 1257 1258 # Check all of the request_types for resource constraints 1259 for request_type in request_types: 1260 val = ''' 1261if (!checkResourceAvailable(%s_RequestType_%s, addr)) { 1262 return TransitionResult_ResourceStall; 1263} 1264''' % (self.ident, request_type.ident) 1265 case_sorter.append(val) 1266 1267 # Emit the code sequences in a sorted order. This makes the 1268 # output deterministic (without this the output order can vary 1269 # since Map's keys() on a vector of pointers is not deterministic 1270 for c in sorted(case_sorter): 1271 case("$c") 1272 1273 # Record access types for this transition 1274 for request_type in request_types: 1275 case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);') 1276 1277 # Figure out if we stall 1278 stall = False 1279 for action in actions: 1280 if action.ident == "z_stall": 1281 stall = True 1282 break 1283 1284 if stall: 1285 case('return TransitionResult_ProtocolStall;') 1286 else: 1287 if self.TBEType != None and self.EntryType != None: 1288 for action in actions: 1289 case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 1290 elif self.TBEType != None: 1291 for action in actions: 1292 case('${{action.ident}}(m_tbe_ptr, addr);') 1293 elif self.EntryType != None: 1294 for action in actions: 1295 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1296 else: 1297 for action in actions: 1298 case('${{action.ident}}(addr);') 1299 case('return TransitionResult_Valid;') 1300 1301 case = str(case) 1302 1303 # Look to see if this transition code is unique. 1304 if case not in cases: 1305 cases[case] = [] 1306 1307 cases[case].append(case_string) 1308 1309 # Walk through all of the unique code blocks and spit out the 1310 # corresponding case statement elements 1311 for case,transitions in cases.iteritems(): 1312 # Iterative over all the multiple transitions that share 1313 # the same code 1314 for trans in transitions: 1315 code(' case HASH_FUN($trans):') 1316 code(' $case') 1317 1318 code(''' 1319 default: 1320 fatal("Invalid transition\\n" 1321 "%s time: %d addr: %s event: %s state: %s\\n", 1322 name(), curCycle(), addr, event, state); 1323 } 1324 return TransitionResult_Valid; 1325} 1326''') 1327 code.write(path, "%s_Transitions.cc" % self.ident) 1328 1329 def printProfileDumperHH(self, path): 1330 code = self.symtab.codeFormatter() 1331 ident = self.ident 1332 1333 code(''' 1334// Auto generated C++ code started by $__file__:$__line__ 1335// ${ident}: ${{self.short}} 1336 1337#ifndef __${ident}_PROFILE_DUMPER_HH__ 1338#define __${ident}_PROFILE_DUMPER_HH__ 1339 1340#include <cassert> 1341#include <iostream> 1342#include <vector> 1343 1344#include "${ident}_Event.hh" 1345#include "${ident}_Profiler.hh" 1346 1347typedef std::vector<${ident}_Profiler *> ${ident}_profilers; 1348 1349class ${ident}_ProfileDumper 1350{ 1351 public: 1352 ${ident}_ProfileDumper(); 1353 void registerProfiler(${ident}_Profiler* profiler); 1354 void dumpStats(std::ostream& out) const; 1355 1356 private: 1357 ${ident}_profilers m_profilers; 1358}; 1359 1360#endif // __${ident}_PROFILE_DUMPER_HH__ 1361''') 1362 code.write(path, "%s_ProfileDumper.hh" % self.ident) 1363 1364 def printProfileDumperCC(self, path): 1365 code = self.symtab.codeFormatter() 1366 ident = self.ident 1367 1368 code(''' 1369// Auto generated C++ code started by $__file__:$__line__ 1370// ${ident}: ${{self.short}} 1371 1372#include "mem/protocol/${ident}_ProfileDumper.hh" 1373 1374${ident}_ProfileDumper::${ident}_ProfileDumper() 1375{ 1376} 1377 1378void 1379${ident}_ProfileDumper::registerProfiler(${ident}_Profiler* profiler) 1380{ 1381 m_profilers.push_back(profiler); 1382} 1383 1384void 1385${ident}_ProfileDumper::dumpStats(std::ostream& out) const 1386{ 1387 out << " --- ${ident} ---\\n"; 1388 out << " - Event Counts -\\n"; 1389 for (${ident}_Event event = ${ident}_Event_FIRST; 1390 event < ${ident}_Event_NUM; 1391 ++event) { 1392 out << (${ident}_Event) event << " ["; 1393 uint64 total = 0; 1394 for (int i = 0; i < m_profilers.size(); i++) { 1395 out << m_profilers[i]->getEventCount(event) << " "; 1396 total += m_profilers[i]->getEventCount(event); 1397 } 1398 out << "] " << total << "\\n"; 1399 } 1400 out << "\\n"; 1401 out << " - Transitions -\\n"; 1402 for (${ident}_State state = ${ident}_State_FIRST; 1403 state < ${ident}_State_NUM; 1404 ++state) { 1405 for (${ident}_Event event = ${ident}_Event_FIRST; 1406 event < ${ident}_Event_NUM; 1407 ++event) { 1408 if (m_profilers[0]->isPossible(state, event)) { 1409 out << (${ident}_State) state << " " 1410 << (${ident}_Event) event << " ["; 1411 uint64 total = 0; 1412 for (int i = 0; i < m_profilers.size(); i++) { 1413 out << m_profilers[i]->getTransitionCount(state, event) << " "; 1414 total += m_profilers[i]->getTransitionCount(state, event); 1415 } 1416 out << "] " << total << "\\n"; 1417 } 1418 } 1419 out << "\\n"; 1420 } 1421} 1422''') 1423 code.write(path, "%s_ProfileDumper.cc" % self.ident) 1424 1425 def printProfilerHH(self, path): 1426 code = self.symtab.codeFormatter() 1427 ident = self.ident 1428 1429 code(''' 1430// Auto generated C++ code started by $__file__:$__line__ 1431// ${ident}: ${{self.short}} 1432 1433#ifndef __${ident}_PROFILER_HH__ 1434#define __${ident}_PROFILER_HH__ 1435 1436#include <cassert> 1437#include <iostream> 1438 1439#include "mem/protocol/${ident}_Event.hh" 1440#include "mem/protocol/${ident}_State.hh" 1441#include "mem/ruby/common/TypeDefines.hh" 1442 1443class ${ident}_Profiler 1444{ 1445 public: 1446 ${ident}_Profiler(); 1447 void setVersion(int version); 1448 void countTransition(${ident}_State state, ${ident}_Event event); 1449 void possibleTransition(${ident}_State state, ${ident}_Event event); 1450 uint64 getEventCount(${ident}_Event event); 1451 bool isPossible(${ident}_State state, ${ident}_Event event); 1452 uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); 1453 void clearStats(); 1454 1455 private: 1456 int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 1457 int m_event_counters[${ident}_Event_NUM]; 1458 bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 1459 int m_version; 1460}; 1461 1462#endif // __${ident}_PROFILER_HH__ 1463''') 1464 code.write(path, "%s_Profiler.hh" % self.ident) 1465 1466 def printProfilerCC(self, path): 1467 code = self.symtab.codeFormatter() 1468 ident = self.ident 1469 1470 code(''' 1471// Auto generated C++ code started by $__file__:$__line__ 1472// ${ident}: ${{self.short}} 1473 1474#include <cassert> 1475 1476#include "mem/protocol/${ident}_Profiler.hh" 1477 1478${ident}_Profiler::${ident}_Profiler() 1479{ 1480 for (int state = 0; state < ${ident}_State_NUM; state++) { 1481 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1482 m_possible[state][event] = false; 1483 m_counters[state][event] = 0; 1484 } 1485 } 1486 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1487 m_event_counters[event] = 0; 1488 } 1489} 1490 1491void 1492${ident}_Profiler::setVersion(int version) 1493{ 1494 m_version = version; 1495} 1496 1497void 1498${ident}_Profiler::clearStats() 1499{ 1500 for (int state = 0; state < ${ident}_State_NUM; state++) { 1501 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1502 m_counters[state][event] = 0; 1503 } 1504 } 1505 1506 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1507 m_event_counters[event] = 0; 1508 } 1509} 1510void 1511${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) 1512{ 1513 assert(m_possible[state][event]); 1514 m_counters[state][event]++; 1515 m_event_counters[event]++; 1516} 1517void 1518${ident}_Profiler::possibleTransition(${ident}_State state, 1519 ${ident}_Event event) 1520{ 1521 m_possible[state][event] = true; 1522} 1523 1524uint64 1525${ident}_Profiler::getEventCount(${ident}_Event event) 1526{ 1527 return m_event_counters[event]; 1528} 1529 1530bool 1531${ident}_Profiler::isPossible(${ident}_State state, ${ident}_Event event) 1532{ 1533 return m_possible[state][event]; 1534} 1535 1536uint64 1537${ident}_Profiler::getTransitionCount(${ident}_State state, 1538 ${ident}_Event event) 1539{ 1540 return m_counters[state][event]; 1541} 1542 1543''') 1544 code.write(path, "%s_Profiler.cc" % self.ident) 1545 1546 # ************************** 1547 # ******* HTML Files ******* 1548 # ************************** 1549 def frameRef(self, click_href, click_target, over_href, over_num, text): 1550 code = self.symtab.codeFormatter(fix_newlines=False) 1551 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1552 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1553 parent.frames[$over_num].location='$over_href' 1554 }\"> 1555 ${{html.formatShorthand(text)}} 1556 </A>""") 1557 return str(code) 1558 1559 def writeHTMLFiles(self, path): 1560 # Create table with no row hilighted 1561 self.printHTMLTransitions(path, None) 1562 1563 # Generate transition tables 1564 for state in self.states.itervalues(): 1565 self.printHTMLTransitions(path, state) 1566 1567 # Generate action descriptions 1568 for action in self.actions.itervalues(): 1569 name = "%s_action_%s.html" % (self.ident, action.ident) 1570 code = html.createSymbol(action, "Action") 1571 code.write(path, name) 1572 1573 # Generate state descriptions 1574 for state in self.states.itervalues(): 1575 name = "%s_State_%s.html" % (self.ident, state.ident) 1576 code = html.createSymbol(state, "State") 1577 code.write(path, name) 1578 1579 # Generate event descriptions 1580 for event in self.events.itervalues(): 1581 name = "%s_Event_%s.html" % (self.ident, event.ident) 1582 code = html.createSymbol(event, "Event") 1583 code.write(path, name) 1584 1585 def printHTMLTransitions(self, path, active_state): 1586 code = self.symtab.codeFormatter() 1587 1588 code(''' 1589<HTML> 1590<BODY link="blue" vlink="blue"> 1591 1592<H1 align="center">${{html.formatShorthand(self.short)}}: 1593''') 1594 code.indent() 1595 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1596 mid = machine.ident 1597 if i != 0: 1598 extra = " - " 1599 else: 1600 extra = "" 1601 if machine == self: 1602 code('$extra$mid') 1603 else: 1604 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1605 code.dedent() 1606 1607 code(""" 1608</H1> 1609 1610<TABLE border=1> 1611<TR> 1612 <TH> </TH> 1613""") 1614 1615 for event in self.events.itervalues(): 1616 href = "%s_Event_%s.html" % (self.ident, event.ident) 1617 ref = self.frameRef(href, "Status", href, "1", event.short) 1618 code('<TH bgcolor=white>$ref</TH>') 1619 1620 code('</TR>') 1621 # -- Body of table 1622 for state in self.states.itervalues(): 1623 # -- Each row 1624 if state == active_state: 1625 color = "yellow" 1626 else: 1627 color = "white" 1628 1629 click = "%s_table_%s.html" % (self.ident, state.ident) 1630 over = "%s_State_%s.html" % (self.ident, state.ident) 1631 text = html.formatShorthand(state.short) 1632 ref = self.frameRef(click, "Table", over, "1", state.short) 1633 code(''' 1634<TR> 1635 <TH bgcolor=$color>$ref</TH> 1636''') 1637 1638 # -- One column for each event 1639 for event in self.events.itervalues(): 1640 trans = self.table.get((state,event), None) 1641 if trans is None: 1642 # This is the no transition case 1643 if state == active_state: 1644 color = "#C0C000" 1645 else: 1646 color = "lightgrey" 1647 1648 code('<TD bgcolor=$color> </TD>') 1649 continue 1650 1651 next = trans.nextState 1652 stall_action = False 1653 1654 # -- Get the actions 1655 for action in trans.actions: 1656 if action.ident == "z_stall" or \ 1657 action.ident == "zz_recycleMandatoryQueue": 1658 stall_action = True 1659 1660 # -- Print out "actions/next-state" 1661 if stall_action: 1662 if state == active_state: 1663 color = "#C0C000" 1664 else: 1665 color = "lightgrey" 1666 1667 elif active_state and next.ident == active_state.ident: 1668 color = "aqua" 1669 elif state == active_state: 1670 color = "yellow" 1671 else: 1672 color = "white" 1673 1674 code('<TD bgcolor=$color>') 1675 for action in trans.actions: 1676 href = "%s_action_%s.html" % (self.ident, action.ident) 1677 ref = self.frameRef(href, "Status", href, "1", 1678 action.short) 1679 code(' $ref') 1680 if next != state: 1681 if trans.actions: 1682 code('/') 1683 click = "%s_table_%s.html" % (self.ident, next.ident) 1684 over = "%s_State_%s.html" % (self.ident, next.ident) 1685 ref = self.frameRef(click, "Table", over, "1", next.short) 1686 code("$ref") 1687 code("</TD>") 1688 1689 # -- Each row 1690 if state == active_state: 1691 color = "yellow" 1692 else: 1693 color = "white" 1694 1695 click = "%s_table_%s.html" % (self.ident, state.ident) 1696 over = "%s_State_%s.html" % (self.ident, state.ident) 1697 ref = self.frameRef(click, "Table", over, "1", state.short) 1698 code(''' 1699 <TH bgcolor=$color>$ref</TH> 1700</TR> 1701''') 1702 code(''' 1703<!- Column footer-> 1704<TR> 1705 <TH> </TH> 1706''') 1707 1708 for event in self.events.itervalues(): 1709 href = "%s_Event_%s.html" % (self.ident, event.ident) 1710 ref = self.frameRef(href, "Status", href, "1", event.short) 1711 code('<TH bgcolor=white>$ref</TH>') 1712 code(''' 1713</TR> 1714</TABLE> 1715</BODY></HTML> 1716''') 1717 1718 1719 if active_state: 1720 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1721 else: 1722 name = "%s_table.html" % self.ident 1723 code.write(path, name) 1724 1725__all__ = [ "StateMachine" ]
|