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