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