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