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