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