1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 2# Copyright (c) 2009 The Hewlett-Packard Development Company 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28from m5.util import orderdict 29 30from slicc.symbols.Symbol import Symbol 31from slicc.symbols.Var import Var 32import slicc.generate.html as html 33import re 34 35python_class_map = { 36 "int": "Int", 37 "uint32_t" : "UInt32", 38 "std::string": "String", 39 "bool": "Bool", 40 "CacheMemory": "RubyCache", 41 "WireBuffer": "RubyWireBuffer", 42 "Sequencer": "RubySequencer", 43 "DirectoryMemory": "RubyDirectoryMemory", 44 "MemoryControl": "MemoryControl", 45 "DMASequencer": "DMASequencer", 46 "Prefetcher":"Prefetcher", 47 "Cycles":"Cycles", 48 } 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 55 # Data members in the State Machine that have been declared before 56 # the opening brace '{' of the machine. Note that these along with 57 # the members in self.objects form the entire set of data members. 58 self.config_parameters = config_parameters 59 60 self.prefetchers = [] 61 62 for param in config_parameters: 63 if param.pointer: 64 var = Var(symtab, param.ident, location, param.type_ast.type, 65 "(*m_%s_ptr)" % param.ident, {}, self) 66 else: 67 var = Var(symtab, param.ident, location, param.type_ast.type, 68 "m_%s" % param.ident, {}, self) 69 70 self.symtab.registerSym(param.ident, var) 71 72 if str(param.type_ast.type) == "Prefetcher": 73 self.prefetchers.append(var) 74 75 self.states = orderdict() 76 self.events = orderdict() 77 self.actions = orderdict() 78 self.request_types = orderdict() 79 self.transitions = [] 80 self.in_ports = [] 81 self.functions = [] 82 83 # Data members in the State Machine that have been declared inside 84 # the {} machine. Note that these along with the config params 85 # form the entire set of data members of the machine. 86 self.objects = [] 87 self.TBEType = None 88 self.EntryType = None 89 90 def __repr__(self): 91 return "[StateMachine: %s]" % self.ident 92 93 def addState(self, state): 94 assert self.table is None 95 self.states[state.ident] = state 96 97 def addEvent(self, event): 98 assert self.table is None 99 self.events[event.ident] = event 100 101 def addAction(self, action): 102 assert self.table is None 103 104 # Check for duplicate action 105 for other in self.actions.itervalues(): 106 if action.ident == other.ident: 107 action.warning("Duplicate action definition: %s" % action.ident) 108 action.error("Duplicate action definition: %s" % action.ident) 109 if action.short == other.short: 110 other.warning("Duplicate action shorthand: %s" % other.ident) 111 other.warning(" shorthand = %s" % other.short) 112 action.warning("Duplicate action shorthand: %s" % action.ident) 113 action.error(" shorthand = %s" % action.short) 114 115 self.actions[action.ident] = action 116 117 def addRequestType(self, request_type): 118 assert self.table is None 119 self.request_types[request_type.ident] = request_type 120 121 def addTransition(self, trans): 122 assert self.table is None 123 self.transitions.append(trans) 124 125 def addInPort(self, var): 126 self.in_ports.append(var) 127 128 def addFunc(self, func): 129 # register func in the symbol table 130 self.symtab.registerSym(str(func), func) 131 self.functions.append(func) 132 133 def addObject(self, obj): 134 self.symtab.registerSym(str(obj), obj) 135 self.objects.append(obj) 136 137 def addType(self, type): 138 type_ident = '%s' % type.c_ident 139 140 if type_ident == "%s_TBE" %self.ident: 141 if self.TBEType != None: 142 self.error("Multiple Transaction Buffer types in a " \ 143 "single machine."); 144 self.TBEType = type 145 146 elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 147 if self.EntryType != None: 148 self.error("Multiple AbstractCacheEntry types in a " \ 149 "single machine."); 150 self.EntryType = type 151 152 # Needs to be called before accessing the table 153 def buildTable(self): 154 assert self.table is None 155 156 table = {} 157 158 for trans in self.transitions: 159 # Track which actions we touch so we know if we use them 160 # all -- really this should be done for all symbols as 161 # part of the symbol table, then only trigger it for 162 # Actions, States, Events, etc. 163 164 for action in trans.actions: 165 action.used = True 166 167 index = (trans.state, trans.event) 168 if index in table: 169 table[index].warning("Duplicate transition: %s" % table[index]) 170 trans.error("Duplicate transition: %s" % trans) 171 table[index] = trans 172 173 # Look at all actions to make sure we used them all 174 for action in self.actions.itervalues(): 175 if not action.used: 176 error_msg = "Unused action: %s" % action.ident 177 if "desc" in action: 178 error_msg += ", " + action.desc 179 action.warning(error_msg) 180 self.table = table 181
| 1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 2# Copyright (c) 2009 The Hewlett-Packard Development Company 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28from m5.util import orderdict 29 30from slicc.symbols.Symbol import Symbol 31from slicc.symbols.Var import Var 32import slicc.generate.html as html 33import re 34 35python_class_map = { 36 "int": "Int", 37 "uint32_t" : "UInt32", 38 "std::string": "String", 39 "bool": "Bool", 40 "CacheMemory": "RubyCache", 41 "WireBuffer": "RubyWireBuffer", 42 "Sequencer": "RubySequencer", 43 "DirectoryMemory": "RubyDirectoryMemory", 44 "MemoryControl": "MemoryControl", 45 "DMASequencer": "DMASequencer", 46 "Prefetcher":"Prefetcher", 47 "Cycles":"Cycles", 48 } 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 55 # Data members in the State Machine that have been declared before 56 # the opening brace '{' of the machine. Note that these along with 57 # the members in self.objects form the entire set of data members. 58 self.config_parameters = config_parameters 59 60 self.prefetchers = [] 61 62 for param in config_parameters: 63 if param.pointer: 64 var = Var(symtab, param.ident, location, param.type_ast.type, 65 "(*m_%s_ptr)" % param.ident, {}, self) 66 else: 67 var = Var(symtab, param.ident, location, param.type_ast.type, 68 "m_%s" % param.ident, {}, self) 69 70 self.symtab.registerSym(param.ident, var) 71 72 if str(param.type_ast.type) == "Prefetcher": 73 self.prefetchers.append(var) 74 75 self.states = orderdict() 76 self.events = orderdict() 77 self.actions = orderdict() 78 self.request_types = orderdict() 79 self.transitions = [] 80 self.in_ports = [] 81 self.functions = [] 82 83 # Data members in the State Machine that have been declared inside 84 # the {} machine. Note that these along with the config params 85 # form the entire set of data members of the machine. 86 self.objects = [] 87 self.TBEType = None 88 self.EntryType = None 89 90 def __repr__(self): 91 return "[StateMachine: %s]" % self.ident 92 93 def addState(self, state): 94 assert self.table is None 95 self.states[state.ident] = state 96 97 def addEvent(self, event): 98 assert self.table is None 99 self.events[event.ident] = event 100 101 def addAction(self, action): 102 assert self.table is None 103 104 # Check for duplicate action 105 for other in self.actions.itervalues(): 106 if action.ident == other.ident: 107 action.warning("Duplicate action definition: %s" % action.ident) 108 action.error("Duplicate action definition: %s" % action.ident) 109 if action.short == other.short: 110 other.warning("Duplicate action shorthand: %s" % other.ident) 111 other.warning(" shorthand = %s" % other.short) 112 action.warning("Duplicate action shorthand: %s" % action.ident) 113 action.error(" shorthand = %s" % action.short) 114 115 self.actions[action.ident] = action 116 117 def addRequestType(self, request_type): 118 assert self.table is None 119 self.request_types[request_type.ident] = request_type 120 121 def addTransition(self, trans): 122 assert self.table is None 123 self.transitions.append(trans) 124 125 def addInPort(self, var): 126 self.in_ports.append(var) 127 128 def addFunc(self, func): 129 # register func in the symbol table 130 self.symtab.registerSym(str(func), func) 131 self.functions.append(func) 132 133 def addObject(self, obj): 134 self.symtab.registerSym(str(obj), obj) 135 self.objects.append(obj) 136 137 def addType(self, type): 138 type_ident = '%s' % type.c_ident 139 140 if type_ident == "%s_TBE" %self.ident: 141 if self.TBEType != None: 142 self.error("Multiple Transaction Buffer types in a " \ 143 "single machine."); 144 self.TBEType = type 145 146 elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 147 if self.EntryType != None: 148 self.error("Multiple AbstractCacheEntry types in a " \ 149 "single machine."); 150 self.EntryType = type 151 152 # Needs to be called before accessing the table 153 def buildTable(self): 154 assert self.table is None 155 156 table = {} 157 158 for trans in self.transitions: 159 # Track which actions we touch so we know if we use them 160 # all -- really this should be done for all symbols as 161 # part of the symbol table, then only trigger it for 162 # Actions, States, Events, etc. 163 164 for action in trans.actions: 165 action.used = True 166 167 index = (trans.state, trans.event) 168 if index in table: 169 table[index].warning("Duplicate transition: %s" % table[index]) 170 trans.error("Duplicate transition: %s" % trans) 171 table[index] = trans 172 173 # Look at all actions to make sure we used them all 174 for action in self.actions.itervalues(): 175 if not action.used: 176 error_msg = "Unused action: %s" % action.ident 177 if "desc" in action: 178 error_msg += ", " + action.desc 179 action.warning(error_msg) 180 self.table = table 181
|
| 182 # determine the port->msg buffer mappings 183 def getBufferMaps(self, ident): 184 msg_bufs = [] 185 port_to_buf_map = {} 186 in_msg_bufs = {} 187 for port in self.in_ports: 188 buf_name = "m_%s_ptr" % port.buffer_expr.name 189 msg_bufs.append(buf_name) 190 port_to_buf_map[port] = msg_bufs.index(buf_name) 191 if buf_name not in in_msg_bufs: 192 in_msg_bufs[buf_name] = [port] 193 else: 194 in_msg_bufs[buf_name].append(port) 195 return port_to_buf_map, in_msg_bufs, msg_bufs 196
|
182 def writeCodeFiles(self, path, includes): 183 self.printControllerPython(path) 184 self.printControllerHH(path) 185 self.printControllerCC(path, includes) 186 self.printCSwitch(path) 187 self.printCWakeup(path, includes) 188 189 def printControllerPython(self, path): 190 code = self.symtab.codeFormatter() 191 ident = self.ident 192 193 py_ident = "%s_Controller" % ident 194 c_ident = "%s_Controller" % self.ident 195 196 code(''' 197from m5.params import * 198from m5.SimObject import SimObject 199from Controller import RubyController 200 201class $py_ident(RubyController): 202 type = '$py_ident' 203 cxx_header = 'mem/protocol/${c_ident}.hh' 204''') 205 code.indent() 206 for param in self.config_parameters: 207 dflt_str = '' 208 209 if param.rvalue is not None: 210 dflt_str = str(param.rvalue.inline()) + ', ' 211 212 if param.type_ast.type.c_ident == "MessageBuffer": 213 if param["network"] == "To": 214 code('${{param.ident}} = MasterPort(${dflt_str}"")') 215 else: 216 code('${{param.ident}} = SlavePort(${dflt_str}"")') 217 218 elif python_class_map.has_key(param.type_ast.type.c_ident): 219 python_type = python_class_map[param.type_ast.type.c_ident] 220 code('${{param.ident}} = Param.${{python_type}}(${dflt_str}"")') 221 222 else: 223 self.error("Unknown c++ to python class conversion for c++ " \ 224 "type: '%s'. Please update the python_class_map " \ 225 "in StateMachine.py", param.type_ast.type.c_ident) 226 code.dedent() 227 code.write(path, '%s.py' % py_ident) 228 229 230 def printControllerHH(self, path): 231 '''Output the method declarations for the class declaration''' 232 code = self.symtab.codeFormatter() 233 ident = self.ident 234 c_ident = "%s_Controller" % self.ident 235 236 code(''' 237/** \\file $c_ident.hh 238 * 239 * Auto generated C++ code started by $__file__:$__line__ 240 * Created by slicc definition of Module "${{self.short}}" 241 */ 242 243#ifndef __${ident}_CONTROLLER_HH__ 244#define __${ident}_CONTROLLER_HH__ 245 246#include <iostream> 247#include <sstream> 248#include <string> 249 250#include "mem/protocol/TransitionResult.hh" 251#include "mem/protocol/Types.hh" 252#include "mem/ruby/common/Consumer.hh" 253#include "mem/ruby/slicc_interface/AbstractController.hh" 254#include "params/$c_ident.hh" 255''') 256 257 seen_types = set() 258 for var in self.objects: 259 if var.type.ident not in seen_types and not var.type.isPrimitive: 260 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 261 seen_types.add(var.type.ident) 262 263 # for adding information to the protocol debug trace 264 code(''' 265extern std::stringstream ${ident}_transitionComment; 266 267class $c_ident : public AbstractController 268{ 269 public: 270 typedef ${c_ident}Params Params; 271 $c_ident(const Params *p); 272 static int getNumControllers(); 273 void init(); 274 275 MessageBuffer* getMandatoryQueue() const; 276 void setNetQueue(const std::string& name, MessageBuffer *b); 277 278 void print(std::ostream& out) const; 279 void wakeup(); 280 void resetStats(); 281 void regStats(); 282 void collateStats(); 283 284 void recordCacheTrace(int cntrl, CacheRecorder* tr); 285 Sequencer* getSequencer() const; 286 287 int functionalWriteBuffers(PacketPtr&); 288 289 void countTransition(${ident}_State state, ${ident}_Event event); 290 void possibleTransition(${ident}_State state, ${ident}_Event event); 291 uint64 getEventCount(${ident}_Event event); 292 bool isPossible(${ident}_State state, ${ident}_Event event); 293 uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); 294 295private: 296''') 297 298 code.indent() 299 # added by SS 300 for param in self.config_parameters: 301 if param.pointer: 302 code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 303 else: 304 code('${{param.type_ast.type}} m_${{param.ident}};') 305 306 code(''' 307TransitionResult doTransition(${ident}_Event event, 308''') 309 310 if self.EntryType != None: 311 code(''' 312 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 313''') 314 if self.TBEType != None: 315 code(''' 316 ${{self.TBEType.c_ident}}* m_tbe_ptr, 317''') 318 319 code(''' 320 const Address addr); 321 322TransitionResult doTransitionWorker(${ident}_Event event, 323 ${ident}_State state, 324 ${ident}_State& next_state, 325''') 326 327 if self.TBEType != None: 328 code(''' 329 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 330''') 331 if self.EntryType != None: 332 code(''' 333 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 334''') 335 336 code(''' 337 const Address& addr); 338 339int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 340int m_event_counters[${ident}_Event_NUM]; 341bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 342 343static std::vector<Stats::Vector *> eventVec; 344static std::vector<std::vector<Stats::Vector *> > transVec; 345static int m_num_controllers; 346 347// Internal functions 348''') 349 350 for func in self.functions: 351 proto = func.prototype 352 if proto: 353 code('$proto') 354 355 if self.EntryType != None: 356 code(''' 357 358// Set and Reset for cache_entry variable 359void set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 360void unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 361''') 362 363 if self.TBEType != None: 364 code(''' 365 366// Set and Reset for tbe variable 367void set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 368void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 369''') 370 371 # Prototype the actions that the controller can take 372 code(''' 373 374// Actions 375''') 376 if self.TBEType != None and self.EntryType != None: 377 for action in self.actions.itervalues(): 378 code('/** \\brief ${{action.desc}} */') 379 code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 380 'm_tbe_ptr, ${{self.EntryType.c_ident}}*& ' 381 'm_cache_entry_ptr, const Address& addr);') 382 elif self.TBEType != None: 383 for action in self.actions.itervalues(): 384 code('/** \\brief ${{action.desc}} */') 385 code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 386 'm_tbe_ptr, const Address& addr);') 387 elif self.EntryType != None: 388 for action in self.actions.itervalues(): 389 code('/** \\brief ${{action.desc}} */') 390 code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& ' 391 'm_cache_entry_ptr, const Address& addr);') 392 else: 393 for action in self.actions.itervalues(): 394 code('/** \\brief ${{action.desc}} */') 395 code('void ${{action.ident}}(const Address& addr);') 396 397 # the controller internal variables 398 code(''' 399 400// Objects 401''') 402 for var in self.objects: 403 th = var.get("template", "") 404 code('${{var.type.c_ident}}$th* m_${{var.ident}}_ptr;') 405 406 code.dedent() 407 code('};') 408 code('#endif // __${ident}_CONTROLLER_H__') 409 code.write(path, '%s.hh' % c_ident) 410 411 def printControllerCC(self, path, includes): 412 '''Output the actions for performing the actions''' 413 414 code = self.symtab.codeFormatter() 415 ident = self.ident 416 c_ident = "%s_Controller" % self.ident 417 418 code(''' 419/** \\file $c_ident.cc 420 * 421 * Auto generated C++ code started by $__file__:$__line__ 422 * Created by slicc definition of Module "${{self.short}}" 423 */ 424 425#include <sys/types.h>
| 197 def writeCodeFiles(self, path, includes): 198 self.printControllerPython(path) 199 self.printControllerHH(path) 200 self.printControllerCC(path, includes) 201 self.printCSwitch(path) 202 self.printCWakeup(path, includes) 203 204 def printControllerPython(self, path): 205 code = self.symtab.codeFormatter() 206 ident = self.ident 207 208 py_ident = "%s_Controller" % ident 209 c_ident = "%s_Controller" % self.ident 210 211 code(''' 212from m5.params import * 213from m5.SimObject import SimObject 214from Controller import RubyController 215 216class $py_ident(RubyController): 217 type = '$py_ident' 218 cxx_header = 'mem/protocol/${c_ident}.hh' 219''') 220 code.indent() 221 for param in self.config_parameters: 222 dflt_str = '' 223 224 if param.rvalue is not None: 225 dflt_str = str(param.rvalue.inline()) + ', ' 226 227 if param.type_ast.type.c_ident == "MessageBuffer": 228 if param["network"] == "To": 229 code('${{param.ident}} = MasterPort(${dflt_str}"")') 230 else: 231 code('${{param.ident}} = SlavePort(${dflt_str}"")') 232 233 elif python_class_map.has_key(param.type_ast.type.c_ident): 234 python_type = python_class_map[param.type_ast.type.c_ident] 235 code('${{param.ident}} = Param.${{python_type}}(${dflt_str}"")') 236 237 else: 238 self.error("Unknown c++ to python class conversion for c++ " \ 239 "type: '%s'. Please update the python_class_map " \ 240 "in StateMachine.py", param.type_ast.type.c_ident) 241 code.dedent() 242 code.write(path, '%s.py' % py_ident) 243 244 245 def printControllerHH(self, path): 246 '''Output the method declarations for the class declaration''' 247 code = self.symtab.codeFormatter() 248 ident = self.ident 249 c_ident = "%s_Controller" % self.ident 250 251 code(''' 252/** \\file $c_ident.hh 253 * 254 * Auto generated C++ code started by $__file__:$__line__ 255 * Created by slicc definition of Module "${{self.short}}" 256 */ 257 258#ifndef __${ident}_CONTROLLER_HH__ 259#define __${ident}_CONTROLLER_HH__ 260 261#include <iostream> 262#include <sstream> 263#include <string> 264 265#include "mem/protocol/TransitionResult.hh" 266#include "mem/protocol/Types.hh" 267#include "mem/ruby/common/Consumer.hh" 268#include "mem/ruby/slicc_interface/AbstractController.hh" 269#include "params/$c_ident.hh" 270''') 271 272 seen_types = set() 273 for var in self.objects: 274 if var.type.ident not in seen_types and not var.type.isPrimitive: 275 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 276 seen_types.add(var.type.ident) 277 278 # for adding information to the protocol debug trace 279 code(''' 280extern std::stringstream ${ident}_transitionComment; 281 282class $c_ident : public AbstractController 283{ 284 public: 285 typedef ${c_ident}Params Params; 286 $c_ident(const Params *p); 287 static int getNumControllers(); 288 void init(); 289 290 MessageBuffer* getMandatoryQueue() const; 291 void setNetQueue(const std::string& name, MessageBuffer *b); 292 293 void print(std::ostream& out) const; 294 void wakeup(); 295 void resetStats(); 296 void regStats(); 297 void collateStats(); 298 299 void recordCacheTrace(int cntrl, CacheRecorder* tr); 300 Sequencer* getSequencer() const; 301 302 int functionalWriteBuffers(PacketPtr&); 303 304 void countTransition(${ident}_State state, ${ident}_Event event); 305 void possibleTransition(${ident}_State state, ${ident}_Event event); 306 uint64 getEventCount(${ident}_Event event); 307 bool isPossible(${ident}_State state, ${ident}_Event event); 308 uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); 309 310private: 311''') 312 313 code.indent() 314 # added by SS 315 for param in self.config_parameters: 316 if param.pointer: 317 code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 318 else: 319 code('${{param.type_ast.type}} m_${{param.ident}};') 320 321 code(''' 322TransitionResult doTransition(${ident}_Event event, 323''') 324 325 if self.EntryType != None: 326 code(''' 327 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 328''') 329 if self.TBEType != None: 330 code(''' 331 ${{self.TBEType.c_ident}}* m_tbe_ptr, 332''') 333 334 code(''' 335 const Address addr); 336 337TransitionResult doTransitionWorker(${ident}_Event event, 338 ${ident}_State state, 339 ${ident}_State& next_state, 340''') 341 342 if self.TBEType != None: 343 code(''' 344 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 345''') 346 if self.EntryType != None: 347 code(''' 348 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 349''') 350 351 code(''' 352 const Address& addr); 353 354int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 355int m_event_counters[${ident}_Event_NUM]; 356bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 357 358static std::vector<Stats::Vector *> eventVec; 359static std::vector<std::vector<Stats::Vector *> > transVec; 360static int m_num_controllers; 361 362// Internal functions 363''') 364 365 for func in self.functions: 366 proto = func.prototype 367 if proto: 368 code('$proto') 369 370 if self.EntryType != None: 371 code(''' 372 373// Set and Reset for cache_entry variable 374void set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 375void unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 376''') 377 378 if self.TBEType != None: 379 code(''' 380 381// Set and Reset for tbe variable 382void set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 383void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 384''') 385 386 # Prototype the actions that the controller can take 387 code(''' 388 389// Actions 390''') 391 if self.TBEType != None and self.EntryType != None: 392 for action in self.actions.itervalues(): 393 code('/** \\brief ${{action.desc}} */') 394 code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 395 'm_tbe_ptr, ${{self.EntryType.c_ident}}*& ' 396 'm_cache_entry_ptr, const Address& addr);') 397 elif self.TBEType != None: 398 for action in self.actions.itervalues(): 399 code('/** \\brief ${{action.desc}} */') 400 code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 401 'm_tbe_ptr, const Address& addr);') 402 elif self.EntryType != None: 403 for action in self.actions.itervalues(): 404 code('/** \\brief ${{action.desc}} */') 405 code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& ' 406 'm_cache_entry_ptr, const Address& addr);') 407 else: 408 for action in self.actions.itervalues(): 409 code('/** \\brief ${{action.desc}} */') 410 code('void ${{action.ident}}(const Address& addr);') 411 412 # the controller internal variables 413 code(''' 414 415// Objects 416''') 417 for var in self.objects: 418 th = var.get("template", "") 419 code('${{var.type.c_ident}}$th* m_${{var.ident}}_ptr;') 420 421 code.dedent() 422 code('};') 423 code('#endif // __${ident}_CONTROLLER_H__') 424 code.write(path, '%s.hh' % c_ident) 425 426 def printControllerCC(self, path, includes): 427 '''Output the actions for performing the actions''' 428 429 code = self.symtab.codeFormatter() 430 ident = self.ident 431 c_ident = "%s_Controller" % self.ident 432 433 code(''' 434/** \\file $c_ident.cc 435 * 436 * Auto generated C++ code started by $__file__:$__line__ 437 * Created by slicc definition of Module "${{self.short}}" 438 */ 439 440#include <sys/types.h>
|
| 441#include <typeinfo>
|
426#include <unistd.h> 427 428#include <cassert> 429#include <sstream> 430#include <string> 431 432#include "base/compiler.hh" 433#include "base/cprintf.hh" 434#include "debug/RubyGenerated.hh" 435#include "debug/RubySlicc.hh" 436#include "mem/protocol/${ident}_Controller.hh" 437#include "mem/protocol/${ident}_Event.hh" 438#include "mem/protocol/${ident}_State.hh" 439#include "mem/protocol/Types.hh" 440#include "mem/ruby/system/System.hh" 441''') 442 for include_path in includes: 443 code('#include "${{include_path}}"') 444 445 code(''' 446 447using namespace std; 448''') 449 450 # include object classes 451 seen_types = set() 452 for var in self.objects: 453 if var.type.ident not in seen_types and not var.type.isPrimitive: 454 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 455 seen_types.add(var.type.ident) 456 457 num_in_ports = len(self.in_ports) 458 459 code(''' 460$c_ident * 461${c_ident}Params::create() 462{ 463 return new $c_ident(this); 464} 465 466int $c_ident::m_num_controllers = 0; 467std::vector<Stats::Vector *> $c_ident::eventVec; 468std::vector<std::vector<Stats::Vector *> > $c_ident::transVec; 469 470// for adding information to the protocol debug trace 471stringstream ${ident}_transitionComment; 472 473#ifndef NDEBUG 474#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 475#else 476#define APPEND_TRANSITION_COMMENT(str) do {} while (0) 477#endif 478 479/** \\brief constructor */ 480$c_ident::$c_ident(const Params *p) 481 : AbstractController(p) 482{ 483 m_machineID.type = MachineType_${ident}; 484 m_machineID.num = m_version; 485 m_num_controllers++; 486 487 m_in_ports = $num_in_ports; 488''') 489 code.indent() 490 491 # 492 # After initializing the universal machine parameters, initialize the 493 # this machines config parameters. Also if these configuration params 494 # include a sequencer, connect the it to the controller. 495 # 496 for param in self.config_parameters: 497 498 # Do not initialize messgage buffers since they are initialized 499 # when the port based connections are made. 500 if param.type_ast.type.c_ident == "MessageBuffer": 501 continue 502 503 if param.pointer: 504 code('m_${{param.ident}}_ptr = p->${{param.ident}};') 505 else: 506 code('m_${{param.ident}} = p->${{param.ident}};') 507 508 if re.compile("sequencer").search(param.ident): 509 code('m_${{param.ident}}_ptr->setController(this);') 510 511 for var in self.objects: 512 if var.ident.find("mandatoryQueue") >= 0: 513 code(''' 514m_${{var.ident}}_ptr = new ${{var.type.c_ident}}(); 515m_${{var.ident}}_ptr->setReceiver(this); 516''') 517 518 code(''' 519 520for (int state = 0; state < ${ident}_State_NUM; state++) { 521 for (int event = 0; event < ${ident}_Event_NUM; event++) { 522 m_possible[state][event] = false; 523 m_counters[state][event] = 0; 524 } 525} 526for (int event = 0; event < ${ident}_Event_NUM; event++) { 527 m_event_counters[event] = 0; 528} 529''') 530 code.dedent() 531 code(''' 532} 533 534void 535$c_ident::setNetQueue(const std::string& name, MessageBuffer *b) 536{ 537 MachineType machine_type = string_to_MachineType("${{self.ident}}"); 538 int base M5_VAR_USED = MachineType_base_number(machine_type); 539 540''') 541 code.indent() 542 543 # set for maintaining the vnet, direction pairs already seen for this 544 # machine. This map helps in implementing the check for avoiding 545 # multiple message buffers being mapped to the same vnet. 546 vnet_dir_set = set() 547 548 for var in self.config_parameters: 549 if "network" in var: 550 vtype = var.type_ast.type 551 vid = "m_%s_ptr" % var.ident 552 553 code(''' 554if ("${{var.ident}}" == name) { 555 $vid = b; 556 assert($vid != NULL); 557''') 558 code.indent() 559 # Network port object 560 network = var["network"] 561 ordered = var["ordered"] 562 563 if "virtual_network" in var: 564 vnet = var["virtual_network"] 565 vnet_type = var["vnet_type"] 566 567 assert (vnet, network) not in vnet_dir_set 568 vnet_dir_set.add((vnet,network)) 569 570 code(''' 571m_net_ptr->set${network}NetQueue(m_version + base, $ordered, $vnet, 572 "$vnet_type", b); 573''') 574 # Set the end 575 if network == "To": 576 code('$vid->setSender(this);') 577 else: 578 code('$vid->setReceiver(this);') 579 580 # Set ordering 581 code('$vid->setOrdering(${{var["ordered"]}});') 582 583 # Set randomization 584 if "random" in var: 585 # A buffer 586 code('$vid->setRandomization(${{var["random"]}});') 587 588 # Set Priority 589 if "rank" in var: 590 code('$vid->setPriority(${{var["rank"]}})') 591 592 # Set buffer size 593 code('$vid->resize(m_buffer_size);') 594 595 if "recycle_latency" in var: 596 code('$vid->setRecycleLatency( ' \ 597 'Cycles(${{var["recycle_latency"]}}));') 598 else: 599 code('$vid->setRecycleLatency(m_recycle_latency);') 600 601 # set description (may be overriden later by port def) 602 code(''' 603$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.ident}}]"); 604''') 605 code.dedent() 606 code('}\n') 607 608 code.dedent() 609 code(''' 610} 611 612void 613$c_ident::init() 614{ 615 // initialize objects 616 617''') 618 619 code.indent() 620 621 for var in self.objects: 622 vtype = var.type 623 vid = "m_%s_ptr" % var.ident 624 if "network" not in var: 625 # Not a network port object 626 if "primitive" in vtype: 627 code('$vid = new ${{vtype.c_ident}};') 628 if "default" in var: 629 code('(*$vid) = ${{var["default"]}};') 630 else: 631 # Normal Object 632 if var.ident.find("mandatoryQueue") < 0: 633 th = var.get("template", "") 634 expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 635 args = "" 636 if "non_obj" not in vtype and not vtype.isEnumeration: 637 args = var.get("constructor", "") 638 code('$expr($args);') 639 640 code('assert($vid != NULL);') 641 642 if "default" in var: 643 code('*$vid = ${{var["default"]}}; // Object default') 644 elif "default" in vtype: 645 comment = "Type %s default" % vtype.ident 646 code('*$vid = ${{vtype["default"]}}; // $comment') 647 648 # Set ordering 649 if "ordered" in var: 650 # A buffer 651 code('$vid->setOrdering(${{var["ordered"]}});') 652 653 # Set randomization 654 if "random" in var: 655 # A buffer 656 code('$vid->setRandomization(${{var["random"]}});') 657 658 # Set Priority 659 if vtype.isBuffer and "rank" in var: 660 code('$vid->setPriority(${{var["rank"]}});') 661 662 # Set sender and receiver for trigger queue 663 if var.ident.find("triggerQueue") >= 0: 664 code('$vid->setSender(this);') 665 code('$vid->setReceiver(this);') 666 elif vtype.c_ident == "TimerTable": 667 code('$vid->setClockObj(this);') 668 elif var.ident.find("optionalQueue") >= 0: 669 code('$vid->setSender(this);') 670 code('$vid->setReceiver(this);') 671 672 if vtype.isBuffer: 673 if "recycle_latency" in var: 674 code('$vid->setRecycleLatency( ' \ 675 'Cycles(${{var["recycle_latency"]}}));') 676 else: 677 code('$vid->setRecycleLatency(m_recycle_latency);') 678 679 # Set the prefetchers 680 code() 681 for prefetcher in self.prefetchers: 682 code('${{prefetcher.code}}.setController(this);') 683 684 code() 685 for port in self.in_ports: 686 # Set the queue consumers 687 code('${{port.code}}.setConsumer(this);') 688 # Set the queue descriptions 689 code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");') 690 691 # Initialize the transition profiling 692 code() 693 for trans in self.transitions: 694 # Figure out if we stall 695 stall = False 696 for action in trans.actions: 697 if action.ident == "z_stall": 698 stall = True 699 700 # Only possible if it is not a 'z' case 701 if not stall: 702 state = "%s_State_%s" % (self.ident, trans.state.ident) 703 event = "%s_Event_%s" % (self.ident, trans.event.ident) 704 code('possibleTransition($state, $event);') 705 706 code.dedent() 707 code(''' 708 AbstractController::init(); 709 resetStats(); 710} 711''') 712 713 mq_ident = "NULL" 714 for port in self.in_ports: 715 if port.code.find("mandatoryQueue_ptr") >= 0: 716 mq_ident = "m_mandatoryQueue_ptr" 717 718 seq_ident = "NULL" 719 for param in self.config_parameters: 720 if param.ident == "sequencer": 721 assert(param.pointer) 722 seq_ident = "m_%s_ptr" % param.ident 723 724 code(''' 725 726void 727$c_ident::regStats() 728{ 729 AbstractController::regStats(); 730 731 if (m_version == 0) { 732 for (${ident}_Event event = ${ident}_Event_FIRST; 733 event < ${ident}_Event_NUM; ++event) { 734 Stats::Vector *t = new Stats::Vector(); 735 t->init(m_num_controllers); 736 t->name(params()->ruby_system->name() + ".${c_ident}." + 737 ${ident}_Event_to_string(event)); 738 t->flags(Stats::pdf | Stats::total | Stats::oneline | 739 Stats::nozero); 740 741 eventVec.push_back(t); 742 } 743 744 for (${ident}_State state = ${ident}_State_FIRST; 745 state < ${ident}_State_NUM; ++state) { 746 747 transVec.push_back(std::vector<Stats::Vector *>()); 748 749 for (${ident}_Event event = ${ident}_Event_FIRST; 750 event < ${ident}_Event_NUM; ++event) { 751 752 Stats::Vector *t = new Stats::Vector(); 753 t->init(m_num_controllers); 754 t->name(params()->ruby_system->name() + ".${c_ident}." + 755 ${ident}_State_to_string(state) + 756 "." + ${ident}_Event_to_string(event)); 757 758 t->flags(Stats::pdf | Stats::total | Stats::oneline | 759 Stats::nozero); 760 transVec[state].push_back(t); 761 } 762 } 763 } 764} 765 766void 767$c_ident::collateStats() 768{ 769 for (${ident}_Event event = ${ident}_Event_FIRST; 770 event < ${ident}_Event_NUM; ++event) { 771 for (unsigned int i = 0; i < m_num_controllers; ++i) { 772 RubySystem *rs = params()->ruby_system; 773 std::map<uint32_t, AbstractController *>::iterator it = 774 rs->m_abstract_controls[MachineType_${ident}].find(i); 775 assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); 776 (*eventVec[event])[i] = 777 (($c_ident *)(*it).second)->getEventCount(event); 778 } 779 } 780 781 for (${ident}_State state = ${ident}_State_FIRST; 782 state < ${ident}_State_NUM; ++state) { 783 784 for (${ident}_Event event = ${ident}_Event_FIRST; 785 event < ${ident}_Event_NUM; ++event) { 786 787 for (unsigned int i = 0; i < m_num_controllers; ++i) { 788 RubySystem *rs = params()->ruby_system; 789 std::map<uint32_t, AbstractController *>::iterator it = 790 rs->m_abstract_controls[MachineType_${ident}].find(i); 791 assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); 792 (*transVec[state][event])[i] = 793 (($c_ident *)(*it).second)->getTransitionCount(state, event); 794 } 795 } 796 } 797} 798 799void 800$c_ident::countTransition(${ident}_State state, ${ident}_Event event) 801{ 802 assert(m_possible[state][event]); 803 m_counters[state][event]++; 804 m_event_counters[event]++; 805} 806void 807$c_ident::possibleTransition(${ident}_State state, 808 ${ident}_Event event) 809{ 810 m_possible[state][event] = true; 811} 812 813uint64 814$c_ident::getEventCount(${ident}_Event event) 815{ 816 return m_event_counters[event]; 817} 818 819bool 820$c_ident::isPossible(${ident}_State state, ${ident}_Event event) 821{ 822 return m_possible[state][event]; 823} 824 825uint64 826$c_ident::getTransitionCount(${ident}_State state, 827 ${ident}_Event event) 828{ 829 return m_counters[state][event]; 830} 831 832int 833$c_ident::getNumControllers() 834{ 835 return m_num_controllers; 836} 837 838MessageBuffer* 839$c_ident::getMandatoryQueue() const 840{ 841 return $mq_ident; 842} 843 844Sequencer* 845$c_ident::getSequencer() const 846{ 847 return $seq_ident; 848} 849 850void 851$c_ident::print(ostream& out) const 852{ 853 out << "[$c_ident " << m_version << "]"; 854} 855 856void $c_ident::resetStats() 857{ 858 for (int state = 0; state < ${ident}_State_NUM; state++) { 859 for (int event = 0; event < ${ident}_Event_NUM; event++) { 860 m_counters[state][event] = 0; 861 } 862 } 863 864 for (int event = 0; event < ${ident}_Event_NUM; event++) { 865 m_event_counters[event] = 0; 866 } 867 868 AbstractController::resetStats(); 869} 870''') 871 872 if self.EntryType != None: 873 code(''' 874 875// Set and Reset for cache_entry variable 876void 877$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 878{ 879 m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 880} 881 882void 883$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 884{ 885 m_cache_entry_ptr = 0; 886} 887''') 888 889 if self.TBEType != None: 890 code(''' 891 892// Set and Reset for tbe variable 893void 894$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 895{ 896 m_tbe_ptr = m_new_tbe; 897} 898 899void 900$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 901{ 902 m_tbe_ptr = NULL; 903} 904''') 905 906 code(''' 907 908void 909$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr) 910{ 911''') 912 # 913 # Record cache contents for all associated caches. 914 # 915 code.indent() 916 for param in self.config_parameters: 917 if param.type_ast.type.ident == "CacheMemory": 918 assert(param.pointer) 919 code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);') 920 921 code.dedent() 922 code(''' 923} 924 925// Actions 926''') 927 if self.TBEType != None and self.EntryType != None: 928 for action in self.actions.itervalues(): 929 if "c_code" not in action: 930 continue 931 932 code(''' 933/** \\brief ${{action.desc}} */ 934void 935$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 936{ 937 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
| 442#include <unistd.h> 443 444#include <cassert> 445#include <sstream> 446#include <string> 447 448#include "base/compiler.hh" 449#include "base/cprintf.hh" 450#include "debug/RubyGenerated.hh" 451#include "debug/RubySlicc.hh" 452#include "mem/protocol/${ident}_Controller.hh" 453#include "mem/protocol/${ident}_Event.hh" 454#include "mem/protocol/${ident}_State.hh" 455#include "mem/protocol/Types.hh" 456#include "mem/ruby/system/System.hh" 457''') 458 for include_path in includes: 459 code('#include "${{include_path}}"') 460 461 code(''' 462 463using namespace std; 464''') 465 466 # include object classes 467 seen_types = set() 468 for var in self.objects: 469 if var.type.ident not in seen_types and not var.type.isPrimitive: 470 code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 471 seen_types.add(var.type.ident) 472 473 num_in_ports = len(self.in_ports) 474 475 code(''' 476$c_ident * 477${c_ident}Params::create() 478{ 479 return new $c_ident(this); 480} 481 482int $c_ident::m_num_controllers = 0; 483std::vector<Stats::Vector *> $c_ident::eventVec; 484std::vector<std::vector<Stats::Vector *> > $c_ident::transVec; 485 486// for adding information to the protocol debug trace 487stringstream ${ident}_transitionComment; 488 489#ifndef NDEBUG 490#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 491#else 492#define APPEND_TRANSITION_COMMENT(str) do {} while (0) 493#endif 494 495/** \\brief constructor */ 496$c_ident::$c_ident(const Params *p) 497 : AbstractController(p) 498{ 499 m_machineID.type = MachineType_${ident}; 500 m_machineID.num = m_version; 501 m_num_controllers++; 502 503 m_in_ports = $num_in_ports; 504''') 505 code.indent() 506 507 # 508 # After initializing the universal machine parameters, initialize the 509 # this machines config parameters. Also if these configuration params 510 # include a sequencer, connect the it to the controller. 511 # 512 for param in self.config_parameters: 513 514 # Do not initialize messgage buffers since they are initialized 515 # when the port based connections are made. 516 if param.type_ast.type.c_ident == "MessageBuffer": 517 continue 518 519 if param.pointer: 520 code('m_${{param.ident}}_ptr = p->${{param.ident}};') 521 else: 522 code('m_${{param.ident}} = p->${{param.ident}};') 523 524 if re.compile("sequencer").search(param.ident): 525 code('m_${{param.ident}}_ptr->setController(this);') 526 527 for var in self.objects: 528 if var.ident.find("mandatoryQueue") >= 0: 529 code(''' 530m_${{var.ident}}_ptr = new ${{var.type.c_ident}}(); 531m_${{var.ident}}_ptr->setReceiver(this); 532''') 533 534 code(''' 535 536for (int state = 0; state < ${ident}_State_NUM; state++) { 537 for (int event = 0; event < ${ident}_Event_NUM; event++) { 538 m_possible[state][event] = false; 539 m_counters[state][event] = 0; 540 } 541} 542for (int event = 0; event < ${ident}_Event_NUM; event++) { 543 m_event_counters[event] = 0; 544} 545''') 546 code.dedent() 547 code(''' 548} 549 550void 551$c_ident::setNetQueue(const std::string& name, MessageBuffer *b) 552{ 553 MachineType machine_type = string_to_MachineType("${{self.ident}}"); 554 int base M5_VAR_USED = MachineType_base_number(machine_type); 555 556''') 557 code.indent() 558 559 # set for maintaining the vnet, direction pairs already seen for this 560 # machine. This map helps in implementing the check for avoiding 561 # multiple message buffers being mapped to the same vnet. 562 vnet_dir_set = set() 563 564 for var in self.config_parameters: 565 if "network" in var: 566 vtype = var.type_ast.type 567 vid = "m_%s_ptr" % var.ident 568 569 code(''' 570if ("${{var.ident}}" == name) { 571 $vid = b; 572 assert($vid != NULL); 573''') 574 code.indent() 575 # Network port object 576 network = var["network"] 577 ordered = var["ordered"] 578 579 if "virtual_network" in var: 580 vnet = var["virtual_network"] 581 vnet_type = var["vnet_type"] 582 583 assert (vnet, network) not in vnet_dir_set 584 vnet_dir_set.add((vnet,network)) 585 586 code(''' 587m_net_ptr->set${network}NetQueue(m_version + base, $ordered, $vnet, 588 "$vnet_type", b); 589''') 590 # Set the end 591 if network == "To": 592 code('$vid->setSender(this);') 593 else: 594 code('$vid->setReceiver(this);') 595 596 # Set ordering 597 code('$vid->setOrdering(${{var["ordered"]}});') 598 599 # Set randomization 600 if "random" in var: 601 # A buffer 602 code('$vid->setRandomization(${{var["random"]}});') 603 604 # Set Priority 605 if "rank" in var: 606 code('$vid->setPriority(${{var["rank"]}})') 607 608 # Set buffer size 609 code('$vid->resize(m_buffer_size);') 610 611 if "recycle_latency" in var: 612 code('$vid->setRecycleLatency( ' \ 613 'Cycles(${{var["recycle_latency"]}}));') 614 else: 615 code('$vid->setRecycleLatency(m_recycle_latency);') 616 617 # set description (may be overriden later by port def) 618 code(''' 619$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.ident}}]"); 620''') 621 code.dedent() 622 code('}\n') 623 624 code.dedent() 625 code(''' 626} 627 628void 629$c_ident::init() 630{ 631 // initialize objects 632 633''') 634 635 code.indent() 636 637 for var in self.objects: 638 vtype = var.type 639 vid = "m_%s_ptr" % var.ident 640 if "network" not in var: 641 # Not a network port object 642 if "primitive" in vtype: 643 code('$vid = new ${{vtype.c_ident}};') 644 if "default" in var: 645 code('(*$vid) = ${{var["default"]}};') 646 else: 647 # Normal Object 648 if var.ident.find("mandatoryQueue") < 0: 649 th = var.get("template", "") 650 expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 651 args = "" 652 if "non_obj" not in vtype and not vtype.isEnumeration: 653 args = var.get("constructor", "") 654 code('$expr($args);') 655 656 code('assert($vid != NULL);') 657 658 if "default" in var: 659 code('*$vid = ${{var["default"]}}; // Object default') 660 elif "default" in vtype: 661 comment = "Type %s default" % vtype.ident 662 code('*$vid = ${{vtype["default"]}}; // $comment') 663 664 # Set ordering 665 if "ordered" in var: 666 # A buffer 667 code('$vid->setOrdering(${{var["ordered"]}});') 668 669 # Set randomization 670 if "random" in var: 671 # A buffer 672 code('$vid->setRandomization(${{var["random"]}});') 673 674 # Set Priority 675 if vtype.isBuffer and "rank" in var: 676 code('$vid->setPriority(${{var["rank"]}});') 677 678 # Set sender and receiver for trigger queue 679 if var.ident.find("triggerQueue") >= 0: 680 code('$vid->setSender(this);') 681 code('$vid->setReceiver(this);') 682 elif vtype.c_ident == "TimerTable": 683 code('$vid->setClockObj(this);') 684 elif var.ident.find("optionalQueue") >= 0: 685 code('$vid->setSender(this);') 686 code('$vid->setReceiver(this);') 687 688 if vtype.isBuffer: 689 if "recycle_latency" in var: 690 code('$vid->setRecycleLatency( ' \ 691 'Cycles(${{var["recycle_latency"]}}));') 692 else: 693 code('$vid->setRecycleLatency(m_recycle_latency);') 694 695 # Set the prefetchers 696 code() 697 for prefetcher in self.prefetchers: 698 code('${{prefetcher.code}}.setController(this);') 699 700 code() 701 for port in self.in_ports: 702 # Set the queue consumers 703 code('${{port.code}}.setConsumer(this);') 704 # Set the queue descriptions 705 code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");') 706 707 # Initialize the transition profiling 708 code() 709 for trans in self.transitions: 710 # Figure out if we stall 711 stall = False 712 for action in trans.actions: 713 if action.ident == "z_stall": 714 stall = True 715 716 # Only possible if it is not a 'z' case 717 if not stall: 718 state = "%s_State_%s" % (self.ident, trans.state.ident) 719 event = "%s_Event_%s" % (self.ident, trans.event.ident) 720 code('possibleTransition($state, $event);') 721 722 code.dedent() 723 code(''' 724 AbstractController::init(); 725 resetStats(); 726} 727''') 728 729 mq_ident = "NULL" 730 for port in self.in_ports: 731 if port.code.find("mandatoryQueue_ptr") >= 0: 732 mq_ident = "m_mandatoryQueue_ptr" 733 734 seq_ident = "NULL" 735 for param in self.config_parameters: 736 if param.ident == "sequencer": 737 assert(param.pointer) 738 seq_ident = "m_%s_ptr" % param.ident 739 740 code(''' 741 742void 743$c_ident::regStats() 744{ 745 AbstractController::regStats(); 746 747 if (m_version == 0) { 748 for (${ident}_Event event = ${ident}_Event_FIRST; 749 event < ${ident}_Event_NUM; ++event) { 750 Stats::Vector *t = new Stats::Vector(); 751 t->init(m_num_controllers); 752 t->name(params()->ruby_system->name() + ".${c_ident}." + 753 ${ident}_Event_to_string(event)); 754 t->flags(Stats::pdf | Stats::total | Stats::oneline | 755 Stats::nozero); 756 757 eventVec.push_back(t); 758 } 759 760 for (${ident}_State state = ${ident}_State_FIRST; 761 state < ${ident}_State_NUM; ++state) { 762 763 transVec.push_back(std::vector<Stats::Vector *>()); 764 765 for (${ident}_Event event = ${ident}_Event_FIRST; 766 event < ${ident}_Event_NUM; ++event) { 767 768 Stats::Vector *t = new Stats::Vector(); 769 t->init(m_num_controllers); 770 t->name(params()->ruby_system->name() + ".${c_ident}." + 771 ${ident}_State_to_string(state) + 772 "." + ${ident}_Event_to_string(event)); 773 774 t->flags(Stats::pdf | Stats::total | Stats::oneline | 775 Stats::nozero); 776 transVec[state].push_back(t); 777 } 778 } 779 } 780} 781 782void 783$c_ident::collateStats() 784{ 785 for (${ident}_Event event = ${ident}_Event_FIRST; 786 event < ${ident}_Event_NUM; ++event) { 787 for (unsigned int i = 0; i < m_num_controllers; ++i) { 788 RubySystem *rs = params()->ruby_system; 789 std::map<uint32_t, AbstractController *>::iterator it = 790 rs->m_abstract_controls[MachineType_${ident}].find(i); 791 assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); 792 (*eventVec[event])[i] = 793 (($c_ident *)(*it).second)->getEventCount(event); 794 } 795 } 796 797 for (${ident}_State state = ${ident}_State_FIRST; 798 state < ${ident}_State_NUM; ++state) { 799 800 for (${ident}_Event event = ${ident}_Event_FIRST; 801 event < ${ident}_Event_NUM; ++event) { 802 803 for (unsigned int i = 0; i < m_num_controllers; ++i) { 804 RubySystem *rs = params()->ruby_system; 805 std::map<uint32_t, AbstractController *>::iterator it = 806 rs->m_abstract_controls[MachineType_${ident}].find(i); 807 assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); 808 (*transVec[state][event])[i] = 809 (($c_ident *)(*it).second)->getTransitionCount(state, event); 810 } 811 } 812 } 813} 814 815void 816$c_ident::countTransition(${ident}_State state, ${ident}_Event event) 817{ 818 assert(m_possible[state][event]); 819 m_counters[state][event]++; 820 m_event_counters[event]++; 821} 822void 823$c_ident::possibleTransition(${ident}_State state, 824 ${ident}_Event event) 825{ 826 m_possible[state][event] = true; 827} 828 829uint64 830$c_ident::getEventCount(${ident}_Event event) 831{ 832 return m_event_counters[event]; 833} 834 835bool 836$c_ident::isPossible(${ident}_State state, ${ident}_Event event) 837{ 838 return m_possible[state][event]; 839} 840 841uint64 842$c_ident::getTransitionCount(${ident}_State state, 843 ${ident}_Event event) 844{ 845 return m_counters[state][event]; 846} 847 848int 849$c_ident::getNumControllers() 850{ 851 return m_num_controllers; 852} 853 854MessageBuffer* 855$c_ident::getMandatoryQueue() const 856{ 857 return $mq_ident; 858} 859 860Sequencer* 861$c_ident::getSequencer() const 862{ 863 return $seq_ident; 864} 865 866void 867$c_ident::print(ostream& out) const 868{ 869 out << "[$c_ident " << m_version << "]"; 870} 871 872void $c_ident::resetStats() 873{ 874 for (int state = 0; state < ${ident}_State_NUM; state++) { 875 for (int event = 0; event < ${ident}_Event_NUM; event++) { 876 m_counters[state][event] = 0; 877 } 878 } 879 880 for (int event = 0; event < ${ident}_Event_NUM; event++) { 881 m_event_counters[event] = 0; 882 } 883 884 AbstractController::resetStats(); 885} 886''') 887 888 if self.EntryType != None: 889 code(''' 890 891// Set and Reset for cache_entry variable 892void 893$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 894{ 895 m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 896} 897 898void 899$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 900{ 901 m_cache_entry_ptr = 0; 902} 903''') 904 905 if self.TBEType != None: 906 code(''' 907 908// Set and Reset for tbe variable 909void 910$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 911{ 912 m_tbe_ptr = m_new_tbe; 913} 914 915void 916$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 917{ 918 m_tbe_ptr = NULL; 919} 920''') 921 922 code(''' 923 924void 925$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr) 926{ 927''') 928 # 929 # Record cache contents for all associated caches. 930 # 931 code.indent() 932 for param in self.config_parameters: 933 if param.type_ast.type.ident == "CacheMemory": 934 assert(param.pointer) 935 code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);') 936 937 code.dedent() 938 code(''' 939} 940 941// Actions 942''') 943 if self.TBEType != None and self.EntryType != None: 944 for action in self.actions.itervalues(): 945 if "c_code" not in action: 946 continue 947 948 code(''' 949/** \\brief ${{action.desc}} */ 950void 951$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 952{ 953 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
|
938 ${{action["c_code"]}}
| 954 try { 955 ${{action["c_code"]}} 956 } catch (const RejectException & e) { 957 fatal("Error in action ${{ident}}:${{action.ident}}: " 958 "executed a peek statement with the wrong message " 959 "type specified. "); 960 }
|
939} 940 941''') 942 elif self.TBEType != None: 943 for action in self.actions.itervalues(): 944 if "c_code" not in action: 945 continue 946 947 code(''' 948/** \\brief ${{action.desc}} */ 949void 950$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr) 951{ 952 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 953 ${{action["c_code"]}} 954} 955 956''') 957 elif self.EntryType != None: 958 for action in self.actions.itervalues(): 959 if "c_code" not in action: 960 continue 961 962 code(''' 963/** \\brief ${{action.desc}} */ 964void 965$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 966{ 967 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 968 ${{action["c_code"]}} 969} 970 971''') 972 else: 973 for action in self.actions.itervalues(): 974 if "c_code" not in action: 975 continue 976 977 code(''' 978/** \\brief ${{action.desc}} */ 979void 980$c_ident::${{action.ident}}(const Address& addr) 981{ 982 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 983 ${{action["c_code"]}} 984} 985 986''') 987 for func in self.functions: 988 code(func.generateCode()) 989 990 # Function for functional writes to messages buffered in the controller 991 code(''' 992int 993$c_ident::functionalWriteBuffers(PacketPtr& pkt) 994{ 995 int num_functional_writes = 0; 996''') 997 for var in self.objects: 998 vtype = var.type 999 if vtype.isBuffer: 1000 vid = "m_%s_ptr" % var.ident 1001 code('num_functional_writes += $vid->functionalWrite(pkt);') 1002 1003 for var in self.config_parameters: 1004 vtype = var.type_ast.type 1005 if vtype.isBuffer: 1006 vid = "m_%s_ptr" % var.ident 1007 code('num_functional_writes += $vid->functionalWrite(pkt);') 1008 1009 code(''' 1010 return num_functional_writes; 1011} 1012''') 1013 1014 code.write(path, "%s.cc" % c_ident) 1015 1016 def printCWakeup(self, path, includes): 1017 '''Output the wakeup loop for the events''' 1018 1019 code = self.symtab.codeFormatter() 1020 ident = self.ident 1021 1022 outputRequest_types = True 1023 if len(self.request_types) == 0: 1024 outputRequest_types = False 1025 1026 code(''' 1027// Auto generated C++ code started by $__file__:$__line__ 1028// ${ident}: ${{self.short}} 1029 1030#include <sys/types.h>
| 961} 962 963''') 964 elif self.TBEType != None: 965 for action in self.actions.itervalues(): 966 if "c_code" not in action: 967 continue 968 969 code(''' 970/** \\brief ${{action.desc}} */ 971void 972$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr) 973{ 974 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 975 ${{action["c_code"]}} 976} 977 978''') 979 elif self.EntryType != None: 980 for action in self.actions.itervalues(): 981 if "c_code" not in action: 982 continue 983 984 code(''' 985/** \\brief ${{action.desc}} */ 986void 987$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 988{ 989 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 990 ${{action["c_code"]}} 991} 992 993''') 994 else: 995 for action in self.actions.itervalues(): 996 if "c_code" not in action: 997 continue 998 999 code(''' 1000/** \\brief ${{action.desc}} */ 1001void 1002$c_ident::${{action.ident}}(const Address& addr) 1003{ 1004 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 1005 ${{action["c_code"]}} 1006} 1007 1008''') 1009 for func in self.functions: 1010 code(func.generateCode()) 1011 1012 # Function for functional writes to messages buffered in the controller 1013 code(''' 1014int 1015$c_ident::functionalWriteBuffers(PacketPtr& pkt) 1016{ 1017 int num_functional_writes = 0; 1018''') 1019 for var in self.objects: 1020 vtype = var.type 1021 if vtype.isBuffer: 1022 vid = "m_%s_ptr" % var.ident 1023 code('num_functional_writes += $vid->functionalWrite(pkt);') 1024 1025 for var in self.config_parameters: 1026 vtype = var.type_ast.type 1027 if vtype.isBuffer: 1028 vid = "m_%s_ptr" % var.ident 1029 code('num_functional_writes += $vid->functionalWrite(pkt);') 1030 1031 code(''' 1032 return num_functional_writes; 1033} 1034''') 1035 1036 code.write(path, "%s.cc" % c_ident) 1037 1038 def printCWakeup(self, path, includes): 1039 '''Output the wakeup loop for the events''' 1040 1041 code = self.symtab.codeFormatter() 1042 ident = self.ident 1043 1044 outputRequest_types = True 1045 if len(self.request_types) == 0: 1046 outputRequest_types = False 1047 1048 code(''' 1049// Auto generated C++ code started by $__file__:$__line__ 1050// ${ident}: ${{self.short}} 1051 1052#include <sys/types.h>
|
| 1053#include <typeinfo>
|
1031#include <unistd.h> 1032 1033#include <cassert> 1034 1035#include "base/misc.hh" 1036#include "debug/RubySlicc.hh" 1037#include "mem/protocol/${ident}_Controller.hh" 1038#include "mem/protocol/${ident}_Event.hh" 1039#include "mem/protocol/${ident}_State.hh" 1040''') 1041 1042 if outputRequest_types: 1043 code('''#include "mem/protocol/${ident}_RequestType.hh"''') 1044 1045 code(''' 1046#include "mem/protocol/Types.hh" 1047#include "mem/ruby/system/System.hh" 1048''') 1049 1050 1051 for include_path in includes: 1052 code('#include "${{include_path}}"') 1053
| 1054#include <unistd.h> 1055 1056#include <cassert> 1057 1058#include "base/misc.hh" 1059#include "debug/RubySlicc.hh" 1060#include "mem/protocol/${ident}_Controller.hh" 1061#include "mem/protocol/${ident}_Event.hh" 1062#include "mem/protocol/${ident}_State.hh" 1063''') 1064 1065 if outputRequest_types: 1066 code('''#include "mem/protocol/${ident}_RequestType.hh"''') 1067 1068 code(''' 1069#include "mem/protocol/Types.hh" 1070#include "mem/ruby/system/System.hh" 1071''') 1072 1073 1074 for include_path in includes: 1075 code('#include "${{include_path}}"') 1076
|
| 1077 port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) 1078
|
1054 code(''' 1055 1056using namespace std; 1057 1058void 1059${ident}_Controller::wakeup() 1060{ 1061 int counter = 0; 1062 while (true) {
| 1079 code(''' 1080 1081using namespace std; 1082 1083void 1084${ident}_Controller::wakeup() 1085{ 1086 int counter = 0; 1087 while (true) {
|
| 1088 unsigned char rejected[${{len(msg_bufs)}}]; 1089 memset(rejected, 0, sizeof(unsigned char)*${{len(msg_bufs)}});
|
1063 // Some cases will put us into an infinite loop without this limit 1064 assert(counter <= m_transitions_per_cycle); 1065 if (counter == m_transitions_per_cycle) { 1066 // Count how often we are fully utilized 1067 m_fully_busy_cycles++; 1068 1069 // Wakeup in another cycle and try again 1070 scheduleEvent(Cycles(1)); 1071 break; 1072 } 1073''') 1074 1075 code.indent() 1076 code.indent() 1077 1078 # InPorts 1079 # 1080 for port in self.in_ports: 1081 code.indent() 1082 code('// ${ident}InPort $port') 1083 if port.pairs.has_key("rank"): 1084 code('m_cur_in_port = ${{port.pairs["rank"]}};') 1085 else: 1086 code('m_cur_in_port = 0;')
| 1090 // Some cases will put us into an infinite loop without this limit 1091 assert(counter <= m_transitions_per_cycle); 1092 if (counter == m_transitions_per_cycle) { 1093 // Count how often we are fully utilized 1094 m_fully_busy_cycles++; 1095 1096 // Wakeup in another cycle and try again 1097 scheduleEvent(Cycles(1)); 1098 break; 1099 } 1100''') 1101 1102 code.indent() 1103 code.indent() 1104 1105 # InPorts 1106 # 1107 for port in self.in_ports: 1108 code.indent() 1109 code('// ${ident}InPort $port') 1110 if port.pairs.has_key("rank"): 1111 code('m_cur_in_port = ${{port.pairs["rank"]}};') 1112 else: 1113 code('m_cur_in_port = 0;')
|
| 1114 if port in port_to_buf_map: 1115 code('try {') 1116 code.indent()
|
1087 code('${{port["c_code_in_port"]}}')
| 1117 code('${{port["c_code_in_port"]}}')
|
1088 code.dedent()
| |
1089
| 1118
|
| 1119 if port in port_to_buf_map: 1120 code.dedent() 1121 code(''' 1122 } catch (const RejectException & e) { 1123 rejected[${{port_to_buf_map[port]}}]++; 1124 } 1125''') 1126 code.dedent()
|
1090 code('') 1091 1092 code.dedent() 1093 code.dedent() 1094 code('''
| 1127 code('') 1128 1129 code.dedent() 1130 code.dedent() 1131 code('''
|
1095 break; // If we got this far, we have nothing left todo
| 1132 // If we got this far, we have nothing left todo or something went 1133 // wrong''') 1134 for buf_name, ports in in_msg_bufs.items(): 1135 if len(ports) > 1: 1136 # only produce checks when a buffer is shared by multiple ports 1137 code(''' 1138 if (${{buf_name}}->isReady() && rejected[${{port_to_buf_map[ports[0]]}}] == ${{len(ports)}}) 1139 { 1140 // no port claimed the message on the top of this buffer 1141 panic("Runtime Error at Ruby Time: %d. " 1142 "All ports rejected a message. " 1143 "You are probably sending a message type to this controller " 1144 "over a virtual network that do not define an in_port for " 1145 "the incoming message type.\\n", 1146 Cycles(1)); 1147 } 1148''') 1149 code(''' 1150 break;
|
1096 } 1097} 1098''') 1099 1100 code.write(path, "%s_Wakeup.cc" % self.ident) 1101 1102 def printCSwitch(self, path): 1103 '''Output switch statement for transition table''' 1104 1105 code = self.symtab.codeFormatter() 1106 ident = self.ident 1107 1108 code(''' 1109// Auto generated C++ code started by $__file__:$__line__ 1110// ${ident}: ${{self.short}} 1111 1112#include <cassert> 1113 1114#include "base/misc.hh" 1115#include "base/trace.hh" 1116#include "debug/ProtocolTrace.hh" 1117#include "debug/RubyGenerated.hh" 1118#include "mem/protocol/${ident}_Controller.hh" 1119#include "mem/protocol/${ident}_Event.hh" 1120#include "mem/protocol/${ident}_State.hh" 1121#include "mem/protocol/Types.hh" 1122#include "mem/ruby/system/System.hh" 1123 1124#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 1125 1126#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 1127#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 1128 1129TransitionResult 1130${ident}_Controller::doTransition(${ident}_Event event, 1131''') 1132 if self.EntryType != None: 1133 code(''' 1134 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 1135''') 1136 if self.TBEType != None: 1137 code(''' 1138 ${{self.TBEType.c_ident}}* m_tbe_ptr, 1139''') 1140 code(''' 1141 const Address addr) 1142{ 1143''') 1144 code.indent() 1145 1146 if self.TBEType != None and self.EntryType != None: 1147 code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 1148 elif self.TBEType != None: 1149 code('${ident}_State state = getState(m_tbe_ptr, addr);') 1150 elif self.EntryType != None: 1151 code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 1152 else: 1153 code('${ident}_State state = getState(addr);') 1154 1155 code(''' 1156${ident}_State next_state = state; 1157 1158DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 1159 *this, curCycle(), ${ident}_State_to_string(state), 1160 ${ident}_Event_to_string(event), addr); 1161 1162TransitionResult result = 1163''') 1164 if self.TBEType != None and self.EntryType != None: 1165 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 1166 elif self.TBEType != None: 1167 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 1168 elif self.EntryType != None: 1169 code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 1170 else: 1171 code('doTransitionWorker(event, state, next_state, addr);') 1172
| 1151 } 1152} 1153''') 1154 1155 code.write(path, "%s_Wakeup.cc" % self.ident) 1156 1157 def printCSwitch(self, path): 1158 '''Output switch statement for transition table''' 1159 1160 code = self.symtab.codeFormatter() 1161 ident = self.ident 1162 1163 code(''' 1164// Auto generated C++ code started by $__file__:$__line__ 1165// ${ident}: ${{self.short}} 1166 1167#include <cassert> 1168 1169#include "base/misc.hh" 1170#include "base/trace.hh" 1171#include "debug/ProtocolTrace.hh" 1172#include "debug/RubyGenerated.hh" 1173#include "mem/protocol/${ident}_Controller.hh" 1174#include "mem/protocol/${ident}_Event.hh" 1175#include "mem/protocol/${ident}_State.hh" 1176#include "mem/protocol/Types.hh" 1177#include "mem/ruby/system/System.hh" 1178 1179#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 1180 1181#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 1182#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 1183 1184TransitionResult 1185${ident}_Controller::doTransition(${ident}_Event event, 1186''') 1187 if self.EntryType != None: 1188 code(''' 1189 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 1190''') 1191 if self.TBEType != None: 1192 code(''' 1193 ${{self.TBEType.c_ident}}* m_tbe_ptr, 1194''') 1195 code(''' 1196 const Address addr) 1197{ 1198''') 1199 code.indent() 1200 1201 if self.TBEType != None and self.EntryType != None: 1202 code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 1203 elif self.TBEType != None: 1204 code('${ident}_State state = getState(m_tbe_ptr, addr);') 1205 elif self.EntryType != None: 1206 code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 1207 else: 1208 code('${ident}_State state = getState(addr);') 1209 1210 code(''' 1211${ident}_State next_state = state; 1212 1213DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 1214 *this, curCycle(), ${ident}_State_to_string(state), 1215 ${ident}_Event_to_string(event), addr); 1216 1217TransitionResult result = 1218''') 1219 if self.TBEType != None and self.EntryType != None: 1220 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 1221 elif self.TBEType != None: 1222 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 1223 elif self.EntryType != None: 1224 code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 1225 else: 1226 code('doTransitionWorker(event, state, next_state, addr);') 1227
|
| 1228 port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) 1229
|
1173 code(''' 1174 1175if (result == TransitionResult_Valid) { 1176 DPRINTF(RubyGenerated, "next_state: %s\\n", 1177 ${ident}_State_to_string(next_state)); 1178 countTransition(state, event); 1179 1180 DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 1181 curTick(), m_version, "${ident}", 1182 ${ident}_Event_to_string(event), 1183 ${ident}_State_to_string(state), 1184 ${ident}_State_to_string(next_state), 1185 addr, GET_TRANSITION_COMMENT()); 1186 1187 CLEAR_TRANSITION_COMMENT(); 1188''') 1189 if self.TBEType != None and self.EntryType != None: 1190 code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 1191 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1192 elif self.TBEType != None: 1193 code('setState(m_tbe_ptr, addr, next_state);') 1194 code('setAccessPermission(addr, next_state);') 1195 elif self.EntryType != None: 1196 code('setState(m_cache_entry_ptr, addr, next_state);') 1197 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1198 else: 1199 code('setState(addr, next_state);') 1200 code('setAccessPermission(addr, next_state);') 1201 1202 code(''' 1203} else if (result == TransitionResult_ResourceStall) { 1204 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1205 curTick(), m_version, "${ident}", 1206 ${ident}_Event_to_string(event), 1207 ${ident}_State_to_string(state), 1208 ${ident}_State_to_string(next_state), 1209 addr, "Resource Stall"); 1210} else if (result == TransitionResult_ProtocolStall) { 1211 DPRINTF(RubyGenerated, "stalling\\n"); 1212 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1213 curTick(), m_version, "${ident}", 1214 ${ident}_Event_to_string(event), 1215 ${ident}_State_to_string(state), 1216 ${ident}_State_to_string(next_state), 1217 addr, "Protocol Stall"); 1218} 1219 1220return result; 1221''') 1222 code.dedent() 1223 code(''' 1224} 1225 1226TransitionResult 1227${ident}_Controller::doTransitionWorker(${ident}_Event event, 1228 ${ident}_State state, 1229 ${ident}_State& next_state, 1230''') 1231 1232 if self.TBEType != None: 1233 code(''' 1234 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 1235''') 1236 if self.EntryType != None: 1237 code(''' 1238 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 1239''') 1240 code(''' 1241 const Address& addr) 1242{ 1243 switch(HASH_FUN(state, event)) { 1244''') 1245 1246 # This map will allow suppress generating duplicate code 1247 cases = orderdict() 1248 1249 for trans in self.transitions: 1250 case_string = "%s_State_%s, %s_Event_%s" % \ 1251 (self.ident, trans.state.ident, self.ident, trans.event.ident) 1252 1253 case = self.symtab.codeFormatter() 1254 # Only set next_state if it changes 1255 if trans.state != trans.nextState: 1256 ns_ident = trans.nextState.ident 1257 case('next_state = ${ident}_State_${ns_ident};') 1258 1259 actions = trans.actions 1260 request_types = trans.request_types 1261 1262 # Check for resources 1263 case_sorter = [] 1264 res = trans.resources 1265 for key,val in res.iteritems(): 1266 val = ''' 1267if (!%s.areNSlotsAvailable(%s)) 1268 return TransitionResult_ResourceStall; 1269''' % (key.code, val) 1270 case_sorter.append(val) 1271 1272 # Check all of the request_types for resource constraints 1273 for request_type in request_types: 1274 val = ''' 1275if (!checkResourceAvailable(%s_RequestType_%s, addr)) { 1276 return TransitionResult_ResourceStall; 1277} 1278''' % (self.ident, request_type.ident) 1279 case_sorter.append(val) 1280 1281 # Emit the code sequences in a sorted order. This makes the 1282 # output deterministic (without this the output order can vary 1283 # since Map's keys() on a vector of pointers is not deterministic 1284 for c in sorted(case_sorter): 1285 case("$c") 1286 1287 # Record access types for this transition 1288 for request_type in request_types: 1289 case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);') 1290 1291 # Figure out if we stall 1292 stall = False 1293 for action in actions: 1294 if action.ident == "z_stall": 1295 stall = True 1296 break 1297 1298 if stall: 1299 case('return TransitionResult_ProtocolStall;') 1300 else: 1301 if self.TBEType != None and self.EntryType != None: 1302 for action in actions: 1303 case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 1304 elif self.TBEType != None: 1305 for action in actions: 1306 case('${{action.ident}}(m_tbe_ptr, addr);') 1307 elif self.EntryType != None: 1308 for action in actions: 1309 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1310 else: 1311 for action in actions: 1312 case('${{action.ident}}(addr);') 1313 case('return TransitionResult_Valid;') 1314 1315 case = str(case) 1316 1317 # Look to see if this transition code is unique. 1318 if case not in cases: 1319 cases[case] = [] 1320 1321 cases[case].append(case_string) 1322 1323 # Walk through all of the unique code blocks and spit out the 1324 # corresponding case statement elements 1325 for case,transitions in cases.iteritems(): 1326 # Iterative over all the multiple transitions that share 1327 # the same code 1328 for trans in transitions: 1329 code(' case HASH_FUN($trans):') 1330 code(' $case\n') 1331 1332 code(''' 1333 default: 1334 panic("Invalid transition\\n" 1335 "%s time: %d addr: %s event: %s state: %s\\n", 1336 name(), curCycle(), addr, event, state); 1337 } 1338 1339 return TransitionResult_Valid; 1340} 1341''') 1342 code.write(path, "%s_Transitions.cc" % self.ident) 1343 1344 1345 # ************************** 1346 # ******* HTML Files ******* 1347 # ************************** 1348 def frameRef(self, click_href, click_target, over_href, over_num, text): 1349 code = self.symtab.codeFormatter(fix_newlines=False) 1350 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1351 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1352 parent.frames[$over_num].location='$over_href' 1353 }\"> 1354 ${{html.formatShorthand(text)}} 1355 </A>""") 1356 return str(code) 1357 1358 def writeHTMLFiles(self, path): 1359 # Create table with no row hilighted 1360 self.printHTMLTransitions(path, None) 1361 1362 # Generate transition tables 1363 for state in self.states.itervalues(): 1364 self.printHTMLTransitions(path, state) 1365 1366 # Generate action descriptions 1367 for action in self.actions.itervalues(): 1368 name = "%s_action_%s.html" % (self.ident, action.ident) 1369 code = html.createSymbol(action, "Action") 1370 code.write(path, name) 1371 1372 # Generate state descriptions 1373 for state in self.states.itervalues(): 1374 name = "%s_State_%s.html" % (self.ident, state.ident) 1375 code = html.createSymbol(state, "State") 1376 code.write(path, name) 1377 1378 # Generate event descriptions 1379 for event in self.events.itervalues(): 1380 name = "%s_Event_%s.html" % (self.ident, event.ident) 1381 code = html.createSymbol(event, "Event") 1382 code.write(path, name) 1383 1384 def printHTMLTransitions(self, path, active_state): 1385 code = self.symtab.codeFormatter() 1386 1387 code(''' 1388<HTML> 1389<BODY link="blue" vlink="blue"> 1390 1391<H1 align="center">${{html.formatShorthand(self.short)}}: 1392''') 1393 code.indent() 1394 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1395 mid = machine.ident 1396 if i != 0: 1397 extra = " - " 1398 else: 1399 extra = "" 1400 if machine == self: 1401 code('$extra$mid') 1402 else: 1403 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1404 code.dedent() 1405 1406 code(""" 1407</H1> 1408 1409<TABLE border=1> 1410<TR> 1411 <TH> </TH> 1412""") 1413 1414 for event in self.events.itervalues(): 1415 href = "%s_Event_%s.html" % (self.ident, event.ident) 1416 ref = self.frameRef(href, "Status", href, "1", event.short) 1417 code('<TH bgcolor=white>$ref</TH>') 1418 1419 code('</TR>') 1420 # -- Body of table 1421 for state in self.states.itervalues(): 1422 # -- Each row 1423 if state == active_state: 1424 color = "yellow" 1425 else: 1426 color = "white" 1427 1428 click = "%s_table_%s.html" % (self.ident, state.ident) 1429 over = "%s_State_%s.html" % (self.ident, state.ident) 1430 text = html.formatShorthand(state.short) 1431 ref = self.frameRef(click, "Table", over, "1", state.short) 1432 code(''' 1433<TR> 1434 <TH bgcolor=$color>$ref</TH> 1435''') 1436 1437 # -- One column for each event 1438 for event in self.events.itervalues(): 1439 trans = self.table.get((state,event), None) 1440 if trans is None: 1441 # This is the no transition case 1442 if state == active_state: 1443 color = "#C0C000" 1444 else: 1445 color = "lightgrey" 1446 1447 code('<TD bgcolor=$color> </TD>') 1448 continue 1449 1450 next = trans.nextState 1451 stall_action = False 1452 1453 # -- Get the actions 1454 for action in trans.actions: 1455 if action.ident == "z_stall" or \ 1456 action.ident == "zz_recycleMandatoryQueue": 1457 stall_action = True 1458 1459 # -- Print out "actions/next-state" 1460 if stall_action: 1461 if state == active_state: 1462 color = "#C0C000" 1463 else: 1464 color = "lightgrey" 1465 1466 elif active_state and next.ident == active_state.ident: 1467 color = "aqua" 1468 elif state == active_state: 1469 color = "yellow" 1470 else: 1471 color = "white" 1472 1473 code('<TD bgcolor=$color>') 1474 for action in trans.actions: 1475 href = "%s_action_%s.html" % (self.ident, action.ident) 1476 ref = self.frameRef(href, "Status", href, "1", 1477 action.short) 1478 code(' $ref') 1479 if next != state: 1480 if trans.actions: 1481 code('/') 1482 click = "%s_table_%s.html" % (self.ident, next.ident) 1483 over = "%s_State_%s.html" % (self.ident, next.ident) 1484 ref = self.frameRef(click, "Table", over, "1", next.short) 1485 code("$ref") 1486 code("</TD>") 1487 1488 # -- Each row 1489 if state == active_state: 1490 color = "yellow" 1491 else: 1492 color = "white" 1493 1494 click = "%s_table_%s.html" % (self.ident, state.ident) 1495 over = "%s_State_%s.html" % (self.ident, state.ident) 1496 ref = self.frameRef(click, "Table", over, "1", state.short) 1497 code(''' 1498 <TH bgcolor=$color>$ref</TH> 1499</TR> 1500''') 1501 code(''' 1502<!- Column footer-> 1503<TR> 1504 <TH> </TH> 1505''') 1506 1507 for event in self.events.itervalues(): 1508 href = "%s_Event_%s.html" % (self.ident, event.ident) 1509 ref = self.frameRef(href, "Status", href, "1", event.short) 1510 code('<TH bgcolor=white>$ref</TH>') 1511 code(''' 1512</TR> 1513</TABLE> 1514</BODY></HTML> 1515''') 1516 1517 1518 if active_state: 1519 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1520 else: 1521 name = "%s_table.html" % self.ident 1522 code.write(path, name) 1523 1524__all__ = [ "StateMachine" ]
| 1230 code(''' 1231 1232if (result == TransitionResult_Valid) { 1233 DPRINTF(RubyGenerated, "next_state: %s\\n", 1234 ${ident}_State_to_string(next_state)); 1235 countTransition(state, event); 1236 1237 DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 1238 curTick(), m_version, "${ident}", 1239 ${ident}_Event_to_string(event), 1240 ${ident}_State_to_string(state), 1241 ${ident}_State_to_string(next_state), 1242 addr, GET_TRANSITION_COMMENT()); 1243 1244 CLEAR_TRANSITION_COMMENT(); 1245''') 1246 if self.TBEType != None and self.EntryType != None: 1247 code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 1248 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1249 elif self.TBEType != None: 1250 code('setState(m_tbe_ptr, addr, next_state);') 1251 code('setAccessPermission(addr, next_state);') 1252 elif self.EntryType != None: 1253 code('setState(m_cache_entry_ptr, addr, next_state);') 1254 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1255 else: 1256 code('setState(addr, next_state);') 1257 code('setAccessPermission(addr, next_state);') 1258 1259 code(''' 1260} else if (result == TransitionResult_ResourceStall) { 1261 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1262 curTick(), m_version, "${ident}", 1263 ${ident}_Event_to_string(event), 1264 ${ident}_State_to_string(state), 1265 ${ident}_State_to_string(next_state), 1266 addr, "Resource Stall"); 1267} else if (result == TransitionResult_ProtocolStall) { 1268 DPRINTF(RubyGenerated, "stalling\\n"); 1269 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1270 curTick(), m_version, "${ident}", 1271 ${ident}_Event_to_string(event), 1272 ${ident}_State_to_string(state), 1273 ${ident}_State_to_string(next_state), 1274 addr, "Protocol Stall"); 1275} 1276 1277return result; 1278''') 1279 code.dedent() 1280 code(''' 1281} 1282 1283TransitionResult 1284${ident}_Controller::doTransitionWorker(${ident}_Event event, 1285 ${ident}_State state, 1286 ${ident}_State& next_state, 1287''') 1288 1289 if self.TBEType != None: 1290 code(''' 1291 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 1292''') 1293 if self.EntryType != None: 1294 code(''' 1295 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 1296''') 1297 code(''' 1298 const Address& addr) 1299{ 1300 switch(HASH_FUN(state, event)) { 1301''') 1302 1303 # This map will allow suppress generating duplicate code 1304 cases = orderdict() 1305 1306 for trans in self.transitions: 1307 case_string = "%s_State_%s, %s_Event_%s" % \ 1308 (self.ident, trans.state.ident, self.ident, trans.event.ident) 1309 1310 case = self.symtab.codeFormatter() 1311 # Only set next_state if it changes 1312 if trans.state != trans.nextState: 1313 ns_ident = trans.nextState.ident 1314 case('next_state = ${ident}_State_${ns_ident};') 1315 1316 actions = trans.actions 1317 request_types = trans.request_types 1318 1319 # Check for resources 1320 case_sorter = [] 1321 res = trans.resources 1322 for key,val in res.iteritems(): 1323 val = ''' 1324if (!%s.areNSlotsAvailable(%s)) 1325 return TransitionResult_ResourceStall; 1326''' % (key.code, val) 1327 case_sorter.append(val) 1328 1329 # Check all of the request_types for resource constraints 1330 for request_type in request_types: 1331 val = ''' 1332if (!checkResourceAvailable(%s_RequestType_%s, addr)) { 1333 return TransitionResult_ResourceStall; 1334} 1335''' % (self.ident, request_type.ident) 1336 case_sorter.append(val) 1337 1338 # Emit the code sequences in a sorted order. This makes the 1339 # output deterministic (without this the output order can vary 1340 # since Map's keys() on a vector of pointers is not deterministic 1341 for c in sorted(case_sorter): 1342 case("$c") 1343 1344 # Record access types for this transition 1345 for request_type in request_types: 1346 case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);') 1347 1348 # Figure out if we stall 1349 stall = False 1350 for action in actions: 1351 if action.ident == "z_stall": 1352 stall = True 1353 break 1354 1355 if stall: 1356 case('return TransitionResult_ProtocolStall;') 1357 else: 1358 if self.TBEType != None and self.EntryType != None: 1359 for action in actions: 1360 case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 1361 elif self.TBEType != None: 1362 for action in actions: 1363 case('${{action.ident}}(m_tbe_ptr, addr);') 1364 elif self.EntryType != None: 1365 for action in actions: 1366 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1367 else: 1368 for action in actions: 1369 case('${{action.ident}}(addr);') 1370 case('return TransitionResult_Valid;') 1371 1372 case = str(case) 1373 1374 # Look to see if this transition code is unique. 1375 if case not in cases: 1376 cases[case] = [] 1377 1378 cases[case].append(case_string) 1379 1380 # Walk through all of the unique code blocks and spit out the 1381 # corresponding case statement elements 1382 for case,transitions in cases.iteritems(): 1383 # Iterative over all the multiple transitions that share 1384 # the same code 1385 for trans in transitions: 1386 code(' case HASH_FUN($trans):') 1387 code(' $case\n') 1388 1389 code(''' 1390 default: 1391 panic("Invalid transition\\n" 1392 "%s time: %d addr: %s event: %s state: %s\\n", 1393 name(), curCycle(), addr, event, state); 1394 } 1395 1396 return TransitionResult_Valid; 1397} 1398''') 1399 code.write(path, "%s_Transitions.cc" % self.ident) 1400 1401 1402 # ************************** 1403 # ******* HTML Files ******* 1404 # ************************** 1405 def frameRef(self, click_href, click_target, over_href, over_num, text): 1406 code = self.symtab.codeFormatter(fix_newlines=False) 1407 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1408 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1409 parent.frames[$over_num].location='$over_href' 1410 }\"> 1411 ${{html.formatShorthand(text)}} 1412 </A>""") 1413 return str(code) 1414 1415 def writeHTMLFiles(self, path): 1416 # Create table with no row hilighted 1417 self.printHTMLTransitions(path, None) 1418 1419 # Generate transition tables 1420 for state in self.states.itervalues(): 1421 self.printHTMLTransitions(path, state) 1422 1423 # Generate action descriptions 1424 for action in self.actions.itervalues(): 1425 name = "%s_action_%s.html" % (self.ident, action.ident) 1426 code = html.createSymbol(action, "Action") 1427 code.write(path, name) 1428 1429 # Generate state descriptions 1430 for state in self.states.itervalues(): 1431 name = "%s_State_%s.html" % (self.ident, state.ident) 1432 code = html.createSymbol(state, "State") 1433 code.write(path, name) 1434 1435 # Generate event descriptions 1436 for event in self.events.itervalues(): 1437 name = "%s_Event_%s.html" % (self.ident, event.ident) 1438 code = html.createSymbol(event, "Event") 1439 code.write(path, name) 1440 1441 def printHTMLTransitions(self, path, active_state): 1442 code = self.symtab.codeFormatter() 1443 1444 code(''' 1445<HTML> 1446<BODY link="blue" vlink="blue"> 1447 1448<H1 align="center">${{html.formatShorthand(self.short)}}: 1449''') 1450 code.indent() 1451 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1452 mid = machine.ident 1453 if i != 0: 1454 extra = " - " 1455 else: 1456 extra = "" 1457 if machine == self: 1458 code('$extra$mid') 1459 else: 1460 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1461 code.dedent() 1462 1463 code(""" 1464</H1> 1465 1466<TABLE border=1> 1467<TR> 1468 <TH> </TH> 1469""") 1470 1471 for event in self.events.itervalues(): 1472 href = "%s_Event_%s.html" % (self.ident, event.ident) 1473 ref = self.frameRef(href, "Status", href, "1", event.short) 1474 code('<TH bgcolor=white>$ref</TH>') 1475 1476 code('</TR>') 1477 # -- Body of table 1478 for state in self.states.itervalues(): 1479 # -- Each row 1480 if state == active_state: 1481 color = "yellow" 1482 else: 1483 color = "white" 1484 1485 click = "%s_table_%s.html" % (self.ident, state.ident) 1486 over = "%s_State_%s.html" % (self.ident, state.ident) 1487 text = html.formatShorthand(state.short) 1488 ref = self.frameRef(click, "Table", over, "1", state.short) 1489 code(''' 1490<TR> 1491 <TH bgcolor=$color>$ref</TH> 1492''') 1493 1494 # -- One column for each event 1495 for event in self.events.itervalues(): 1496 trans = self.table.get((state,event), None) 1497 if trans is None: 1498 # This is the no transition case 1499 if state == active_state: 1500 color = "#C0C000" 1501 else: 1502 color = "lightgrey" 1503 1504 code('<TD bgcolor=$color> </TD>') 1505 continue 1506 1507 next = trans.nextState 1508 stall_action = False 1509 1510 # -- Get the actions 1511 for action in trans.actions: 1512 if action.ident == "z_stall" or \ 1513 action.ident == "zz_recycleMandatoryQueue": 1514 stall_action = True 1515 1516 # -- Print out "actions/next-state" 1517 if stall_action: 1518 if state == active_state: 1519 color = "#C0C000" 1520 else: 1521 color = "lightgrey" 1522 1523 elif active_state and next.ident == active_state.ident: 1524 color = "aqua" 1525 elif state == active_state: 1526 color = "yellow" 1527 else: 1528 color = "white" 1529 1530 code('<TD bgcolor=$color>') 1531 for action in trans.actions: 1532 href = "%s_action_%s.html" % (self.ident, action.ident) 1533 ref = self.frameRef(href, "Status", href, "1", 1534 action.short) 1535 code(' $ref') 1536 if next != state: 1537 if trans.actions: 1538 code('/') 1539 click = "%s_table_%s.html" % (self.ident, next.ident) 1540 over = "%s_State_%s.html" % (self.ident, next.ident) 1541 ref = self.frameRef(click, "Table", over, "1", next.short) 1542 code("$ref") 1543 code("</TD>") 1544 1545 # -- Each row 1546 if state == active_state: 1547 color = "yellow" 1548 else: 1549 color = "white" 1550 1551 click = "%s_table_%s.html" % (self.ident, state.ident) 1552 over = "%s_State_%s.html" % (self.ident, state.ident) 1553 ref = self.frameRef(click, "Table", over, "1", state.short) 1554 code(''' 1555 <TH bgcolor=$color>$ref</TH> 1556</TR> 1557''') 1558 code(''' 1559<!- Column footer-> 1560<TR> 1561 <TH> </TH> 1562''') 1563 1564 for event in self.events.itervalues(): 1565 href = "%s_Event_%s.html" % (self.ident, event.ident) 1566 ref = self.frameRef(href, "Status", href, "1", event.short) 1567 code('<TH bgcolor=white>$ref</TH>') 1568 code(''' 1569</TR> 1570</TABLE> 1571</BODY></HTML> 1572''') 1573 1574 1575 if active_state: 1576 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1577 else: 1578 name = "%s_table.html" % self.ident 1579 code.write(path, name) 1580 1581__all__ = [ "StateMachine" ]
|