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 code_formatter, orderdict 29 30from slicc.symbols.Symbol import Symbol 31from slicc.symbols.Var import Var 32import slicc.generate.html as html 33 34class StateMachine(Symbol): 35 def __init__(self, symtab, ident, location, pairs, config_parameters): 36 super(StateMachine, self).__init__(symtab, ident, location, pairs) 37 self.table = None 38 self.config_parameters = config_parameters 39 for param in config_parameters: 40 var = Var(symtab, param.name, location, param.type_ast.type, 41 "m_%s" % param.name, {}, self) 42 self.symtab.registerSym(param.name, var) 43 44 self.states = orderdict() 45 self.events = orderdict() 46 self.actions = orderdict() 47 self.transitions = [] 48 self.in_ports = [] 49 self.functions = [] 50 self.objects = [] 51 52 self.message_buffer_names = [] 53 54 def __repr__(self): 55 return "[StateMachine: %s]" % self.ident 56 57 def addState(self, state): 58 assert self.table is None 59 self.states[state.ident] = state 60 61 def addEvent(self, event): 62 assert self.table is None 63 self.events[event.ident] = event 64 65 def addAction(self, action): 66 assert self.table is None 67 68 # Check for duplicate action 69 for other in self.actions.itervalues(): 70 if action.ident == other.ident: 71 action.warning("Duplicate action definition: %s" % action.ident) 72 action.error("Duplicate action definition: %s" % action.ident) 73 if action.short == other.short: 74 other.warning("Duplicate action shorthand: %s" % other.ident) 75 other.warning(" shorthand = %s" % other.short) 76 action.warning("Duplicate action shorthand: %s" % action.ident) 77 action.error(" shorthand = %s" % action.short) 78 79 self.actions[action.ident] = action 80 81 def addTransition(self, trans): 82 assert self.table is None 83 self.transitions.append(trans) 84 85 def addInPort(self, var): 86 self.in_ports.append(var) 87 88 def addFunc(self, func): 89 # register func in the symbol table 90 self.symtab.registerSym(str(func), func) 91 self.functions.append(func) 92 93 def addObject(self, obj): 94 self.objects.append(obj) 95 96 # Needs to be called before accessing the table 97 def buildTable(self): 98 assert self.table is None 99 100 table = {} 101 102 for trans in self.transitions: 103 # Track which actions we touch so we know if we use them 104 # all -- really this should be done for all symbols as 105 # part of the symbol table, then only trigger it for 106 # Actions, States, Events, etc. 107 108 for action in trans.actions: 109 action.used = True 110 111 index = (trans.state, trans.event) 112 if index in table: 113 table[index].warning("Duplicate transition: %s" % table[index]) 114 trans.error("Duplicate transition: %s" % trans) 115 table[index] = trans 116 117 # Look at all actions to make sure we used them all 118 for action in self.actions.itervalues(): 119 if not action.used: 120 error_msg = "Unused action: %s" % action.ident 121 if "desc" in action: 122 error_msg += ", " + action.desc 123 action.warning(error_msg) 124 self.table = table 125 126 def writeCodeFiles(self, path): 127 self.printControllerHH(path) 128 self.printControllerCC(path) 129 self.printCSwitch(path) 130 self.printCWakeup(path) 131 self.printProfilerCC(path) 132 self.printProfilerHH(path) 133 134 for func in self.functions: 135 func.writeCodeFiles(path) 136 137 def printControllerHH(self, path): 138 '''Output the method declarations for the class declaration''' 139 code = code_formatter() 140 ident = self.ident 141 c_ident = "%s_Controller" % self.ident 142 143 self.message_buffer_names = [] 144 145 code(''' 146/** \\file $ident.hh 147 * 148 * Auto generated C++ code started by $__file__:$__line__ 149 * Created by slicc definition of Module "${{self.short}}" 150 */ 151 152#ifndef ${ident}_CONTROLLER_H 153#define ${ident}_CONTROLLER_H 154 155#include "mem/ruby/common/Global.hh" 156#include "mem/ruby/common/Consumer.hh" 157#include "mem/ruby/slicc_interface/AbstractController.hh" 158#include "mem/protocol/TransitionResult.hh" 159#include "mem/protocol/Types.hh" 160#include "mem/protocol/${ident}_Profiler.hh" 161''') 162 163 seen_types = set() 164 for var in self.objects: 165 if var.type.ident not in seen_types and not var.type.isPrimitive: 166 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 167 seen_types.add(var.type.ident) 168 169 # for adding information to the protocol debug trace 170 code(''' 171extern stringstream ${ident}_transitionComment; 172 173class $c_ident : public AbstractController { 174#ifdef CHECK_COHERENCE 175#endif /* CHECK_COHERENCE */ 176public: 177 $c_ident(const string & name); 178 static int getNumControllers(); 179 void init(Network* net_ptr, const vector<string> & argv); 180 MessageBuffer* getMandatoryQueue() const; 181 const int & getVersion() const; 182 const string toString() const; 183 const string getName() const; 184 const MachineType getMachineType() const; 185 void print(ostream& out) const; 186 void printConfig(ostream& out) const; 187 void wakeup(); 188 void set_atomic(Address addr);
| 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 code_formatter, orderdict 29 30from slicc.symbols.Symbol import Symbol 31from slicc.symbols.Var import Var 32import slicc.generate.html as html 33 34class StateMachine(Symbol): 35 def __init__(self, symtab, ident, location, pairs, config_parameters): 36 super(StateMachine, self).__init__(symtab, ident, location, pairs) 37 self.table = None 38 self.config_parameters = config_parameters 39 for param in config_parameters: 40 var = Var(symtab, param.name, location, param.type_ast.type, 41 "m_%s" % param.name, {}, self) 42 self.symtab.registerSym(param.name, var) 43 44 self.states = orderdict() 45 self.events = orderdict() 46 self.actions = orderdict() 47 self.transitions = [] 48 self.in_ports = [] 49 self.functions = [] 50 self.objects = [] 51 52 self.message_buffer_names = [] 53 54 def __repr__(self): 55 return "[StateMachine: %s]" % self.ident 56 57 def addState(self, state): 58 assert self.table is None 59 self.states[state.ident] = state 60 61 def addEvent(self, event): 62 assert self.table is None 63 self.events[event.ident] = event 64 65 def addAction(self, action): 66 assert self.table is None 67 68 # Check for duplicate action 69 for other in self.actions.itervalues(): 70 if action.ident == other.ident: 71 action.warning("Duplicate action definition: %s" % action.ident) 72 action.error("Duplicate action definition: %s" % action.ident) 73 if action.short == other.short: 74 other.warning("Duplicate action shorthand: %s" % other.ident) 75 other.warning(" shorthand = %s" % other.short) 76 action.warning("Duplicate action shorthand: %s" % action.ident) 77 action.error(" shorthand = %s" % action.short) 78 79 self.actions[action.ident] = action 80 81 def addTransition(self, trans): 82 assert self.table is None 83 self.transitions.append(trans) 84 85 def addInPort(self, var): 86 self.in_ports.append(var) 87 88 def addFunc(self, func): 89 # register func in the symbol table 90 self.symtab.registerSym(str(func), func) 91 self.functions.append(func) 92 93 def addObject(self, obj): 94 self.objects.append(obj) 95 96 # Needs to be called before accessing the table 97 def buildTable(self): 98 assert self.table is None 99 100 table = {} 101 102 for trans in self.transitions: 103 # Track which actions we touch so we know if we use them 104 # all -- really this should be done for all symbols as 105 # part of the symbol table, then only trigger it for 106 # Actions, States, Events, etc. 107 108 for action in trans.actions: 109 action.used = True 110 111 index = (trans.state, trans.event) 112 if index in table: 113 table[index].warning("Duplicate transition: %s" % table[index]) 114 trans.error("Duplicate transition: %s" % trans) 115 table[index] = trans 116 117 # Look at all actions to make sure we used them all 118 for action in self.actions.itervalues(): 119 if not action.used: 120 error_msg = "Unused action: %s" % action.ident 121 if "desc" in action: 122 error_msg += ", " + action.desc 123 action.warning(error_msg) 124 self.table = table 125 126 def writeCodeFiles(self, path): 127 self.printControllerHH(path) 128 self.printControllerCC(path) 129 self.printCSwitch(path) 130 self.printCWakeup(path) 131 self.printProfilerCC(path) 132 self.printProfilerHH(path) 133 134 for func in self.functions: 135 func.writeCodeFiles(path) 136 137 def printControllerHH(self, path): 138 '''Output the method declarations for the class declaration''' 139 code = code_formatter() 140 ident = self.ident 141 c_ident = "%s_Controller" % self.ident 142 143 self.message_buffer_names = [] 144 145 code(''' 146/** \\file $ident.hh 147 * 148 * Auto generated C++ code started by $__file__:$__line__ 149 * Created by slicc definition of Module "${{self.short}}" 150 */ 151 152#ifndef ${ident}_CONTROLLER_H 153#define ${ident}_CONTROLLER_H 154 155#include "mem/ruby/common/Global.hh" 156#include "mem/ruby/common/Consumer.hh" 157#include "mem/ruby/slicc_interface/AbstractController.hh" 158#include "mem/protocol/TransitionResult.hh" 159#include "mem/protocol/Types.hh" 160#include "mem/protocol/${ident}_Profiler.hh" 161''') 162 163 seen_types = set() 164 for var in self.objects: 165 if var.type.ident not in seen_types and not var.type.isPrimitive: 166 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 167 seen_types.add(var.type.ident) 168 169 # for adding information to the protocol debug trace 170 code(''' 171extern stringstream ${ident}_transitionComment; 172 173class $c_ident : public AbstractController { 174#ifdef CHECK_COHERENCE 175#endif /* CHECK_COHERENCE */ 176public: 177 $c_ident(const string & name); 178 static int getNumControllers(); 179 void init(Network* net_ptr, const vector<string> & argv); 180 MessageBuffer* getMandatoryQueue() const; 181 const int & getVersion() const; 182 const string toString() const; 183 const string getName() const; 184 const MachineType getMachineType() const; 185 void print(ostream& out) const; 186 void printConfig(ostream& out) const; 187 void wakeup(); 188 void set_atomic(Address addr);
|
189 void started_writes(); 190 void clear_atomic();
| 189 void clear_atomic(Address addr); 190 void reset_atomics();
|
191 void printStats(ostream& out) const { s_profiler.dumpStats(out); } 192 void clearStats() { s_profiler.clearStats(); } 193private: 194''') 195 196 code.indent() 197 # added by SS 198 for param in self.config_parameters: 199 code('int m_${{param.ident}};') 200 201 if self.ident == "L1Cache": 202 code(''' 203int servicing_atomic;
| 191 void printStats(ostream& out) const { s_profiler.dumpStats(out); } 192 void clearStats() { s_profiler.clearStats(); } 193private: 194''') 195 196 code.indent() 197 # added by SS 198 for param in self.config_parameters: 199 code('int m_${{param.ident}};') 200 201 if self.ident == "L1Cache": 202 code(''' 203int servicing_atomic;
|
204bool started_receiving_writes;
| |
205Address locked_read_request1; 206Address locked_read_request2; 207Address locked_read_request3; 208Address locked_read_request4; 209int read_counter; 210''') 211 212 code(''' 213int m_number_of_TBEs; 214 215TransitionResult doTransition(${ident}_Event event, ${ident}_State state, const Address& addr); // in ${ident}_Transitions.cc 216TransitionResult doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr); // in ${ident}_Transitions.cc 217string m_name; 218int m_transitions_per_cycle; 219int m_buffer_size; 220int m_recycle_latency; 221map< string, string > m_cfg; 222NodeID m_version; 223Network* m_net_ptr; 224MachineID m_machineID; 225${ident}_Profiler s_profiler; 226static int m_num_controllers; 227// Internal functions 228''') 229 230 for func in self.functions: 231 proto = func.prototype 232 if proto: 233 code('$proto') 234 235 code(''' 236 237// Actions 238''') 239 for action in self.actions.itervalues(): 240 code('/** \\brief ${{action.desc}} */') 241 code('void ${{action.ident}}(const Address& addr);') 242 243 # the controller internal variables 244 code(''' 245 246// Object 247''') 248 for var in self.objects: 249 th = var.get("template_hack", "") 250 code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') 251 252 if var.type.ident == "MessageBuffer": 253 self.message_buffer_names.append("m_%s_ptr" % var.c_ident) 254 255 code.dedent() 256 code('};') 257 code('#endif // ${ident}_CONTROLLER_H') 258 code.write(path, '%s.hh' % c_ident) 259 260 def printControllerCC(self, path): 261 '''Output the actions for performing the actions''' 262 263 code = code_formatter() 264 ident = self.ident 265 c_ident = "%s_Controller" % self.ident 266 267 code(''' 268/** \\file $ident.cc 269 * 270 * Auto generated C++ code started by $__file__:$__line__ 271 * Created by slicc definition of Module "${{self.short}}" 272 */ 273 274#include "mem/ruby/common/Global.hh" 275#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 276#include "mem/protocol/${ident}_Controller.hh" 277#include "mem/protocol/${ident}_State.hh" 278#include "mem/protocol/${ident}_Event.hh" 279#include "mem/protocol/Types.hh" 280#include "mem/ruby/system/System.hh" 281''') 282 283 # include object classes 284 seen_types = set() 285 for var in self.objects: 286 if var.type.ident not in seen_types and not var.type.isPrimitive: 287 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 288 seen_types.add(var.type.ident) 289 290 code(''' 291int $c_ident::m_num_controllers = 0; 292 293stringstream ${ident}_transitionComment; 294#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 295/** \\brief constructor */ 296$c_ident::$c_ident(const string &name) 297 : m_name(name) 298{ 299''') 300 code.indent() 301 if self.ident == "L1Cache": 302 code(''' 303servicing_atomic = 0;
| 204Address locked_read_request1; 205Address locked_read_request2; 206Address locked_read_request3; 207Address locked_read_request4; 208int read_counter; 209''') 210 211 code(''' 212int m_number_of_TBEs; 213 214TransitionResult doTransition(${ident}_Event event, ${ident}_State state, const Address& addr); // in ${ident}_Transitions.cc 215TransitionResult doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr); // in ${ident}_Transitions.cc 216string m_name; 217int m_transitions_per_cycle; 218int m_buffer_size; 219int m_recycle_latency; 220map< string, string > m_cfg; 221NodeID m_version; 222Network* m_net_ptr; 223MachineID m_machineID; 224${ident}_Profiler s_profiler; 225static int m_num_controllers; 226// Internal functions 227''') 228 229 for func in self.functions: 230 proto = func.prototype 231 if proto: 232 code('$proto') 233 234 code(''' 235 236// Actions 237''') 238 for action in self.actions.itervalues(): 239 code('/** \\brief ${{action.desc}} */') 240 code('void ${{action.ident}}(const Address& addr);') 241 242 # the controller internal variables 243 code(''' 244 245// Object 246''') 247 for var in self.objects: 248 th = var.get("template_hack", "") 249 code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') 250 251 if var.type.ident == "MessageBuffer": 252 self.message_buffer_names.append("m_%s_ptr" % var.c_ident) 253 254 code.dedent() 255 code('};') 256 code('#endif // ${ident}_CONTROLLER_H') 257 code.write(path, '%s.hh' % c_ident) 258 259 def printControllerCC(self, path): 260 '''Output the actions for performing the actions''' 261 262 code = code_formatter() 263 ident = self.ident 264 c_ident = "%s_Controller" % self.ident 265 266 code(''' 267/** \\file $ident.cc 268 * 269 * Auto generated C++ code started by $__file__:$__line__ 270 * Created by slicc definition of Module "${{self.short}}" 271 */ 272 273#include "mem/ruby/common/Global.hh" 274#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 275#include "mem/protocol/${ident}_Controller.hh" 276#include "mem/protocol/${ident}_State.hh" 277#include "mem/protocol/${ident}_Event.hh" 278#include "mem/protocol/Types.hh" 279#include "mem/ruby/system/System.hh" 280''') 281 282 # include object classes 283 seen_types = set() 284 for var in self.objects: 285 if var.type.ident not in seen_types and not var.type.isPrimitive: 286 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 287 seen_types.add(var.type.ident) 288 289 code(''' 290int $c_ident::m_num_controllers = 0; 291 292stringstream ${ident}_transitionComment; 293#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 294/** \\brief constructor */ 295$c_ident::$c_ident(const string &name) 296 : m_name(name) 297{ 298''') 299 code.indent() 300 if self.ident == "L1Cache": 301 code(''' 302servicing_atomic = 0;
|
304started_receiving_writes = false;
| |
305locked_read_request1 = Address(-1); 306locked_read_request2 = Address(-1); 307locked_read_request3 = Address(-1); 308locked_read_request4 = Address(-1); 309read_counter = 0; 310''') 311 312 code('m_num_controllers++;') 313 for var in self.objects: 314 if var.ident.find("mandatoryQueue") >= 0: 315 code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();') 316 317 code.dedent() 318 code(''' 319} 320 321void $c_ident::init(Network *net_ptr, const vector<string> &argv) 322{ 323 for (size_t i = 0; i < argv.size(); i += 2) { 324 if (argv[i] == "version") 325 m_version = atoi(argv[i+1].c_str()); 326 else if (argv[i] == "transitions_per_cycle") 327 m_transitions_per_cycle = atoi(argv[i+1].c_str()); 328 else if (argv[i] == "buffer_size") 329 m_buffer_size = atoi(argv[i+1].c_str()); 330 else if (argv[i] == "recycle_latency") 331 m_recycle_latency = atoi(argv[i+1].c_str()); 332 else if (argv[i] == "number_of_TBEs") 333 m_number_of_TBEs = atoi(argv[i+1].c_str()); 334''') 335 336 code.indent() 337 code.indent() 338 for param in self.config_parameters: 339 code('else if (argv[i] == "${{param.name}}")') 340 if param.type_ast.type.ident == "int": 341 code(' m_${{param.name}} = atoi(argv[i+1].c_str());') 342 elif param.type_ast.type.ident == "bool": 343 code(' m_${{param.name}} = string_to_bool(argv[i+1]);') 344 else: 345 self.error("only int and bool parameters are "\ 346 "currently supported") 347 code.dedent() 348 code.dedent() 349 code(''' 350 } 351 352 m_net_ptr = net_ptr; 353 m_machineID.type = MachineType_${ident}; 354 m_machineID.num = m_version; 355 for (size_t i = 0; i < argv.size(); i += 2) { 356 if (argv[i] != "version") 357 m_cfg[argv[i]] = argv[i+1]; 358 } 359 360 // Objects 361 s_profiler.setVersion(m_version); 362''') 363 364 code.indent() 365 for var in self.objects: 366 vtype = var.type 367 vid = "m_%s_ptr" % var.c_ident 368 if "network" not in var: 369 # Not a network port object 370 if "primitive" in vtype: 371 code('$vid = new ${{vtype.c_ident}};') 372 if "default" in var: 373 code('(*$vid) = ${{var["default"]}};') 374 else: 375 # Normal Object 376 # added by SS 377 if "factory" in var: 378 code('$vid = ${{var["factory"]}};') 379 elif var.ident.find("mandatoryQueue") < 0: 380 th = var.get("template_hack", "") 381 expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 382 383 args = "" 384 if "non_obj" not in vtype and not vtype.isEnumeration: 385 if expr.find("TBETable") >= 0: 386 args = "m_number_of_TBEs" 387 else: 388 args = var.get("constructor_hack", "") 389 args = "(%s)" % args 390 391 code('$expr$args;') 392 else: 393 code(';') 394 395 code('assert($vid != NULL);') 396 397 if "default" in var: 398 code('(*$vid) = ${{var["default"]}}; // Object default') 399 elif "default" in vtype: 400 code('(*$vid) = ${{vtype["default"]}}; // Type ${{vtype.ident}} default') 401 402 # Set ordering 403 if "ordered" in var and "trigger_queue" not in var: 404 # A buffer 405 code('$vid->setOrdering(${{var["ordered"]}});') 406 407 # Set randomization 408 if "random" in var: 409 # A buffer 410 code('$vid->setRandomization(${{var["random"]}});') 411 412 # Set Priority 413 if vtype.isBuffer and \ 414 "rank" in var and "trigger_queue" not in var: 415 code('$vid->setPriority(${{var["rank"]}});') 416 else: 417 # Network port object 418 network = var["network"] 419 ordered = var["ordered"] 420 vnet = var["virtual_network"] 421 422 assert var.machine is not None 423 code(''' 424$vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string_to_MachineType("${{var.machine.ident}}")), $ordered, $vnet); 425''') 426 427 code('assert($vid != NULL);') 428 429 # Set ordering 430 if "ordered" in var: 431 # A buffer 432 code('$vid->setOrdering(${{var["ordered"]}});') 433 434 # Set randomization 435 if "random" in var: 436 # A buffer 437 code('$vid->setRandomization(${{var["random"]}})') 438 439 # Set Priority 440 if "rank" in var: 441 code('$vid->setPriority(${{var["rank"]}})') 442 443 # Set buffer size 444 if vtype.isBuffer: 445 code(''' 446if (m_buffer_size > 0) { 447 $vid->setSize(m_buffer_size); 448} 449''') 450 451 # set description (may be overriden later by port def) 452 code('$vid->setDescription("[Version " + int_to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");') 453 454 # Set the queue consumers 455 code.insert_newline() 456 for port in self.in_ports: 457 code('${{port.code}}.setConsumer(this);') 458 459 # Set the queue descriptions 460 code.insert_newline() 461 for port in self.in_ports: 462 code('${{port.code}}.setDescription("[Version " + int_to_string(m_version) + ", $ident, $port]");') 463 464 # Initialize the transition profiling 465 code.insert_newline() 466 for trans in self.transitions: 467 # Figure out if we stall 468 stall = False 469 for action in trans.actions: 470 if action.ident == "z_stall": 471 stall = True 472 473 # Only possible if it is not a 'z' case 474 if not stall: 475 state = "%s_State_%s" % (self.ident, trans.state.ident) 476 event = "%s_Event_%s" % (self.ident, trans.event.ident) 477 code('s_profiler.possibleTransition($state, $event);') 478 479 # added by SS to initialize recycle_latency of message buffers 480 for buf in self.message_buffer_names: 481 code("$buf->setRecycleLatency(m_recycle_latency);") 482 483 code.dedent() 484 code('}') 485 486 has_mandatory_q = False 487 for port in self.in_ports: 488 if port.code.find("mandatoryQueue_ptr") >= 0: 489 has_mandatory_q = True 490 491 if has_mandatory_q: 492 mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident 493 else: 494 mq_ident = "NULL" 495 496 code(''' 497int $c_ident::getNumControllers() { 498 return m_num_controllers; 499} 500 501MessageBuffer* $c_ident::getMandatoryQueue() const { 502 return $mq_ident; 503} 504 505const int & $c_ident::getVersion() const{ 506 return m_version; 507} 508 509const string $c_ident::toString() const{ 510 return "$c_ident"; 511} 512 513const string $c_ident::getName() const{ 514 return m_name; 515} 516const MachineType $c_ident::getMachineType() const{ 517 return MachineType_${ident}; 518} 519 520void $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; } 521 522void $c_ident::printConfig(ostream& out) const { 523 out << "$c_ident config: " << m_name << endl; 524 out << " version: " << m_version << endl; 525 for (map<string, string>::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) { 526 out << " " << (*it).first << ": " << (*it).second << endl; 527 } 528} 529 530// Actions 531''') 532 533 for action in self.actions.itervalues(): 534 if "c_code" not in action: 535 continue 536 537 code(''' 538/** \\brief ${{action.desc}} */ 539void $c_ident::${{action.ident}}(const Address& addr) 540{ 541 DEBUG_MSG(GENERATED_COMP, HighPrio, "executing"); 542 ${{action["c_code"]}} 543} 544 545''') 546 code.write(path, "%s.cc" % c_ident) 547 548 def printCWakeup(self, path): 549 '''Output the wakeup loop for the events''' 550 551 code = code_formatter() 552 ident = self.ident 553 554 code(''' 555// Auto generated C++ code started by $__file__:$__line__ 556// ${ident}: ${{self.short}} 557 558#include "mem/ruby/common/Global.hh" 559#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 560#include "mem/protocol/${ident}_Controller.hh" 561#include "mem/protocol/${ident}_State.hh" 562#include "mem/protocol/${ident}_Event.hh" 563#include "mem/protocol/Types.hh" 564#include "mem/ruby/system/System.hh" 565 566void ${ident}_Controller::wakeup() 567{ 568 569 int counter = 0; 570 while (true) { 571 // Some cases will put us into an infinite loop without this limit 572 assert(counter <= m_transitions_per_cycle); 573 if (counter == m_transitions_per_cycle) { 574 g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we\'re fully utilized 575 g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again 576 break; 577 } 578''') 579 580 code.indent() 581 code.indent() 582 583 # InPorts 584 # 585 # Find the position of the mandatory queue in the vector so 586 # that we can print it out first 587 588 mandatory_q = None 589 if self.ident == "L1Cache": 590 for i,port in enumerate(self.in_ports): 591 assert "c_code_in_port" in port 592 if str(port).find("mandatoryQueue_in") >= 0: 593 assert mandatory_q is None 594 mandatory_q = port 595 596 assert mandatory_q is not None 597 598 # print out the mandatory queue here 599 port = mandatory_q 600 code('// ${ident}InPort $port') 601 output = port["c_code_in_port"] 602
| 303locked_read_request1 = Address(-1); 304locked_read_request2 = Address(-1); 305locked_read_request3 = Address(-1); 306locked_read_request4 = Address(-1); 307read_counter = 0; 308''') 309 310 code('m_num_controllers++;') 311 for var in self.objects: 312 if var.ident.find("mandatoryQueue") >= 0: 313 code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();') 314 315 code.dedent() 316 code(''' 317} 318 319void $c_ident::init(Network *net_ptr, const vector<string> &argv) 320{ 321 for (size_t i = 0; i < argv.size(); i += 2) { 322 if (argv[i] == "version") 323 m_version = atoi(argv[i+1].c_str()); 324 else if (argv[i] == "transitions_per_cycle") 325 m_transitions_per_cycle = atoi(argv[i+1].c_str()); 326 else if (argv[i] == "buffer_size") 327 m_buffer_size = atoi(argv[i+1].c_str()); 328 else if (argv[i] == "recycle_latency") 329 m_recycle_latency = atoi(argv[i+1].c_str()); 330 else if (argv[i] == "number_of_TBEs") 331 m_number_of_TBEs = atoi(argv[i+1].c_str()); 332''') 333 334 code.indent() 335 code.indent() 336 for param in self.config_parameters: 337 code('else if (argv[i] == "${{param.name}}")') 338 if param.type_ast.type.ident == "int": 339 code(' m_${{param.name}} = atoi(argv[i+1].c_str());') 340 elif param.type_ast.type.ident == "bool": 341 code(' m_${{param.name}} = string_to_bool(argv[i+1]);') 342 else: 343 self.error("only int and bool parameters are "\ 344 "currently supported") 345 code.dedent() 346 code.dedent() 347 code(''' 348 } 349 350 m_net_ptr = net_ptr; 351 m_machineID.type = MachineType_${ident}; 352 m_machineID.num = m_version; 353 for (size_t i = 0; i < argv.size(); i += 2) { 354 if (argv[i] != "version") 355 m_cfg[argv[i]] = argv[i+1]; 356 } 357 358 // Objects 359 s_profiler.setVersion(m_version); 360''') 361 362 code.indent() 363 for var in self.objects: 364 vtype = var.type 365 vid = "m_%s_ptr" % var.c_ident 366 if "network" not in var: 367 # Not a network port object 368 if "primitive" in vtype: 369 code('$vid = new ${{vtype.c_ident}};') 370 if "default" in var: 371 code('(*$vid) = ${{var["default"]}};') 372 else: 373 # Normal Object 374 # added by SS 375 if "factory" in var: 376 code('$vid = ${{var["factory"]}};') 377 elif var.ident.find("mandatoryQueue") < 0: 378 th = var.get("template_hack", "") 379 expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 380 381 args = "" 382 if "non_obj" not in vtype and not vtype.isEnumeration: 383 if expr.find("TBETable") >= 0: 384 args = "m_number_of_TBEs" 385 else: 386 args = var.get("constructor_hack", "") 387 args = "(%s)" % args 388 389 code('$expr$args;') 390 else: 391 code(';') 392 393 code('assert($vid != NULL);') 394 395 if "default" in var: 396 code('(*$vid) = ${{var["default"]}}; // Object default') 397 elif "default" in vtype: 398 code('(*$vid) = ${{vtype["default"]}}; // Type ${{vtype.ident}} default') 399 400 # Set ordering 401 if "ordered" in var and "trigger_queue" not in var: 402 # A buffer 403 code('$vid->setOrdering(${{var["ordered"]}});') 404 405 # Set randomization 406 if "random" in var: 407 # A buffer 408 code('$vid->setRandomization(${{var["random"]}});') 409 410 # Set Priority 411 if vtype.isBuffer and \ 412 "rank" in var and "trigger_queue" not in var: 413 code('$vid->setPriority(${{var["rank"]}});') 414 else: 415 # Network port object 416 network = var["network"] 417 ordered = var["ordered"] 418 vnet = var["virtual_network"] 419 420 assert var.machine is not None 421 code(''' 422$vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string_to_MachineType("${{var.machine.ident}}")), $ordered, $vnet); 423''') 424 425 code('assert($vid != NULL);') 426 427 # Set ordering 428 if "ordered" in var: 429 # A buffer 430 code('$vid->setOrdering(${{var["ordered"]}});') 431 432 # Set randomization 433 if "random" in var: 434 # A buffer 435 code('$vid->setRandomization(${{var["random"]}})') 436 437 # Set Priority 438 if "rank" in var: 439 code('$vid->setPriority(${{var["rank"]}})') 440 441 # Set buffer size 442 if vtype.isBuffer: 443 code(''' 444if (m_buffer_size > 0) { 445 $vid->setSize(m_buffer_size); 446} 447''') 448 449 # set description (may be overriden later by port def) 450 code('$vid->setDescription("[Version " + int_to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");') 451 452 # Set the queue consumers 453 code.insert_newline() 454 for port in self.in_ports: 455 code('${{port.code}}.setConsumer(this);') 456 457 # Set the queue descriptions 458 code.insert_newline() 459 for port in self.in_ports: 460 code('${{port.code}}.setDescription("[Version " + int_to_string(m_version) + ", $ident, $port]");') 461 462 # Initialize the transition profiling 463 code.insert_newline() 464 for trans in self.transitions: 465 # Figure out if we stall 466 stall = False 467 for action in trans.actions: 468 if action.ident == "z_stall": 469 stall = True 470 471 # Only possible if it is not a 'z' case 472 if not stall: 473 state = "%s_State_%s" % (self.ident, trans.state.ident) 474 event = "%s_Event_%s" % (self.ident, trans.event.ident) 475 code('s_profiler.possibleTransition($state, $event);') 476 477 # added by SS to initialize recycle_latency of message buffers 478 for buf in self.message_buffer_names: 479 code("$buf->setRecycleLatency(m_recycle_latency);") 480 481 code.dedent() 482 code('}') 483 484 has_mandatory_q = False 485 for port in self.in_ports: 486 if port.code.find("mandatoryQueue_ptr") >= 0: 487 has_mandatory_q = True 488 489 if has_mandatory_q: 490 mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident 491 else: 492 mq_ident = "NULL" 493 494 code(''' 495int $c_ident::getNumControllers() { 496 return m_num_controllers; 497} 498 499MessageBuffer* $c_ident::getMandatoryQueue() const { 500 return $mq_ident; 501} 502 503const int & $c_ident::getVersion() const{ 504 return m_version; 505} 506 507const string $c_ident::toString() const{ 508 return "$c_ident"; 509} 510 511const string $c_ident::getName() const{ 512 return m_name; 513} 514const MachineType $c_ident::getMachineType() const{ 515 return MachineType_${ident}; 516} 517 518void $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; } 519 520void $c_ident::printConfig(ostream& out) const { 521 out << "$c_ident config: " << m_name << endl; 522 out << " version: " << m_version << endl; 523 for (map<string, string>::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) { 524 out << " " << (*it).first << ": " << (*it).second << endl; 525 } 526} 527 528// Actions 529''') 530 531 for action in self.actions.itervalues(): 532 if "c_code" not in action: 533 continue 534 535 code(''' 536/** \\brief ${{action.desc}} */ 537void $c_ident::${{action.ident}}(const Address& addr) 538{ 539 DEBUG_MSG(GENERATED_COMP, HighPrio, "executing"); 540 ${{action["c_code"]}} 541} 542 543''') 544 code.write(path, "%s.cc" % c_ident) 545 546 def printCWakeup(self, path): 547 '''Output the wakeup loop for the events''' 548 549 code = code_formatter() 550 ident = self.ident 551 552 code(''' 553// Auto generated C++ code started by $__file__:$__line__ 554// ${ident}: ${{self.short}} 555 556#include "mem/ruby/common/Global.hh" 557#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 558#include "mem/protocol/${ident}_Controller.hh" 559#include "mem/protocol/${ident}_State.hh" 560#include "mem/protocol/${ident}_Event.hh" 561#include "mem/protocol/Types.hh" 562#include "mem/ruby/system/System.hh" 563 564void ${ident}_Controller::wakeup() 565{ 566 567 int counter = 0; 568 while (true) { 569 // Some cases will put us into an infinite loop without this limit 570 assert(counter <= m_transitions_per_cycle); 571 if (counter == m_transitions_per_cycle) { 572 g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we\'re fully utilized 573 g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again 574 break; 575 } 576''') 577 578 code.indent() 579 code.indent() 580 581 # InPorts 582 # 583 # Find the position of the mandatory queue in the vector so 584 # that we can print it out first 585 586 mandatory_q = None 587 if self.ident == "L1Cache": 588 for i,port in enumerate(self.in_ports): 589 assert "c_code_in_port" in port 590 if str(port).find("mandatoryQueue_in") >= 0: 591 assert mandatory_q is None 592 mandatory_q = port 593 594 assert mandatory_q is not None 595 596 # print out the mandatory queue here 597 port = mandatory_q 598 code('// ${ident}InPort $port') 599 output = port["c_code_in_port"] 600
|
603 pos = output.find("TransitionResult result = doTransition((L1Cache_mandatory_request_type_to_event(((*in_msg_ptr)).m_Type)), L1Cache_getState(addr), addr);") 604 assert pos >= 0 605 atomics_string = ''' 606if ((((*in_msg_ptr)).m_Type) == CacheRequestType_ATOMIC) { 607 if (servicing_atomic == 0) { 608 if (locked_read_request1 == Address(-1)) { 609 assert(read_counter == 0); 610 locked_read_request1 = addr; 611 assert(read_counter == 0); 612 read_counter++; 613 } 614 else if (addr == locked_read_request1) { 615 ; // do nothing 616 } 617 else { 618 assert(0); // should never be here if servicing one request at a time 619 } 620 } 621 else if (!started_receiving_writes) { 622 if (servicing_atomic == 1) { 623 if (locked_read_request2 == Address(-1)) { 624 assert(locked_read_request1 != Address(-1)); 625 assert(read_counter == 1); 626 locked_read_request2 = addr; 627 assert(read_counter == 1); 628 read_counter++; 629 } 630 else if (addr == locked_read_request2) { 631 ; // do nothing 632 } 633 else { 634 assert(0); // should never be here if servicing one request at a time 635 } 636 } 637 else if (servicing_atomic == 2) { 638 if (locked_read_request3 == Address(-1)) { 639 assert(locked_read_request1 != Address(-1)); 640 assert(locked_read_request2 != Address(-1)); 641 assert(read_counter == 1); 642 locked_read_request3 = addr; 643 assert(read_counter == 2); 644 read_counter++; 645 } 646 else if (addr == locked_read_request3) { 647 ; // do nothing 648 } 649 else { 650 assert(0); // should never be here if servicing one request at a time 651 } 652 } 653 else if (servicing_atomic == 3) { 654 if (locked_read_request4 == Address(-1)) { 655 assert(locked_read_request1 != Address(-1)); 656 assert(locked_read_request2 != Address(-1)); 657 assert(locked_read_request3 != Address(-1)); 658 assert(read_counter == 1); 659 locked_read_request4 = addr; 660 assert(read_counter == 3); 661 read_counter++; 662 } 663 else if (addr == locked_read_request4) { 664 ; // do nothing 665 } 666 else { 667 assert(0); // should never be here if servicing one request at a time 668 } 669 } 670 else { 671 assert(0); 672 } 673 } 674} 675else { 676 if (servicing_atomic > 0) { 677 // reset 678 servicing_atomic = 0; 679 read_counter = 0; 680 started_receiving_writes = false; 681 locked_read_request1 = Address(-1); 682 locked_read_request2 = Address(-1); 683 locked_read_request3 = Address(-1); 684 locked_read_request4 = Address(-1); 685 } 686} 687''' 688 689 output = output[:pos] + atomics_string + output[pos:]
| |
690 code('$output') 691 692 for port in self.in_ports: 693 # don't print out mandatory queue twice 694 if port == mandatory_q: 695 continue 696 697 if ident == "L1Cache":
| 601 code('$output') 602 603 for port in self.in_ports: 604 # don't print out mandatory queue twice 605 if port == mandatory_q: 606 continue 607 608 if ident == "L1Cache":
|
698 if str(port).find("forwardRequestNetwork_in") >= 0:
| 609 if (str(port).find("forwardRequestNetwork_in") >= 0 or str(port).find("requestNetwork_in") >= 0 or str(port).find("requestIntraChipL1Network_in") >= 0):
|
699 code(''' 700bool postpone = false; 701if ((((*m_L1Cache_forwardToCache_ptr)).isReady())) { 702 const RequestMsg* in_msg_ptr; 703 in_msg_ptr = dynamic_cast<const RequestMsg*>(((*m_L1Cache_forwardToCache_ptr)).peek());
| 610 code(''' 611bool postpone = false; 612if ((((*m_L1Cache_forwardToCache_ptr)).isReady())) { 613 const RequestMsg* in_msg_ptr; 614 in_msg_ptr = dynamic_cast<const RequestMsg*>(((*m_L1Cache_forwardToCache_ptr)).peek());
|
704 if ((((servicing_atomic == 1) && (locked_read_request1 == ((*in_msg_ptr)).m_Address)) || 705 ((servicing_atomic == 2) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address)) || 706 ((servicing_atomic == 3) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address)) || 707 ((servicing_atomic == 4) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address || locked_read_request1 == ((*in_msg_ptr)).m_Address)))) { 708 postpone = true;
| 615 if ((((servicing_atomic > 0) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address || locked_read_request1 == ((*in_msg_ptr)).m_Address)))) { 616 postpone = true;
|
709 } 710} 711if (!postpone) { 712''') 713 code.indent() 714 code('// ${ident}InPort $port') 715 code('${{port["c_code_in_port"]}}') 716 code.dedent() 717 718 if ident == "L1Cache":
| 617 } 618} 619if (!postpone) { 620''') 621 code.indent() 622 code('// ${ident}InPort $port') 623 code('${{port["c_code_in_port"]}}') 624 code.dedent() 625 626 if ident == "L1Cache":
|
719 if str(port).find("forwardRequestNetwork_in") >= 0:
| 627 if (str(port).find("forwardRequestNetwork_in") >= 0 or str(port).find("requestNetwork_in") >= 0 or str(port).find("requestIntraChipL1Network_in") >= 0):
|
720 code.dedent() 721 code('}') 722 code.indent() 723 code('') 724 725 code.dedent() 726 code.dedent() 727 code(''' 728 break; // If we got this far, we have nothing left todo 729 } 730} 731''') 732 733 if self.ident == "L1Cache": 734 code(''' 735void ${ident}_Controller::set_atomic(Address addr) 736{ 737 servicing_atomic++;
| 628 code.dedent() 629 code('}') 630 code.indent() 631 code('') 632 633 code.dedent() 634 code.dedent() 635 code(''' 636 break; // If we got this far, we have nothing left todo 637 } 638} 639''') 640 641 if self.ident == "L1Cache": 642 code(''' 643void ${ident}_Controller::set_atomic(Address addr) 644{ 645 servicing_atomic++;
|
| 646 switch (servicing_atomic) { 647 case(1): 648 assert(locked_read_request1 == Address(-1)); 649 locked_read_request1 = addr; 650 break; 651 case(2): 652 assert(locked_read_request2 == Address(-1)); 653 locked_read_request2 = addr; 654 break; 655 case(3): 656 assert(locked_read_request3 == Address(-1)); 657 locked_read_request3 = addr; 658 break; 659 case(4): 660 assert(locked_read_request4 == Address(-1)); 661 locked_read_request4 = addr; 662 break; 663 default: 664 assert(0); 665 666 }
|
738} 739
| 667} 668
|
740void ${ident}_Controller::started_writes()
| 669void ${ident}_Controller::clear_atomic(Address addr)
|
741{
| 670{
|
742 started_receiving_writes = true;
| 671 672 assert(servicing_atomic > 0); 673 if (addr == locked_read_request1) 674 locked_read_request1 = Address(-1); 675 else if (addr == locked_read_request2) 676 locked_read_request2 = Address(-1); 677 else if (addr == locked_read_request3) 678 locked_read_request3 = Address(-1); 679 else if (addr == locked_read_request4) 680 locked_read_request4 = Address(-1); 681 else 682 assert(0); 683 servicing_atomic--; 684
|
743} 744
| 685} 686
|
745void ${ident}_Controller::clear_atomic()
| 687void ${ident}_Controller::reset_atomics()
|
746{
| 688{
|
747 assert(servicing_atomic > 0); 748 read_counter--; 749 servicing_atomic--; 750 if (read_counter == 0) { 751 servicing_atomic = 0; 752 started_receiving_writes = false; 753 locked_read_request1 = Address(-1); 754 locked_read_request2 = Address(-1); 755 locked_read_request3 = Address(-1); 756 locked_read_request4 = Address(-1); 757 }
| 689 690 servicing_atomic = 0; 691 locked_read_request1 = Address(-1); 692 locked_read_request2 = Address(-1); 693 locked_read_request3 = Address(-1); 694 locked_read_request4 = Address(-1); 695
|
758}
| 696}
|
| 697
|
759''') 760 else: 761 code('''
| 698''') 699 else: 700 code('''
|
762void ${ident}_Controller::started_writes()
| 701void ${ident}_Controller::reset_atomics()
|
763{ 764 assert(0); 765} 766 767void ${ident}_Controller::set_atomic(Address addr) 768{ 769 assert(0); 770} 771
| 702{ 703 assert(0); 704} 705 706void ${ident}_Controller::set_atomic(Address addr) 707{ 708 assert(0); 709} 710
|
772void ${ident}_Controller::clear_atomic()
| 711void ${ident}_Controller::clear_atomic(Address addr)
|
773{ 774 assert(0); 775} 776''') 777 778 779 code.write(path, "%s_Wakeup.cc" % self.ident) 780 781 def printCSwitch(self, path): 782 '''Output switch statement for transition table''' 783 784 code = code_formatter() 785 ident = self.ident 786 787 code(''' 788// Auto generated C++ code started by $__file__:$__line__ 789// ${ident}: ${{self.short}} 790 791#include "mem/ruby/common/Global.hh" 792#include "mem/protocol/${ident}_Controller.hh" 793#include "mem/protocol/${ident}_State.hh" 794#include "mem/protocol/${ident}_Event.hh" 795#include "mem/protocol/Types.hh" 796#include "mem/ruby/system/System.hh" 797 798#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 799 800#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 801#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 802 803TransitionResult ${ident}_Controller::doTransition(${ident}_Event event, ${ident}_State state, const Address& addr 804) 805{ 806 ${ident}_State next_state = state; 807 808 DEBUG_NEWLINE(GENERATED_COMP, MedPrio); 809 DEBUG_MSG(GENERATED_COMP, MedPrio, *this); 810 DEBUG_EXPR(GENERATED_COMP, MedPrio, g_eventQueue_ptr->getTime()); 811 DEBUG_EXPR(GENERATED_COMP, MedPrio,state); 812 DEBUG_EXPR(GENERATED_COMP, MedPrio,event); 813 DEBUG_EXPR(GENERATED_COMP, MedPrio,addr); 814 815 TransitionResult result = doTransitionWorker(event, state, next_state, addr); 816 817 if (result == TransitionResult_Valid) { 818 DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state); 819 DEBUG_NEWLINE(GENERATED_COMP, MedPrio); 820 s_profiler.countTransition(state, event); 821 if (Debug::getProtocolTrace()) { 822 g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, 823 ${ident}_State_to_string(state), 824 ${ident}_Event_to_string(event), 825 ${ident}_State_to_string(next_state), GET_TRANSITION_COMMENT()); 826 } 827 CLEAR_TRANSITION_COMMENT(); 828 ${ident}_setState(addr, next_state); 829 830 } else if (result == TransitionResult_ResourceStall) { 831 if (Debug::getProtocolTrace()) { 832 g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, 833 ${ident}_State_to_string(state), 834 ${ident}_Event_to_string(event), 835 ${ident}_State_to_string(next_state), 836 "Resource Stall"); 837 } 838 } else if (result == TransitionResult_ProtocolStall) { 839 DEBUG_MSG(GENERATED_COMP, HighPrio, "stalling"); 840 DEBUG_NEWLINE(GENERATED_COMP, MedPrio); 841 if (Debug::getProtocolTrace()) { 842 g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, 843 ${ident}_State_to_string(state), 844 ${ident}_Event_to_string(event), 845 ${ident}_State_to_string(next_state), 846 "Protocol Stall"); 847 } 848 } 849 850 return result; 851} 852 853TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr 854) 855{ 856 switch(HASH_FUN(state, event)) { 857''') 858 859 # This map will allow suppress generating duplicate code 860 cases = orderdict() 861 862 for trans in self.transitions: 863 case_string = "%s_State_%s, %s_Event_%s" % \ 864 (self.ident, trans.state.ident, self.ident, trans.event.ident) 865 866 case = code_formatter() 867 # Only set next_state if it changes 868 if trans.state != trans.nextState: 869 ns_ident = trans.nextState.ident 870 case('next_state = ${ident}_State_${ns_ident};') 871 872 actions = trans.actions 873 874 # Check for resources 875 case_sorter = [] 876 res = trans.resources 877 for key,val in res.iteritems(): 878 if key.type.ident != "DNUCAStopTable": 879 val = ''' 880if (!%s.areNSlotsAvailable(%s)) { 881 return TransitionResult_ResourceStall; 882} 883''' % (key.code, val) 884 case_sorter.append(val) 885 886 887 # Emit the code sequences in a sorted order. This makes the 888 # output deterministic (without this the output order can vary 889 # since Map's keys() on a vector of pointers is not deterministic 890 for c in sorted(case_sorter): 891 case("$c") 892 893 # Figure out if we stall 894 stall = False 895 for action in actions: 896 if action.ident == "z_stall": 897 stall = True 898 break 899 900 if stall: 901 case('return TransitionResult_ProtocolStall;') 902 else: 903 for action in actions: 904 case('${{action.ident}}(addr);') 905 case('return TransitionResult_Valid;') 906 907 case = str(case) 908 909 # Look to see if this transition code is unique. 910 if case not in cases: 911 cases[case] = [] 912 913 cases[case].append(case_string) 914 915 # Walk through all of the unique code blocks and spit out the 916 # corresponding case statement elements 917 for case,transitions in cases.iteritems(): 918 # Iterative over all the multiple transitions that share 919 # the same code 920 for trans in transitions: 921 code(' case HASH_FUN($trans):') 922 code(' {') 923 code(' $case') 924 code(' }') 925 926 code(''' 927 default: 928 WARN_EXPR(m_version); 929 WARN_EXPR(g_eventQueue_ptr->getTime()); 930 WARN_EXPR(addr); 931 WARN_EXPR(event); 932 WARN_EXPR(state); 933 ERROR_MSG(\"Invalid transition\"); 934 } 935 return TransitionResult_Valid; 936} 937''') 938 code.write(path, "%s_Transitions.cc" % self.ident) 939 940 def printProfilerHH(self, path): 941 code = code_formatter() 942 ident = self.ident 943 944 code(''' 945// Auto generated C++ code started by $__file__:$__line__ 946// ${ident}: ${{self.short}} 947 948#ifndef ${ident}_PROFILER_H 949#define ${ident}_PROFILER_H 950 951#include "mem/ruby/common/Global.hh" 952#include "mem/protocol/${ident}_State.hh" 953#include "mem/protocol/${ident}_Event.hh" 954 955class ${ident}_Profiler { 956 public: 957 ${ident}_Profiler(); 958 void setVersion(int version); 959 void countTransition(${ident}_State state, ${ident}_Event event); 960 void possibleTransition(${ident}_State state, ${ident}_Event event); 961 void dumpStats(ostream& out) const; 962 void clearStats(); 963 964 private: 965 int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 966 int m_event_counters[${ident}_Event_NUM]; 967 bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 968 int m_version; 969}; 970 971#endif // ${ident}_PROFILER_H 972''') 973 code.write(path, "%s_Profiler.hh" % self.ident) 974 975 def printProfilerCC(self, path): 976 code = code_formatter() 977 ident = self.ident 978 979 code(''' 980// Auto generated C++ code started by $__file__:$__line__ 981// ${ident}: ${{self.short}} 982 983#include "mem/protocol/${ident}_Profiler.hh" 984 985${ident}_Profiler::${ident}_Profiler() 986{ 987 for (int state = 0; state < ${ident}_State_NUM; state++) { 988 for (int event = 0; event < ${ident}_Event_NUM; event++) { 989 m_possible[state][event] = false; 990 m_counters[state][event] = 0; 991 } 992 } 993 for (int event = 0; event < ${ident}_Event_NUM; event++) { 994 m_event_counters[event] = 0; 995 } 996} 997void ${ident}_Profiler::setVersion(int version) 998{ 999 m_version = version; 1000} 1001void ${ident}_Profiler::clearStats() 1002{ 1003 for (int state = 0; state < ${ident}_State_NUM; state++) { 1004 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1005 m_counters[state][event] = 0; 1006 } 1007 } 1008 1009 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1010 m_event_counters[event] = 0; 1011 } 1012} 1013void ${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) 1014{ 1015 assert(m_possible[state][event]); 1016 m_counters[state][event]++; 1017 m_event_counters[event]++; 1018} 1019void ${ident}_Profiler::possibleTransition(${ident}_State state, ${ident}_Event event) 1020{ 1021 m_possible[state][event] = true; 1022} 1023void ${ident}_Profiler::dumpStats(ostream& out) const 1024{ 1025 out << " --- ${ident} " << m_version << " ---" << endl; 1026 out << " - Event Counts -" << endl; 1027 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1028 int count = m_event_counters[event]; 1029 out << (${ident}_Event) event << " " << count << endl; 1030 } 1031 out << endl; 1032 out << " - Transitions -" << endl; 1033 for (int state = 0; state < ${ident}_State_NUM; state++) { 1034 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1035 if (m_possible[state][event]) { 1036 int count = m_counters[state][event]; 1037 out << (${ident}_State) state << " " << (${ident}_Event) event << " " << count; 1038 if (count == 0) { 1039 out << " <-- "; 1040 } 1041 out << endl; 1042 } 1043 } 1044 out << endl; 1045 } 1046} 1047''') 1048 code.write(path, "%s_Profiler.cc" % self.ident) 1049 1050 # ************************** 1051 # ******* HTML Files ******* 1052 # ************************** 1053 def frameRef(self, click_href, click_target, over_href, over_target_num, 1054 text): 1055 code = code_formatter(fix_newlines=False) 1056 code("""<A href=\"$click_href\" target=\"$click_target\" onMouseOver=\"if (parent.frames[$over_target_num].location != parent.location + '$over_href') { parent.frames[$over_target_num].location='$over_href' }\" >${{html.formatShorthand(text)}}</A>""") 1057 return str(code) 1058 1059 def writeHTMLFiles(self, path): 1060 # Create table with no row hilighted 1061 self.printHTMLTransitions(path, None) 1062 1063 # Generate transition tables 1064 for state in self.states.itervalues(): 1065 self.printHTMLTransitions(path, state) 1066 1067 # Generate action descriptions 1068 for action in self.actions.itervalues(): 1069 name = "%s_action_%s.html" % (self.ident, action.ident) 1070 code = html.createSymbol(action, "Action") 1071 code.write(path, name) 1072 1073 # Generate state descriptions 1074 for state in self.states.itervalues(): 1075 name = "%s_State_%s.html" % (self.ident, state.ident) 1076 code = html.createSymbol(state, "State") 1077 code.write(path, name) 1078 1079 # Generate event descriptions 1080 for event in self.events.itervalues(): 1081 name = "%s_Event_%s.html" % (self.ident, event.ident) 1082 code = html.createSymbol(event, "Event") 1083 code.write(path, name) 1084 1085 def printHTMLTransitions(self, path, active_state): 1086 code = code_formatter() 1087 1088 code(''' 1089<HTML><BODY link="blue" vlink="blue"> 1090 1091<H1 align="center">${{html.formatShorthand(self.short)}}: 1092''') 1093 code.indent() 1094 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1095 mid = machine.ident 1096 if i != 0: 1097 extra = " - " 1098 else: 1099 extra = "" 1100 if machine == self: 1101 code('$extra$mid') 1102 else: 1103 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1104 code.dedent() 1105 1106 code(""" 1107</H1> 1108 1109<TABLE border=1> 1110<TR> 1111 <TH> </TH> 1112""") 1113 1114 for event in self.events.itervalues(): 1115 href = "%s_Event_%s.html" % (self.ident, event.ident) 1116 ref = self.frameRef(href, "Status", href, "1", event.short) 1117 code('<TH bgcolor=white>$ref</TH>') 1118 1119 code('</TR>') 1120 # -- Body of table 1121 for state in self.states.itervalues(): 1122 # -- Each row 1123 if state == active_state: 1124 color = "yellow" 1125 else: 1126 color = "white" 1127 1128 click = "%s_table_%s.html" % (self.ident, state.ident) 1129 over = "%s_State_%s.html" % (self.ident, state.ident) 1130 text = html.formatShorthand(state.short) 1131 ref = self.frameRef(click, "Table", over, "1", state.short) 1132 code(''' 1133<TR> 1134 <TH bgcolor=$color>$ref</TH> 1135''') 1136 1137 # -- One column for each event 1138 for event in self.events.itervalues(): 1139 trans = self.table.get((state,event), None) 1140 if trans is None: 1141 # This is the no transition case 1142 if state == active_state: 1143 color = "#C0C000" 1144 else: 1145 color = "lightgrey" 1146 1147 code('<TD bgcolor=$color> </TD>') 1148 continue 1149 1150 next = trans.nextState 1151 stall_action = False 1152 1153 # -- Get the actions 1154 for action in trans.actions: 1155 if action.ident == "z_stall" or \ 1156 action.ident == "zz_recycleMandatoryQueue": 1157 stall_action = True 1158 1159 # -- Print out "actions/next-state" 1160 if stall_action: 1161 if state == active_state: 1162 color = "#C0C000" 1163 else: 1164 color = "lightgrey" 1165 1166 elif active_state and next.ident == active_state.ident: 1167 color = "aqua" 1168 elif state == active_state: 1169 color = "yellow" 1170 else: 1171 color = "white" 1172 1173 fix = code.nofix() 1174 code('<TD bgcolor=$color>') 1175 for action in trans.actions: 1176 href = "%s_action_%s.html" % (self.ident, action.ident) 1177 ref = self.frameRef(href, "Status", href, "1", 1178 action.short) 1179 code(' $ref\n') 1180 if next != state: 1181 if trans.actions: 1182 code('/') 1183 click = "%s_table_%s.html" % (self.ident, next.ident) 1184 over = "%s_State_%s.html" % (self.ident, next.ident) 1185 ref = self.frameRef(click, "Table", over, "1", next.short) 1186 code("$ref") 1187 code("</TD>\n") 1188 code.fix(fix) 1189 1190 # -- Each row 1191 if state == active_state: 1192 color = "yellow" 1193 else: 1194 color = "white" 1195 1196 click = "%s_table_%s.html" % (self.ident, state.ident) 1197 over = "%s_State_%s.html" % (self.ident, state.ident) 1198 ref = self.frameRef(click, "Table", over, "1", state.short) 1199 code(''' 1200 <TH bgcolor=$color>$ref</TH> 1201</TR> 1202''') 1203 code(''' 1204<TR> 1205 <TH> </TH> 1206''') 1207 1208 for event in self.events.itervalues(): 1209 href = "%s_Event_%s.html" % (self.ident, event.ident) 1210 ref = self.frameRef(href, "Status", href, "1", event.short) 1211 code('<TH bgcolor=white>$ref</TH>') 1212 code(''' 1213</TR> 1214</TABLE> 1215</BODY></HTML> 1216''') 1217 1218 1219 if active_state: 1220 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1221 else: 1222 name = "%s_table.html" % self.ident 1223 code.write(path, name) 1224 1225__all__ = [ "StateMachine" ]
| 712{ 713 assert(0); 714} 715''') 716 717 718 code.write(path, "%s_Wakeup.cc" % self.ident) 719 720 def printCSwitch(self, path): 721 '''Output switch statement for transition table''' 722 723 code = code_formatter() 724 ident = self.ident 725 726 code(''' 727// Auto generated C++ code started by $__file__:$__line__ 728// ${ident}: ${{self.short}} 729 730#include "mem/ruby/common/Global.hh" 731#include "mem/protocol/${ident}_Controller.hh" 732#include "mem/protocol/${ident}_State.hh" 733#include "mem/protocol/${ident}_Event.hh" 734#include "mem/protocol/Types.hh" 735#include "mem/ruby/system/System.hh" 736 737#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 738 739#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 740#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 741 742TransitionResult ${ident}_Controller::doTransition(${ident}_Event event, ${ident}_State state, const Address& addr 743) 744{ 745 ${ident}_State next_state = state; 746 747 DEBUG_NEWLINE(GENERATED_COMP, MedPrio); 748 DEBUG_MSG(GENERATED_COMP, MedPrio, *this); 749 DEBUG_EXPR(GENERATED_COMP, MedPrio, g_eventQueue_ptr->getTime()); 750 DEBUG_EXPR(GENERATED_COMP, MedPrio,state); 751 DEBUG_EXPR(GENERATED_COMP, MedPrio,event); 752 DEBUG_EXPR(GENERATED_COMP, MedPrio,addr); 753 754 TransitionResult result = doTransitionWorker(event, state, next_state, addr); 755 756 if (result == TransitionResult_Valid) { 757 DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state); 758 DEBUG_NEWLINE(GENERATED_COMP, MedPrio); 759 s_profiler.countTransition(state, event); 760 if (Debug::getProtocolTrace()) { 761 g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, 762 ${ident}_State_to_string(state), 763 ${ident}_Event_to_string(event), 764 ${ident}_State_to_string(next_state), GET_TRANSITION_COMMENT()); 765 } 766 CLEAR_TRANSITION_COMMENT(); 767 ${ident}_setState(addr, next_state); 768 769 } else if (result == TransitionResult_ResourceStall) { 770 if (Debug::getProtocolTrace()) { 771 g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, 772 ${ident}_State_to_string(state), 773 ${ident}_Event_to_string(event), 774 ${ident}_State_to_string(next_state), 775 "Resource Stall"); 776 } 777 } else if (result == TransitionResult_ProtocolStall) { 778 DEBUG_MSG(GENERATED_COMP, HighPrio, "stalling"); 779 DEBUG_NEWLINE(GENERATED_COMP, MedPrio); 780 if (Debug::getProtocolTrace()) { 781 g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, 782 ${ident}_State_to_string(state), 783 ${ident}_Event_to_string(event), 784 ${ident}_State_to_string(next_state), 785 "Protocol Stall"); 786 } 787 } 788 789 return result; 790} 791 792TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr 793) 794{ 795 switch(HASH_FUN(state, event)) { 796''') 797 798 # This map will allow suppress generating duplicate code 799 cases = orderdict() 800 801 for trans in self.transitions: 802 case_string = "%s_State_%s, %s_Event_%s" % \ 803 (self.ident, trans.state.ident, self.ident, trans.event.ident) 804 805 case = code_formatter() 806 # Only set next_state if it changes 807 if trans.state != trans.nextState: 808 ns_ident = trans.nextState.ident 809 case('next_state = ${ident}_State_${ns_ident};') 810 811 actions = trans.actions 812 813 # Check for resources 814 case_sorter = [] 815 res = trans.resources 816 for key,val in res.iteritems(): 817 if key.type.ident != "DNUCAStopTable": 818 val = ''' 819if (!%s.areNSlotsAvailable(%s)) { 820 return TransitionResult_ResourceStall; 821} 822''' % (key.code, val) 823 case_sorter.append(val) 824 825 826 # Emit the code sequences in a sorted order. This makes the 827 # output deterministic (without this the output order can vary 828 # since Map's keys() on a vector of pointers is not deterministic 829 for c in sorted(case_sorter): 830 case("$c") 831 832 # Figure out if we stall 833 stall = False 834 for action in actions: 835 if action.ident == "z_stall": 836 stall = True 837 break 838 839 if stall: 840 case('return TransitionResult_ProtocolStall;') 841 else: 842 for action in actions: 843 case('${{action.ident}}(addr);') 844 case('return TransitionResult_Valid;') 845 846 case = str(case) 847 848 # Look to see if this transition code is unique. 849 if case not in cases: 850 cases[case] = [] 851 852 cases[case].append(case_string) 853 854 # Walk through all of the unique code blocks and spit out the 855 # corresponding case statement elements 856 for case,transitions in cases.iteritems(): 857 # Iterative over all the multiple transitions that share 858 # the same code 859 for trans in transitions: 860 code(' case HASH_FUN($trans):') 861 code(' {') 862 code(' $case') 863 code(' }') 864 865 code(''' 866 default: 867 WARN_EXPR(m_version); 868 WARN_EXPR(g_eventQueue_ptr->getTime()); 869 WARN_EXPR(addr); 870 WARN_EXPR(event); 871 WARN_EXPR(state); 872 ERROR_MSG(\"Invalid transition\"); 873 } 874 return TransitionResult_Valid; 875} 876''') 877 code.write(path, "%s_Transitions.cc" % self.ident) 878 879 def printProfilerHH(self, path): 880 code = code_formatter() 881 ident = self.ident 882 883 code(''' 884// Auto generated C++ code started by $__file__:$__line__ 885// ${ident}: ${{self.short}} 886 887#ifndef ${ident}_PROFILER_H 888#define ${ident}_PROFILER_H 889 890#include "mem/ruby/common/Global.hh" 891#include "mem/protocol/${ident}_State.hh" 892#include "mem/protocol/${ident}_Event.hh" 893 894class ${ident}_Profiler { 895 public: 896 ${ident}_Profiler(); 897 void setVersion(int version); 898 void countTransition(${ident}_State state, ${ident}_Event event); 899 void possibleTransition(${ident}_State state, ${ident}_Event event); 900 void dumpStats(ostream& out) const; 901 void clearStats(); 902 903 private: 904 int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 905 int m_event_counters[${ident}_Event_NUM]; 906 bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 907 int m_version; 908}; 909 910#endif // ${ident}_PROFILER_H 911''') 912 code.write(path, "%s_Profiler.hh" % self.ident) 913 914 def printProfilerCC(self, path): 915 code = code_formatter() 916 ident = self.ident 917 918 code(''' 919// Auto generated C++ code started by $__file__:$__line__ 920// ${ident}: ${{self.short}} 921 922#include "mem/protocol/${ident}_Profiler.hh" 923 924${ident}_Profiler::${ident}_Profiler() 925{ 926 for (int state = 0; state < ${ident}_State_NUM; state++) { 927 for (int event = 0; event < ${ident}_Event_NUM; event++) { 928 m_possible[state][event] = false; 929 m_counters[state][event] = 0; 930 } 931 } 932 for (int event = 0; event < ${ident}_Event_NUM; event++) { 933 m_event_counters[event] = 0; 934 } 935} 936void ${ident}_Profiler::setVersion(int version) 937{ 938 m_version = version; 939} 940void ${ident}_Profiler::clearStats() 941{ 942 for (int state = 0; state < ${ident}_State_NUM; state++) { 943 for (int event = 0; event < ${ident}_Event_NUM; event++) { 944 m_counters[state][event] = 0; 945 } 946 } 947 948 for (int event = 0; event < ${ident}_Event_NUM; event++) { 949 m_event_counters[event] = 0; 950 } 951} 952void ${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) 953{ 954 assert(m_possible[state][event]); 955 m_counters[state][event]++; 956 m_event_counters[event]++; 957} 958void ${ident}_Profiler::possibleTransition(${ident}_State state, ${ident}_Event event) 959{ 960 m_possible[state][event] = true; 961} 962void ${ident}_Profiler::dumpStats(ostream& out) const 963{ 964 out << " --- ${ident} " << m_version << " ---" << endl; 965 out << " - Event Counts -" << endl; 966 for (int event = 0; event < ${ident}_Event_NUM; event++) { 967 int count = m_event_counters[event]; 968 out << (${ident}_Event) event << " " << count << endl; 969 } 970 out << endl; 971 out << " - Transitions -" << endl; 972 for (int state = 0; state < ${ident}_State_NUM; state++) { 973 for (int event = 0; event < ${ident}_Event_NUM; event++) { 974 if (m_possible[state][event]) { 975 int count = m_counters[state][event]; 976 out << (${ident}_State) state << " " << (${ident}_Event) event << " " << count; 977 if (count == 0) { 978 out << " <-- "; 979 } 980 out << endl; 981 } 982 } 983 out << endl; 984 } 985} 986''') 987 code.write(path, "%s_Profiler.cc" % self.ident) 988 989 # ************************** 990 # ******* HTML Files ******* 991 # ************************** 992 def frameRef(self, click_href, click_target, over_href, over_target_num, 993 text): 994 code = code_formatter(fix_newlines=False) 995 code("""<A href=\"$click_href\" target=\"$click_target\" onMouseOver=\"if (parent.frames[$over_target_num].location != parent.location + '$over_href') { parent.frames[$over_target_num].location='$over_href' }\" >${{html.formatShorthand(text)}}</A>""") 996 return str(code) 997 998 def writeHTMLFiles(self, path): 999 # Create table with no row hilighted 1000 self.printHTMLTransitions(path, None) 1001 1002 # Generate transition tables 1003 for state in self.states.itervalues(): 1004 self.printHTMLTransitions(path, state) 1005 1006 # Generate action descriptions 1007 for action in self.actions.itervalues(): 1008 name = "%s_action_%s.html" % (self.ident, action.ident) 1009 code = html.createSymbol(action, "Action") 1010 code.write(path, name) 1011 1012 # Generate state descriptions 1013 for state in self.states.itervalues(): 1014 name = "%s_State_%s.html" % (self.ident, state.ident) 1015 code = html.createSymbol(state, "State") 1016 code.write(path, name) 1017 1018 # Generate event descriptions 1019 for event in self.events.itervalues(): 1020 name = "%s_Event_%s.html" % (self.ident, event.ident) 1021 code = html.createSymbol(event, "Event") 1022 code.write(path, name) 1023 1024 def printHTMLTransitions(self, path, active_state): 1025 code = code_formatter() 1026 1027 code(''' 1028<HTML><BODY link="blue" vlink="blue"> 1029 1030<H1 align="center">${{html.formatShorthand(self.short)}}: 1031''') 1032 code.indent() 1033 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1034 mid = machine.ident 1035 if i != 0: 1036 extra = " - " 1037 else: 1038 extra = "" 1039 if machine == self: 1040 code('$extra$mid') 1041 else: 1042 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1043 code.dedent() 1044 1045 code(""" 1046</H1> 1047 1048<TABLE border=1> 1049<TR> 1050 <TH> </TH> 1051""") 1052 1053 for event in self.events.itervalues(): 1054 href = "%s_Event_%s.html" % (self.ident, event.ident) 1055 ref = self.frameRef(href, "Status", href, "1", event.short) 1056 code('<TH bgcolor=white>$ref</TH>') 1057 1058 code('</TR>') 1059 # -- Body of table 1060 for state in self.states.itervalues(): 1061 # -- Each row 1062 if state == active_state: 1063 color = "yellow" 1064 else: 1065 color = "white" 1066 1067 click = "%s_table_%s.html" % (self.ident, state.ident) 1068 over = "%s_State_%s.html" % (self.ident, state.ident) 1069 text = html.formatShorthand(state.short) 1070 ref = self.frameRef(click, "Table", over, "1", state.short) 1071 code(''' 1072<TR> 1073 <TH bgcolor=$color>$ref</TH> 1074''') 1075 1076 # -- One column for each event 1077 for event in self.events.itervalues(): 1078 trans = self.table.get((state,event), None) 1079 if trans is None: 1080 # This is the no transition case 1081 if state == active_state: 1082 color = "#C0C000" 1083 else: 1084 color = "lightgrey" 1085 1086 code('<TD bgcolor=$color> </TD>') 1087 continue 1088 1089 next = trans.nextState 1090 stall_action = False 1091 1092 # -- Get the actions 1093 for action in trans.actions: 1094 if action.ident == "z_stall" or \ 1095 action.ident == "zz_recycleMandatoryQueue": 1096 stall_action = True 1097 1098 # -- Print out "actions/next-state" 1099 if stall_action: 1100 if state == active_state: 1101 color = "#C0C000" 1102 else: 1103 color = "lightgrey" 1104 1105 elif active_state and next.ident == active_state.ident: 1106 color = "aqua" 1107 elif state == active_state: 1108 color = "yellow" 1109 else: 1110 color = "white" 1111 1112 fix = code.nofix() 1113 code('<TD bgcolor=$color>') 1114 for action in trans.actions: 1115 href = "%s_action_%s.html" % (self.ident, action.ident) 1116 ref = self.frameRef(href, "Status", href, "1", 1117 action.short) 1118 code(' $ref\n') 1119 if next != state: 1120 if trans.actions: 1121 code('/') 1122 click = "%s_table_%s.html" % (self.ident, next.ident) 1123 over = "%s_State_%s.html" % (self.ident, next.ident) 1124 ref = self.frameRef(click, "Table", over, "1", next.short) 1125 code("$ref") 1126 code("</TD>\n") 1127 code.fix(fix) 1128 1129 # -- Each row 1130 if state == active_state: 1131 color = "yellow" 1132 else: 1133 color = "white" 1134 1135 click = "%s_table_%s.html" % (self.ident, state.ident) 1136 over = "%s_State_%s.html" % (self.ident, state.ident) 1137 ref = self.frameRef(click, "Table", over, "1", state.short) 1138 code(''' 1139 <TH bgcolor=$color>$ref</TH> 1140</TR> 1141''') 1142 code(''' 1143<TR> 1144 <TH> </TH> 1145''') 1146 1147 for event in self.events.itervalues(): 1148 href = "%s_Event_%s.html" % (self.ident, event.ident) 1149 ref = self.frameRef(href, "Status", href, "1", event.short) 1150 code('<TH bgcolor=white>$ref</TH>') 1151 code(''' 1152</TR> 1153</TABLE> 1154</BODY></HTML> 1155''') 1156 1157 1158 if active_state: 1159 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1160 else: 1161 name = "%s_table.html" % self.ident 1162 code.write(path, name) 1163 1164__all__ = [ "StateMachine" ]
|