StateMachine.py revision 8532:8f27cf8971fe
113511Sgabeblack@google.com# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 213511Sgabeblack@google.com# Copyright (c) 2009 The Hewlett-Packard Development Company 313511Sgabeblack@google.com# All rights reserved. 413511Sgabeblack@google.com# 513511Sgabeblack@google.com# Redistribution and use in source and binary forms, with or without 613511Sgabeblack@google.com# modification, are permitted provided that the following conditions are 713511Sgabeblack@google.com# met: redistributions of source code must retain the above copyright 813511Sgabeblack@google.com# notice, this list of conditions and the following disclaimer; 913511Sgabeblack@google.com# redistributions in binary form must reproduce the above copyright 1013511Sgabeblack@google.com# notice, this list of conditions and the following disclaimer in the 1113511Sgabeblack@google.com# documentation and/or other materials provided with the distribution; 1213511Sgabeblack@google.com# neither the name of the copyright holders nor the names of its 1313511Sgabeblack@google.com# contributors may be used to endorse or promote products derived from 1413511Sgabeblack@google.com# this software without specific prior written permission. 1513511Sgabeblack@google.com# 1613511Sgabeblack@google.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1713511Sgabeblack@google.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1813511Sgabeblack@google.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1913511Sgabeblack@google.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2013513Sgabeblack@google.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2113513Sgabeblack@google.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2213511Sgabeblack@google.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2313511Sgabeblack@google.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2413511Sgabeblack@google.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2513513Sgabeblack@google.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2613511Sgabeblack@google.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2713511Sgabeblack@google.com 2813511Sgabeblack@google.comfrom m5.util import orderdict 2913513Sgabeblack@google.com 3013513Sgabeblack@google.comfrom slicc.symbols.Symbol import Symbol 3113511Sgabeblack@google.comfrom slicc.symbols.Var import Var 3213513Sgabeblack@google.comimport slicc.generate.html as html 3313513Sgabeblack@google.comimport re 3413513Sgabeblack@google.com 3513513Sgabeblack@google.compython_class_map = {"int": "Int", 3613513Sgabeblack@google.com "std::string": "String", 3713511Sgabeblack@google.com "bool": "Bool", 3813513Sgabeblack@google.com "CacheMemory": "RubyCache", 3913513Sgabeblack@google.com "WireBuffer": "RubyWireBuffer", 4013513Sgabeblack@google.com "Sequencer": "RubySequencer", 4113513Sgabeblack@google.com "DirectoryMemory": "RubyDirectoryMemory", 4213513Sgabeblack@google.com "MemoryControl": "RubyMemoryControl", 4313513Sgabeblack@google.com "DMASequencer": "DMASequencer" 4413513Sgabeblack@google.com } 4513513Sgabeblack@google.com 4613513Sgabeblack@google.comclass StateMachine(Symbol): 4713511Sgabeblack@google.com def __init__(self, symtab, ident, location, pairs, config_parameters): 4813511Sgabeblack@google.com super(StateMachine, self).__init__(symtab, ident, location, pairs) 4913513Sgabeblack@google.com self.table = None 5013513Sgabeblack@google.com self.config_parameters = config_parameters 5113511Sgabeblack@google.com 5213513Sgabeblack@google.com for param in config_parameters: 5313511Sgabeblack@google.com if param.pointer: 5413511Sgabeblack@google.com var = Var(symtab, param.name, location, param.type_ast.type, 5513513Sgabeblack@google.com "(*m_%s_ptr)" % param.name, {}, self) 5613513Sgabeblack@google.com else: 5713511Sgabeblack@google.com var = Var(symtab, param.name, location, param.type_ast.type, 5813513Sgabeblack@google.com "m_%s" % param.name, {}, self) 5913511Sgabeblack@google.com self.symtab.registerSym(param.name, var) 6013511Sgabeblack@google.com 6113513Sgabeblack@google.com self.states = orderdict() 6213513Sgabeblack@google.com self.events = orderdict() 6313513Sgabeblack@google.com self.actions = orderdict() 6413513Sgabeblack@google.com self.transitions = [] 6513513Sgabeblack@google.com self.in_ports = [] 6613513Sgabeblack@google.com self.functions = [] 6713513Sgabeblack@google.com self.objects = [] 6813513Sgabeblack@google.com self.TBEType = None 6913513Sgabeblack@google.com self.EntryType = None 7013513Sgabeblack@google.com 7113511Sgabeblack@google.com self.message_buffer_names = [] 7213513Sgabeblack@google.com 7313513Sgabeblack@google.com def __repr__(self): 7413513Sgabeblack@google.com return "[StateMachine: %s]" % self.ident 7513513Sgabeblack@google.com 7613513Sgabeblack@google.com def addState(self, state): 7713513Sgabeblack@google.com assert self.table is None 7813513Sgabeblack@google.com self.states[state.ident] = state 7913513Sgabeblack@google.com 8013513Sgabeblack@google.com def addEvent(self, event): 8113513Sgabeblack@google.com assert self.table is None 8213513Sgabeblack@google.com self.events[event.ident] = event 8313513Sgabeblack@google.com 8413513Sgabeblack@google.com def addAction(self, action): 8513513Sgabeblack@google.com assert self.table is None 8613513Sgabeblack@google.com 8713513Sgabeblack@google.com # Check for duplicate action 8813513Sgabeblack@google.com for other in self.actions.itervalues(): 8913513Sgabeblack@google.com if action.ident == other.ident: 9013513Sgabeblack@google.com action.warning("Duplicate action definition: %s" % action.ident) 9113513Sgabeblack@google.com action.error("Duplicate action definition: %s" % action.ident) 9213513Sgabeblack@google.com if action.short == other.short: 9313513Sgabeblack@google.com other.warning("Duplicate action shorthand: %s" % other.ident) 9413513Sgabeblack@google.com other.warning(" shorthand = %s" % other.short) 9513513Sgabeblack@google.com action.warning("Duplicate action shorthand: %s" % action.ident) 9613513Sgabeblack@google.com action.error(" shorthand = %s" % action.short) 9713513Sgabeblack@google.com 9813513Sgabeblack@google.com self.actions[action.ident] = action 9913513Sgabeblack@google.com 10013513Sgabeblack@google.com def addTransition(self, trans): 10113513Sgabeblack@google.com assert self.table is None 10213513Sgabeblack@google.com self.transitions.append(trans) 10313513Sgabeblack@google.com 10413513Sgabeblack@google.com def addInPort(self, var): 10513513Sgabeblack@google.com self.in_ports.append(var) 10613511Sgabeblack@google.com 10713511Sgabeblack@google.com def addFunc(self, func): 10813511Sgabeblack@google.com # register func in the symbol table 10913513Sgabeblack@google.com self.symtab.registerSym(str(func), func) 11013513Sgabeblack@google.com self.functions.append(func) 11113513Sgabeblack@google.com 11213513Sgabeblack@google.com def addObject(self, obj): 11313511Sgabeblack@google.com self.objects.append(obj) 11413513Sgabeblack@google.com 11513511Sgabeblack@google.com def addType(self, type): 11613511Sgabeblack@google.com type_ident = '%s' % type.c_ident 11713513Sgabeblack@google.com 11813513Sgabeblack@google.com if type_ident == "%s_TBE" %self.ident: 11913511Sgabeblack@google.com if self.TBEType != None: 12013513Sgabeblack@google.com self.error("Multiple Transaction Buffer types in a " \ 12113511Sgabeblack@google.com "single machine."); 12213511Sgabeblack@google.com self.TBEType = type 12313513Sgabeblack@google.com 12413513Sgabeblack@google.com elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 12513513Sgabeblack@google.com if self.EntryType != None: 12613511Sgabeblack@google.com self.error("Multiple AbstractCacheEntry types in a " \ 12713513Sgabeblack@google.com "single machine."); 12813513Sgabeblack@google.com self.EntryType = type 12913513Sgabeblack@google.com 13013513Sgabeblack@google.com # Needs to be called before accessing the table 13113513Sgabeblack@google.com def buildTable(self): 13213513Sgabeblack@google.com assert self.table is None 13313513Sgabeblack@google.com 13413513Sgabeblack@google.com table = {} 13513513Sgabeblack@google.com 13613513Sgabeblack@google.com for trans in self.transitions: 13713513Sgabeblack@google.com # Track which actions we touch so we know if we use them 13813513Sgabeblack@google.com # all -- really this should be done for all symbols as 13913513Sgabeblack@google.com # part of the symbol table, then only trigger it for 14013513Sgabeblack@google.com # Actions, States, Events, etc. 14113513Sgabeblack@google.com 14213513Sgabeblack@google.com for action in trans.actions: 14313513Sgabeblack@google.com action.used = True 14413513Sgabeblack@google.com 14513513Sgabeblack@google.com index = (trans.state, trans.event) 14613513Sgabeblack@google.com if index in table: 14713513Sgabeblack@google.com table[index].warning("Duplicate transition: %s" % table[index]) 14813513Sgabeblack@google.com trans.error("Duplicate transition: %s" % trans) 14913513Sgabeblack@google.com table[index] = trans 15013513Sgabeblack@google.com 15113513Sgabeblack@google.com # Look at all actions to make sure we used them all 15213513Sgabeblack@google.com for action in self.actions.itervalues(): 15313513Sgabeblack@google.com if not action.used: 15413513Sgabeblack@google.com error_msg = "Unused action: %s" % action.ident 15513513Sgabeblack@google.com if "desc" in action: 15613513Sgabeblack@google.com error_msg += ", " + action.desc 15713513Sgabeblack@google.com action.warning(error_msg) 15813513Sgabeblack@google.com self.table = table 15913513Sgabeblack@google.com 16013513Sgabeblack@google.com def writeCodeFiles(self, path): 16113513Sgabeblack@google.com self.printControllerPython(path) 16213513Sgabeblack@google.com self.printControllerHH(path) 16313513Sgabeblack@google.com self.printControllerCC(path) 16413513Sgabeblack@google.com self.printCSwitch(path) 16513513Sgabeblack@google.com self.printCWakeup(path) 16613513Sgabeblack@google.com self.printProfilerCC(path) 16713513Sgabeblack@google.com self.printProfilerHH(path) 16813513Sgabeblack@google.com self.printProfileDumperCC(path) 16913513Sgabeblack@google.com self.printProfileDumperHH(path) 17013513Sgabeblack@google.com 17113513Sgabeblack@google.com def printControllerPython(self, path): 17213513Sgabeblack@google.com code = self.symtab.codeFormatter() 17313513Sgabeblack@google.com ident = self.ident 17413513Sgabeblack@google.com py_ident = "%s_Controller" % ident 17513513Sgabeblack@google.com c_ident = "%s_Controller" % self.ident 17613513Sgabeblack@google.com code(''' 17713513Sgabeblack@google.comfrom m5.params import * 17813513Sgabeblack@google.comfrom m5.SimObject import SimObject 17913513Sgabeblack@google.comfrom Controller import RubyController 18013513Sgabeblack@google.com 18113513Sgabeblack@google.comclass $py_ident(RubyController): 18213513Sgabeblack@google.com type = '$py_ident' 18313513Sgabeblack@google.com''') 18413513Sgabeblack@google.com code.indent() 18513513Sgabeblack@google.com for param in self.config_parameters: 18613513Sgabeblack@google.com dflt_str = '' 18713513Sgabeblack@google.com if param.default is not None: 18813513Sgabeblack@google.com dflt_str = str(param.default) + ', ' 18913513Sgabeblack@google.com if python_class_map.has_key(param.type_ast.type.c_ident): 19013513Sgabeblack@google.com python_type = python_class_map[param.type_ast.type.c_ident] 19113513Sgabeblack@google.com code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")') 19213513Sgabeblack@google.com else: 19313513Sgabeblack@google.com self.error("Unknown c++ to python class conversion for c++ " \ 19413513Sgabeblack@google.com "type: '%s'. Please update the python_class_map " \ 19513513Sgabeblack@google.com "in StateMachine.py", param.type_ast.type.c_ident) 19613513Sgabeblack@google.com code.dedent() 19713513Sgabeblack@google.com code.write(path, '%s.py' % py_ident) 19813513Sgabeblack@google.com 19913513Sgabeblack@google.com 20013513Sgabeblack@google.com def printControllerHH(self, path): 20113513Sgabeblack@google.com '''Output the method declarations for the class declaration''' 20213513Sgabeblack@google.com code = self.symtab.codeFormatter() 20313513Sgabeblack@google.com ident = self.ident 20413513Sgabeblack@google.com c_ident = "%s_Controller" % self.ident 20513513Sgabeblack@google.com 20613513Sgabeblack@google.com self.message_buffer_names = [] 20713513Sgabeblack@google.com 20813513Sgabeblack@google.com code(''' 20913513Sgabeblack@google.com/** \\file $c_ident.hh 21013513Sgabeblack@google.com * 21113513Sgabeblack@google.com * Auto generated C++ code started by $__file__:$__line__ 21213513Sgabeblack@google.com * Created by slicc definition of Module "${{self.short}}" 21313513Sgabeblack@google.com */ 21413513Sgabeblack@google.com 21513513Sgabeblack@google.com#ifndef __${ident}_CONTROLLER_HH__ 21613513Sgabeblack@google.com#define __${ident}_CONTROLLER_HH__ 21713513Sgabeblack@google.com 21813513Sgabeblack@google.com#include <iostream> 21913513Sgabeblack@google.com#include <sstream> 22013513Sgabeblack@google.com#include <string> 22113513Sgabeblack@google.com 22213513Sgabeblack@google.com#include "mem/protocol/${ident}_ProfileDumper.hh" 22313513Sgabeblack@google.com#include "mem/protocol/${ident}_Profiler.hh" 22413513Sgabeblack@google.com#include "mem/protocol/TransitionResult.hh" 22513513Sgabeblack@google.com#include "mem/protocol/Types.hh" 22613513Sgabeblack@google.com#include "mem/ruby/common/Consumer.hh" 22713513Sgabeblack@google.com#include "mem/ruby/common/Global.hh" 22813513Sgabeblack@google.com#include "mem/ruby/slicc_interface/AbstractController.hh" 22913513Sgabeblack@google.com#include "params/$c_ident.hh" 23013513Sgabeblack@google.com''') 23113513Sgabeblack@google.com 23213513Sgabeblack@google.com seen_types = set() 23313513Sgabeblack@google.com for var in self.objects: 23413513Sgabeblack@google.com if var.type.ident not in seen_types and not var.type.isPrimitive: 23513513Sgabeblack@google.com code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 23613513Sgabeblack@google.com seen_types.add(var.type.ident) 23713513Sgabeblack@google.com 23813513Sgabeblack@google.com # for adding information to the protocol debug trace 23913513Sgabeblack@google.com code(''' 24013513Sgabeblack@google.comextern std::stringstream ${ident}_transitionComment; 24113513Sgabeblack@google.com 24213513Sgabeblack@google.comclass $c_ident : public AbstractController 24313513Sgabeblack@google.com{ 24413513Sgabeblack@google.com// the coherence checker needs to call isBlockExclusive() and isBlockShared() 24513513Sgabeblack@google.com// making the Chip a friend class is an easy way to do this for now 24613513Sgabeblack@google.com 24713513Sgabeblack@google.compublic: 24813513Sgabeblack@google.com typedef ${c_ident}Params Params; 24913513Sgabeblack@google.com $c_ident(const Params *p); 25013513Sgabeblack@google.com static int getNumControllers(); 25113513Sgabeblack@google.com void init(); 25213513Sgabeblack@google.com MessageBuffer* getMandatoryQueue() const; 25313513Sgabeblack@google.com const int & getVersion() const; 25413513Sgabeblack@google.com const std::string toString() const; 25513513Sgabeblack@google.com const std::string getName() const; 25613513Sgabeblack@google.com const MachineType getMachineType() const; 25713513Sgabeblack@google.com void stallBuffer(MessageBuffer* buf, Address addr); 25813513Sgabeblack@google.com void wakeUpBuffers(Address addr); 25913513Sgabeblack@google.com void wakeUpAllBuffers(); 26013513Sgabeblack@google.com void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; } 26113513Sgabeblack@google.com void print(std::ostream& out) const; 26213513Sgabeblack@google.com void printConfig(std::ostream& out) const; 26313513Sgabeblack@google.com void wakeup(); 26413513Sgabeblack@google.com void printStats(std::ostream& out) const; 26513513Sgabeblack@google.com void clearStats(); 26613513Sgabeblack@google.com void blockOnQueue(Address addr, MessageBuffer* port); 26713513Sgabeblack@google.com void unblock(Address addr); 26813513Sgabeblack@google.com 26913513Sgabeblack@google.comprivate: 27013513Sgabeblack@google.com''') 27113513Sgabeblack@google.com 27213513Sgabeblack@google.com code.indent() 27313513Sgabeblack@google.com # added by SS 27413513Sgabeblack@google.com for param in self.config_parameters: 27513513Sgabeblack@google.com if param.pointer: 27613513Sgabeblack@google.com code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 27713513Sgabeblack@google.com else: 27813513Sgabeblack@google.com code('${{param.type_ast.type}} m_${{param.ident}};') 27913513Sgabeblack@google.com 28013513Sgabeblack@google.com code(''' 28113513Sgabeblack@google.comint m_number_of_TBEs; 28213513Sgabeblack@google.com 28313513Sgabeblack@google.comTransitionResult doTransition(${ident}_Event event, 28413513Sgabeblack@google.com''') 28513513Sgabeblack@google.com 28613513Sgabeblack@google.com if self.EntryType != None: 28713513Sgabeblack@google.com code(''' 28813513Sgabeblack@google.com ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 28913513Sgabeblack@google.com''') 29013513Sgabeblack@google.com if self.TBEType != None: 29113513Sgabeblack@google.com code(''' 29213513Sgabeblack@google.com ${{self.TBEType.c_ident}}* m_tbe_ptr, 29313513Sgabeblack@google.com''') 29413513Sgabeblack@google.com 29513513Sgabeblack@google.com code(''' 29613513Sgabeblack@google.com const Address& addr); 29713513Sgabeblack@google.com 29813513Sgabeblack@google.comTransitionResult doTransitionWorker(${ident}_Event event, 29913513Sgabeblack@google.com ${ident}_State state, 30013513Sgabeblack@google.com ${ident}_State& next_state, 30113513Sgabeblack@google.com''') 30213513Sgabeblack@google.com 30313513Sgabeblack@google.com if self.TBEType != None: 30413513Sgabeblack@google.com code(''' 30513513Sgabeblack@google.com ${{self.TBEType.c_ident}}*& m_tbe_ptr, 30613513Sgabeblack@google.com''') 30713513Sgabeblack@google.com if self.EntryType != None: 30813513Sgabeblack@google.com code(''' 30913513Sgabeblack@google.com ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 31013513Sgabeblack@google.com''') 31113513Sgabeblack@google.com 31213513Sgabeblack@google.com code(''' 31313513Sgabeblack@google.com const Address& addr); 31413513Sgabeblack@google.com 31513513Sgabeblack@google.comstd::string m_name; 31613513Sgabeblack@google.comint m_transitions_per_cycle; 31713513Sgabeblack@google.comint m_buffer_size; 31813513Sgabeblack@google.comint m_recycle_latency; 31913513Sgabeblack@google.comstd::map<std::string, std::string> m_cfg; 32013513Sgabeblack@google.comNodeID m_version; 32113513Sgabeblack@google.comNetwork* m_net_ptr; 32213513Sgabeblack@google.comMachineID m_machineID; 32313513Sgabeblack@google.combool m_is_blocking; 32413513Sgabeblack@google.comstd::map<Address, MessageBuffer*> m_block_map; 32513513Sgabeblack@google.comtypedef std::vector<MessageBuffer*> MsgVecType; 32613513Sgabeblack@google.comtypedef m5::hash_map< Address, MsgVecType* > WaitingBufType; 32713513Sgabeblack@google.comWaitingBufType m_waiting_buffers; 32813513Sgabeblack@google.comint m_max_in_port_rank; 32913513Sgabeblack@google.comint m_cur_in_port_rank; 33013513Sgabeblack@google.comstatic ${ident}_ProfileDumper s_profileDumper; 33113513Sgabeblack@google.com${ident}_Profiler m_profiler; 33213513Sgabeblack@google.comstatic int m_num_controllers; 33313513Sgabeblack@google.com 33413513Sgabeblack@google.com// Internal functions 33513513Sgabeblack@google.com''') 33613513Sgabeblack@google.com 33713513Sgabeblack@google.com for func in self.functions: 33813513Sgabeblack@google.com proto = func.prototype 33913513Sgabeblack@google.com if proto: 34013513Sgabeblack@google.com code('$proto') 34113513Sgabeblack@google.com 34213513Sgabeblack@google.com if self.EntryType != None: 34313513Sgabeblack@google.com code(''' 34413513Sgabeblack@google.com 34513513Sgabeblack@google.com// Set and Reset for cache_entry variable 34613513Sgabeblack@google.comvoid set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 34713513Sgabeblack@google.comvoid unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 34813513Sgabeblack@google.com''') 34913513Sgabeblack@google.com 35013513Sgabeblack@google.com if self.TBEType != None: 35113513Sgabeblack@google.com code(''' 35213513Sgabeblack@google.com 35313513Sgabeblack@google.com// Set and Reset for tbe variable 35413513Sgabeblack@google.comvoid set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 35513513Sgabeblack@google.comvoid unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 35613513Sgabeblack@google.com''') 35713513Sgabeblack@google.com 35813513Sgabeblack@google.com code(''' 35913513Sgabeblack@google.com 36013513Sgabeblack@google.com// Actions 36113513Sgabeblack@google.com''') 36213513Sgabeblack@google.com if self.TBEType != None and self.EntryType != None: 36313513Sgabeblack@google.com for action in self.actions.itervalues(): 36413513Sgabeblack@google.com code('/** \\brief ${{action.desc}} */') 36513513Sgabeblack@google.com code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 36613513Sgabeblack@google.com elif self.TBEType != None: 36713513Sgabeblack@google.com for action in self.actions.itervalues(): 36813513Sgabeblack@google.com code('/** \\brief ${{action.desc}} */') 36913513Sgabeblack@google.com code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr);') 37013513Sgabeblack@google.com elif self.EntryType != None: 37113513Sgabeblack@google.com for action in self.actions.itervalues(): 37213513Sgabeblack@google.com code('/** \\brief ${{action.desc}} */') 37313513Sgabeblack@google.com code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 37413513Sgabeblack@google.com else: 37513513Sgabeblack@google.com for action in self.actions.itervalues(): 37613513Sgabeblack@google.com code('/** \\brief ${{action.desc}} */') 37713513Sgabeblack@google.com code('void ${{action.ident}}(const Address& addr);') 37813513Sgabeblack@google.com 37913513Sgabeblack@google.com # the controller internal variables 38013513Sgabeblack@google.com code(''' 38113513Sgabeblack@google.com 38213513Sgabeblack@google.com// Objects 38313513Sgabeblack@google.com''') 38413513Sgabeblack@google.com for var in self.objects: 38513513Sgabeblack@google.com th = var.get("template_hack", "") 38613513Sgabeblack@google.com code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') 38713513Sgabeblack@google.com 38813513Sgabeblack@google.com if var.type.ident == "MessageBuffer": 38913513Sgabeblack@google.com self.message_buffer_names.append("m_%s_ptr" % var.c_ident) 39013513Sgabeblack@google.com 39113513Sgabeblack@google.com code.dedent() 39213513Sgabeblack@google.com code('};') 39313513Sgabeblack@google.com code('#endif // __${ident}_CONTROLLER_H__') 39413513Sgabeblack@google.com code.write(path, '%s.hh' % c_ident) 39513513Sgabeblack@google.com 39613513Sgabeblack@google.com def printControllerCC(self, path): 39713513Sgabeblack@google.com '''Output the actions for performing the actions''' 39813513Sgabeblack@google.com 39913513Sgabeblack@google.com code = self.symtab.codeFormatter() 40013513Sgabeblack@google.com ident = self.ident 40113513Sgabeblack@google.com c_ident = "%s_Controller" % self.ident 40213513Sgabeblack@google.com 40313513Sgabeblack@google.com code(''' 40413513Sgabeblack@google.com/** \\file $c_ident.cc 40513513Sgabeblack@google.com * 40613513Sgabeblack@google.com * Auto generated C++ code started by $__file__:$__line__ 40713513Sgabeblack@google.com * Created by slicc definition of Module "${{self.short}}" 40813513Sgabeblack@google.com */ 40913513Sgabeblack@google.com 41013513Sgabeblack@google.com#include <cassert> 41113513Sgabeblack@google.com#include <sstream> 41213513Sgabeblack@google.com#include <string> 41313513Sgabeblack@google.com 41413513Sgabeblack@google.com#include "base/cprintf.hh" 41513513Sgabeblack@google.com#include "debug/RubyGenerated.hh" 41613513Sgabeblack@google.com#include "debug/RubySlicc.hh" 41713513Sgabeblack@google.com#include "mem/protocol/${ident}_Controller.hh" 41813513Sgabeblack@google.com#include "mem/protocol/${ident}_Event.hh" 41913513Sgabeblack@google.com#include "mem/protocol/${ident}_State.hh" 42013513Sgabeblack@google.com#include "mem/protocol/Types.hh" 42113513Sgabeblack@google.com#include "mem/ruby/common/Global.hh" 42213513Sgabeblack@google.com#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 42313513Sgabeblack@google.com#include "mem/ruby/system/System.hh" 42413513Sgabeblack@google.com 42513513Sgabeblack@google.comusing namespace std; 42613513Sgabeblack@google.com''') 42713513Sgabeblack@google.com 42813513Sgabeblack@google.com # include object classes 42913513Sgabeblack@google.com seen_types = set() 43013513Sgabeblack@google.com for var in self.objects: 43113513Sgabeblack@google.com if var.type.ident not in seen_types and not var.type.isPrimitive: 43213513Sgabeblack@google.com code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 43313513Sgabeblack@google.com seen_types.add(var.type.ident) 43413513Sgabeblack@google.com 43513513Sgabeblack@google.com code(''' 43613513Sgabeblack@google.com$c_ident * 43713513Sgabeblack@google.com${c_ident}Params::create() 43813513Sgabeblack@google.com{ 43913513Sgabeblack@google.com return new $c_ident(this); 44013513Sgabeblack@google.com} 44113513Sgabeblack@google.com 44213513Sgabeblack@google.comint $c_ident::m_num_controllers = 0; 44313513Sgabeblack@google.com${ident}_ProfileDumper $c_ident::s_profileDumper; 44413513Sgabeblack@google.com 44513513Sgabeblack@google.com// for adding information to the protocol debug trace 44613513Sgabeblack@google.comstringstream ${ident}_transitionComment; 44713513Sgabeblack@google.com#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 44813513Sgabeblack@google.com 44913513Sgabeblack@google.com/** \\brief constructor */ 45013513Sgabeblack@google.com$c_ident::$c_ident(const Params *p) 45113513Sgabeblack@google.com : AbstractController(p) 45213513Sgabeblack@google.com{ 45313513Sgabeblack@google.com m_version = p->version; 45413513Sgabeblack@google.com m_transitions_per_cycle = p->transitions_per_cycle; 45513513Sgabeblack@google.com m_buffer_size = p->buffer_size; 45613513Sgabeblack@google.com m_recycle_latency = p->recycle_latency; 45713513Sgabeblack@google.com m_number_of_TBEs = p->number_of_TBEs; 45813513Sgabeblack@google.com m_is_blocking = false; 45913513Sgabeblack@google.com m_name = "${ident}"; 46013513Sgabeblack@google.com''') 46113513Sgabeblack@google.com # 46213513Sgabeblack@google.com # max_port_rank is used to size vectors and thus should be one plus the 46313513Sgabeblack@google.com # largest port rank 46413513Sgabeblack@google.com # 46513513Sgabeblack@google.com max_port_rank = self.in_ports[0].pairs["max_port_rank"] + 1 46613513Sgabeblack@google.com code(' m_max_in_port_rank = $max_port_rank;') 46713513Sgabeblack@google.com code.indent() 46813513Sgabeblack@google.com 46913513Sgabeblack@google.com # 47013513Sgabeblack@google.com # After initializing the universal machine parameters, initialize the 47113513Sgabeblack@google.com # this machines config parameters. Also detemine if these configuration 47213513Sgabeblack@google.com # params include a sequencer. This information will be used later for 47313513Sgabeblack@google.com # contecting the sequencer back to the L1 cache controller. 47413513Sgabeblack@google.com # 47513513Sgabeblack@google.com contains_dma_sequencer = False 47613513Sgabeblack@google.com sequencers = [] 47713513Sgabeblack@google.com for param in self.config_parameters: 47813513Sgabeblack@google.com if param.name == "dma_sequencer": 47913513Sgabeblack@google.com contains_dma_sequencer = True 48013513Sgabeblack@google.com elif re.compile("sequencer").search(param.name): 48113513Sgabeblack@google.com sequencers.append(param.name) 48213513Sgabeblack@google.com if param.pointer: 48313513Sgabeblack@google.com code('m_${{param.name}}_ptr = p->${{param.name}};') 48413513Sgabeblack@google.com else: 48513513Sgabeblack@google.com code('m_${{param.name}} = p->${{param.name}};') 48613513Sgabeblack@google.com 48713513Sgabeblack@google.com # 48813513Sgabeblack@google.com # For the l1 cache controller, add the special atomic support which 48913513Sgabeblack@google.com # includes passing the sequencer a pointer to the controller. 49013513Sgabeblack@google.com # 49113513Sgabeblack@google.com if self.ident == "L1Cache": 49213513Sgabeblack@google.com if not sequencers: 49313513Sgabeblack@google.com self.error("The L1Cache controller must include the sequencer " \ 49413513Sgabeblack@google.com "configuration parameter") 49513513Sgabeblack@google.com 49613513Sgabeblack@google.com for seq in sequencers: 49713513Sgabeblack@google.com code(''' 49813513Sgabeblack@google.comm_${{seq}}_ptr->setController(this); 49913513Sgabeblack@google.com ''') 50013513Sgabeblack@google.com # 50113513Sgabeblack@google.com # For the DMA controller, pass the sequencer a pointer to the 50213513Sgabeblack@google.com # controller. 50313513Sgabeblack@google.com # 50413513Sgabeblack@google.com if self.ident == "DMA": 50513513Sgabeblack@google.com if not contains_dma_sequencer: 50613513Sgabeblack@google.com self.error("The DMA controller must include the sequencer " \ 50713513Sgabeblack@google.com "configuration parameter") 50813513Sgabeblack@google.com 50913513Sgabeblack@google.com code(''' 51013513Sgabeblack@google.comm_dma_sequencer_ptr->setController(this); 51113513Sgabeblack@google.com''') 51213513Sgabeblack@google.com 51313513Sgabeblack@google.com code('m_num_controllers++;') 51413513Sgabeblack@google.com for var in self.objects: 51513513Sgabeblack@google.com if var.ident.find("mandatoryQueue") >= 0: 51613513Sgabeblack@google.com code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();') 51713513Sgabeblack@google.com 51813513Sgabeblack@google.com code.dedent() 51913513Sgabeblack@google.com code(''' 52013513Sgabeblack@google.com} 52113513Sgabeblack@google.com 52213513Sgabeblack@google.comvoid 52313513Sgabeblack@google.com$c_ident::init() 52413513Sgabeblack@google.com{ 52513513Sgabeblack@google.com MachineType machine_type; 52613513Sgabeblack@google.com int base; 52713513Sgabeblack@google.com 52813513Sgabeblack@google.com m_machineID.type = MachineType_${ident}; 52913513Sgabeblack@google.com m_machineID.num = m_version; 53013513Sgabeblack@google.com 53113513Sgabeblack@google.com // initialize objects 53213513Sgabeblack@google.com m_profiler.setVersion(m_version); 53313513Sgabeblack@google.com s_profileDumper.registerProfiler(&m_profiler); 53413513Sgabeblack@google.com 53513513Sgabeblack@google.com''') 53613513Sgabeblack@google.com 53713513Sgabeblack@google.com code.indent() 53813513Sgabeblack@google.com for var in self.objects: 53913513Sgabeblack@google.com vtype = var.type 54013513Sgabeblack@google.com vid = "m_%s_ptr" % var.c_ident 54113513Sgabeblack@google.com if "network" not in var: 54213513Sgabeblack@google.com # Not a network port object 54313513Sgabeblack@google.com if "primitive" in vtype: 54413513Sgabeblack@google.com code('$vid = new ${{vtype.c_ident}};') 54513513Sgabeblack@google.com if "default" in var: 54613513Sgabeblack@google.com code('(*$vid) = ${{var["default"]}};') 54713513Sgabeblack@google.com else: 54813513Sgabeblack@google.com # Normal Object 54913513Sgabeblack@google.com # added by SS 55013513Sgabeblack@google.com if "factory" in var: 55113513Sgabeblack@google.com code('$vid = ${{var["factory"]}};') 55213513Sgabeblack@google.com elif var.ident.find("mandatoryQueue") < 0: 55313513Sgabeblack@google.com th = var.get("template_hack", "") 55413513Sgabeblack@google.com expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 55513513Sgabeblack@google.com 55613513Sgabeblack@google.com args = "" 55713513Sgabeblack@google.com if "non_obj" not in vtype and not vtype.isEnumeration: 55813513Sgabeblack@google.com if expr.find("TBETable") >= 0: 55913513Sgabeblack@google.com args = "m_number_of_TBEs" 56013513Sgabeblack@google.com else: 56113513Sgabeblack@google.com args = var.get("constructor_hack", "") 56213513Sgabeblack@google.com 56313513Sgabeblack@google.com code('$expr($args);') 56413513Sgabeblack@google.com 56513513Sgabeblack@google.com code('assert($vid != NULL);') 56613513Sgabeblack@google.com 56713513Sgabeblack@google.com if "default" in var: 56813513Sgabeblack@google.com code('*$vid = ${{var["default"]}}; // Object default') 56913513Sgabeblack@google.com elif "default" in vtype: 57013513Sgabeblack@google.com comment = "Type %s default" % vtype.ident 57113513Sgabeblack@google.com code('*$vid = ${{vtype["default"]}}; // $comment') 57213513Sgabeblack@google.com 57313513Sgabeblack@google.com # Set ordering 57413513Sgabeblack@google.com if "ordered" in var and "trigger_queue" not in var: 57513513Sgabeblack@google.com # A buffer 57613513Sgabeblack@google.com code('$vid->setOrdering(${{var["ordered"]}});') 57713513Sgabeblack@google.com 57813513Sgabeblack@google.com # Set randomization 57913513Sgabeblack@google.com if "random" in var: 58013513Sgabeblack@google.com # A buffer 58113513Sgabeblack@google.com code('$vid->setRandomization(${{var["random"]}});') 58213513Sgabeblack@google.com 58313513Sgabeblack@google.com # Set Priority 58413513Sgabeblack@google.com if vtype.isBuffer and \ 58513513Sgabeblack@google.com "rank" in var and "trigger_queue" not in var: 58613513Sgabeblack@google.com code('$vid->setPriority(${{var["rank"]}});') 58713513Sgabeblack@google.com 58813513Sgabeblack@google.com else: 58913513Sgabeblack@google.com # Network port object 59013513Sgabeblack@google.com network = var["network"] 59113513Sgabeblack@google.com ordered = var["ordered"] 59213513Sgabeblack@google.com vnet = var["virtual_network"] 59313513Sgabeblack@google.com vnet_type = var["vnet_type"] 59413513Sgabeblack@google.com 59513513Sgabeblack@google.com assert var.machine is not None 59613513Sgabeblack@google.com code(''' 59713513Sgabeblack@google.commachine_type = string_to_MachineType("${{var.machine.ident}}"); 59813513Sgabeblack@google.combase = MachineType_base_number(machine_type); 59913513Sgabeblack@google.com$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type"); 60013513Sgabeblack@google.com''') 60113513Sgabeblack@google.com 60213513Sgabeblack@google.com code('assert($vid != NULL);') 60313513Sgabeblack@google.com 60413513Sgabeblack@google.com # Set ordering 60513513Sgabeblack@google.com if "ordered" in var: 60613513Sgabeblack@google.com # A buffer 60713513Sgabeblack@google.com code('$vid->setOrdering(${{var["ordered"]}});') 60813513Sgabeblack@google.com 60913513Sgabeblack@google.com # Set randomization 61013513Sgabeblack@google.com if "random" in var: 61113513Sgabeblack@google.com # A buffer 61213513Sgabeblack@google.com code('$vid->setRandomization(${{var["random"]}});') 61313513Sgabeblack@google.com 61413513Sgabeblack@google.com # Set Priority 61513513Sgabeblack@google.com if "rank" in var: 61613513Sgabeblack@google.com code('$vid->setPriority(${{var["rank"]}})') 61713513Sgabeblack@google.com 61813513Sgabeblack@google.com # Set buffer size 61913513Sgabeblack@google.com if vtype.isBuffer: 62013513Sgabeblack@google.com code(''' 62113513Sgabeblack@google.comif (m_buffer_size > 0) { 62213513Sgabeblack@google.com $vid->resize(m_buffer_size); 62313513Sgabeblack@google.com} 62413513Sgabeblack@google.com''') 62513513Sgabeblack@google.com 62613513Sgabeblack@google.com # set description (may be overriden later by port def) 62713513Sgabeblack@google.com code(''' 62813511Sgabeblack@google.com$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]"); 62913511Sgabeblack@google.com 63013513Sgabeblack@google.com''') 63113513Sgabeblack@google.com 63213511Sgabeblack@google.com if vtype.isBuffer: 63313513Sgabeblack@google.com if "recycle_latency" in var: 63413511Sgabeblack@google.com code('$vid->setRecycleLatency(${{var["recycle_latency"]}});') 63513511Sgabeblack@google.com else: 63613513Sgabeblack@google.com code('$vid->setRecycleLatency(m_recycle_latency);') 63713513Sgabeblack@google.com 63813513Sgabeblack@google.com 63913513Sgabeblack@google.com # Set the queue consumers 64013513Sgabeblack@google.com code() 64113513Sgabeblack@google.com for port in self.in_ports: 64213513Sgabeblack@google.com code('${{port.code}}.setConsumer(this);') 64313513Sgabeblack@google.com 64413513Sgabeblack@google.com # Set the queue descriptions 64513513Sgabeblack@google.com code() 64613513Sgabeblack@google.com for port in self.in_ports: 64713511Sgabeblack@google.com code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");') 64813513Sgabeblack@google.com 64913513Sgabeblack@google.com # Initialize the transition profiling 65013513Sgabeblack@google.com code() 65113511Sgabeblack@google.com for trans in self.transitions: 65213511Sgabeblack@google.com # Figure out if we stall 65313513Sgabeblack@google.com stall = False 65413513Sgabeblack@google.com for action in trans.actions: 65513513Sgabeblack@google.com if action.ident == "z_stall": 65613513Sgabeblack@google.com stall = True 65713513Sgabeblack@google.com 65813511Sgabeblack@google.com # Only possible if it is not a 'z' case 65913513Sgabeblack@google.com if not stall: 66013513Sgabeblack@google.com state = "%s_State_%s" % (self.ident, trans.state.ident) 66113513Sgabeblack@google.com event = "%s_Event_%s" % (self.ident, trans.event.ident) 66213511Sgabeblack@google.com code('m_profiler.possibleTransition($state, $event);') 66313511Sgabeblack@google.com 66413513Sgabeblack@google.com code.dedent() 66513513Sgabeblack@google.com code('}') 66613513Sgabeblack@google.com 66713511Sgabeblack@google.com has_mandatory_q = False 66813513Sgabeblack@google.com for port in self.in_ports: 66913513Sgabeblack@google.com if port.code.find("mandatoryQueue_ptr") >= 0: 67013513Sgabeblack@google.com has_mandatory_q = True 67113511Sgabeblack@google.com 67213511Sgabeblack@google.com if has_mandatory_q: 67313513Sgabeblack@google.com mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident 67413513Sgabeblack@google.com else: 67513513Sgabeblack@google.com mq_ident = "NULL" 67613513Sgabeblack@google.com 67713511Sgabeblack@google.com code(''' 67813513Sgabeblack@google.comint 67913513Sgabeblack@google.com$c_ident::getNumControllers() 68013513Sgabeblack@google.com{ 68113513Sgabeblack@google.com return m_num_controllers; 68213513Sgabeblack@google.com} 68313513Sgabeblack@google.com 68413513Sgabeblack@google.comMessageBuffer* 68513513Sgabeblack@google.com$c_ident::getMandatoryQueue() const 68613513Sgabeblack@google.com{ 68713513Sgabeblack@google.com return $mq_ident; 68813513Sgabeblack@google.com} 68913511Sgabeblack@google.com 69013511Sgabeblack@google.comconst int & 69113511Sgabeblack@google.com$c_ident::getVersion() const 69213513Sgabeblack@google.com{ 69313513Sgabeblack@google.com return m_version; 69413513Sgabeblack@google.com} 69513513Sgabeblack@google.com 69613513Sgabeblack@google.comconst string 69713513Sgabeblack@google.com$c_ident::toString() const 69813513Sgabeblack@google.com{ 69913511Sgabeblack@google.com return "$c_ident"; 70013513Sgabeblack@google.com} 70113513Sgabeblack@google.com 70213513Sgabeblack@google.comconst string 70313513Sgabeblack@google.com$c_ident::getName() const 70413513Sgabeblack@google.com{ 70513511Sgabeblack@google.com return m_name; 70613513Sgabeblack@google.com} 70713513Sgabeblack@google.com 70813513Sgabeblack@google.comconst MachineType 70913513Sgabeblack@google.com$c_ident::getMachineType() const 71013513Sgabeblack@google.com{ 71113513Sgabeblack@google.com return MachineType_${ident}; 71213511Sgabeblack@google.com} 71313513Sgabeblack@google.com 71413513Sgabeblack@google.comvoid 71513513Sgabeblack@google.com$c_ident::stallBuffer(MessageBuffer* buf, Address addr) 71613513Sgabeblack@google.com{ 71713513Sgabeblack@google.com if (m_waiting_buffers.count(addr) == 0) { 71813513Sgabeblack@google.com MsgVecType* msgVec = new MsgVecType; 71913513Sgabeblack@google.com msgVec->resize(m_max_in_port_rank, NULL); 72013513Sgabeblack@google.com m_waiting_buffers[addr] = msgVec; 72113513Sgabeblack@google.com } 72213513Sgabeblack@google.com (*(m_waiting_buffers[addr]))[m_cur_in_port_rank] = buf; 72313513Sgabeblack@google.com} 72413513Sgabeblack@google.com 72513513Sgabeblack@google.comvoid 72613513Sgabeblack@google.com$c_ident::wakeUpBuffers(Address addr) 72713513Sgabeblack@google.com{ 72813513Sgabeblack@google.com if (m_waiting_buffers.count(addr) > 0) { 72913513Sgabeblack@google.com // 73013513Sgabeblack@google.com // Wake up all possible lower rank (i.e. lower priority) buffers that could 73113513Sgabeblack@google.com // be waiting on this message. 73213513Sgabeblack@google.com // 73313513Sgabeblack@google.com for (int in_port_rank = m_cur_in_port_rank - 1; 73413513Sgabeblack@google.com in_port_rank >= 0; 73513513Sgabeblack@google.com in_port_rank--) { 73613513Sgabeblack@google.com if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) { 73713513Sgabeblack@google.com (*(m_waiting_buffers[addr]))[in_port_rank]->reanalyzeMessages(addr); 73813513Sgabeblack@google.com } 73913513Sgabeblack@google.com } 74013513Sgabeblack@google.com delete m_waiting_buffers[addr]; 74113513Sgabeblack@google.com m_waiting_buffers.erase(addr); 74213513Sgabeblack@google.com } 74313513Sgabeblack@google.com} 74413513Sgabeblack@google.com 74513513Sgabeblack@google.comvoid 74613513Sgabeblack@google.com$c_ident::wakeUpAllBuffers() 74713513Sgabeblack@google.com{ 74813513Sgabeblack@google.com // 74913511Sgabeblack@google.com // Wake up all possible buffers that could be waiting on any message. 75013511Sgabeblack@google.com // 75113513Sgabeblack@google.com 75213513Sgabeblack@google.com std::vector<MsgVecType*> wokeUpMsgVecs; 75313513Sgabeblack@google.com 75413513Sgabeblack@google.com if(m_waiting_buffers.size() > 0) { 75513513Sgabeblack@google.com for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin(); 75613513Sgabeblack@google.com buf_iter != m_waiting_buffers.end(); 75713513Sgabeblack@google.com ++buf_iter) { 75813513Sgabeblack@google.com for (MsgVecType::iterator vec_iter = buf_iter->second->begin(); 75913513Sgabeblack@google.com vec_iter != buf_iter->second->end(); 76013513Sgabeblack@google.com ++vec_iter) { 76113513Sgabeblack@google.com if (*vec_iter != NULL) { 76213513Sgabeblack@google.com (*vec_iter)->reanalyzeAllMessages(); 76313513Sgabeblack@google.com } 76413511Sgabeblack@google.com } 76513513Sgabeblack@google.com wokeUpMsgVecs.push_back(buf_iter->second); 76613513Sgabeblack@google.com } 76713513Sgabeblack@google.com 76813513Sgabeblack@google.com for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin(); 76913513Sgabeblack@google.com wb_iter != wokeUpMsgVecs.end(); 77013513Sgabeblack@google.com ++wb_iter) { 77113513Sgabeblack@google.com delete (*wb_iter); 77213513Sgabeblack@google.com } 77313513Sgabeblack@google.com 77413511Sgabeblack@google.com m_waiting_buffers.clear(); 77513513Sgabeblack@google.com } 77613513Sgabeblack@google.com} 77713513Sgabeblack@google.com 77813513Sgabeblack@google.comvoid 77913513Sgabeblack@google.com$c_ident::blockOnQueue(Address addr, MessageBuffer* port) 78013513Sgabeblack@google.com{ 78113513Sgabeblack@google.com m_is_blocking = true; 78213513Sgabeblack@google.com m_block_map[addr] = port; 78313513Sgabeblack@google.com} 78413513Sgabeblack@google.com 78513513Sgabeblack@google.comvoid 78613511Sgabeblack@google.com$c_ident::unblock(Address addr) 78713511Sgabeblack@google.com{ 78813513Sgabeblack@google.com m_block_map.erase(addr); 78913513Sgabeblack@google.com if (m_block_map.size() == 0) { 79013513Sgabeblack@google.com m_is_blocking = false; 79113513Sgabeblack@google.com } 79213513Sgabeblack@google.com} 79313513Sgabeblack@google.com 79413513Sgabeblack@google.comvoid 79513513Sgabeblack@google.com$c_ident::print(ostream& out) const 79613511Sgabeblack@google.com{ 79713513Sgabeblack@google.com out << "[$c_ident " << m_version << "]"; 79813513Sgabeblack@google.com} 79913513Sgabeblack@google.com 80013513Sgabeblack@google.comvoid 80113513Sgabeblack@google.com$c_ident::printConfig(ostream& out) const 80213513Sgabeblack@google.com{ 80313513Sgabeblack@google.com out << "$c_ident config: " << m_name << endl; 80413513Sgabeblack@google.com out << " version: " << m_version << endl; 80513513Sgabeblack@google.com map<string, string>::const_iterator it; 80613513Sgabeblack@google.com for (it = m_cfg.begin(); it != m_cfg.end(); it++) 80713513Sgabeblack@google.com out << " " << it->first << ": " << it->second << endl; 80813513Sgabeblack@google.com} 80913511Sgabeblack@google.com 81013513Sgabeblack@google.comvoid 81113513Sgabeblack@google.com$c_ident::printStats(ostream& out) const 81213513Sgabeblack@google.com{ 81313513Sgabeblack@google.com''') 81413513Sgabeblack@google.com # 81513513Sgabeblack@google.com # Cache and Memory Controllers have specific profilers associated with 81613513Sgabeblack@google.com # them. Print out these stats before dumping state transition stats. 81713513Sgabeblack@google.com # 81813513Sgabeblack@google.com for param in self.config_parameters: 81913513Sgabeblack@google.com if param.type_ast.type.ident == "CacheMemory" or \ 82013513Sgabeblack@google.com param.type_ast.type.ident == "DirectoryMemory" or \ 82113513Sgabeblack@google.com param.type_ast.type.ident == "MemoryControl": 82213511Sgabeblack@google.com assert(param.pointer) 82313513Sgabeblack@google.com code(' m_${{param.ident}}_ptr->printStats(out);') 82413513Sgabeblack@google.com 82513513Sgabeblack@google.com code(''' 82613513Sgabeblack@google.com if (m_version == 0) { 82713513Sgabeblack@google.com s_profileDumper.dumpStats(out); 82813513Sgabeblack@google.com } 82913513Sgabeblack@google.com} 83013513Sgabeblack@google.com 83113513Sgabeblack@google.comvoid $c_ident::clearStats() { 83213513Sgabeblack@google.com''') 83313513Sgabeblack@google.com # 83413513Sgabeblack@google.com # Cache and Memory Controllers have specific profilers associated with 83513511Sgabeblack@google.com # them. These stats must be cleared too. 83613513Sgabeblack@google.com # 83713513Sgabeblack@google.com for param in self.config_parameters: 83813513Sgabeblack@google.com if param.type_ast.type.ident == "CacheMemory" or \ 83913513Sgabeblack@google.com param.type_ast.type.ident == "MemoryControl": 84013513Sgabeblack@google.com assert(param.pointer) 84113513Sgabeblack@google.com code(' m_${{param.ident}}_ptr->clearStats();') 84213513Sgabeblack@google.com 84313513Sgabeblack@google.com code(''' 84413513Sgabeblack@google.com m_profiler.clearStats(); 84513513Sgabeblack@google.com} 84613513Sgabeblack@google.com''') 84713511Sgabeblack@google.com 84813513Sgabeblack@google.com if self.EntryType != None: 84913513Sgabeblack@google.com code(''' 85013513Sgabeblack@google.com 85113513Sgabeblack@google.com// Set and Reset for cache_entry variable 85213513Sgabeblack@google.comvoid 85313513Sgabeblack@google.com$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 85413513Sgabeblack@google.com{ 85513513Sgabeblack@google.com m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 85613513Sgabeblack@google.com} 85713513Sgabeblack@google.com 85813511Sgabeblack@google.comvoid 85913511Sgabeblack@google.com$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 86013513Sgabeblack@google.com{ 86113513Sgabeblack@google.com m_cache_entry_ptr = 0; 86213513Sgabeblack@google.com} 86313513Sgabeblack@google.com''') 86413513Sgabeblack@google.com 86513513Sgabeblack@google.com if self.TBEType != None: 86613513Sgabeblack@google.com code(''' 86713513Sgabeblack@google.com 86813513Sgabeblack@google.com// Set and Reset for tbe variable 86913513Sgabeblack@google.comvoid 87013513Sgabeblack@google.com$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 87113513Sgabeblack@google.com{ 87213513Sgabeblack@google.com m_tbe_ptr = m_new_tbe; 87313513Sgabeblack@google.com} 87413513Sgabeblack@google.com 87513513Sgabeblack@google.comvoid 87613513Sgabeblack@google.com$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 87713513Sgabeblack@google.com{ 87813513Sgabeblack@google.com m_tbe_ptr = NULL; 87913513Sgabeblack@google.com} 88013513Sgabeblack@google.com''') 88113513Sgabeblack@google.com 88213513Sgabeblack@google.com code(''' 88313513Sgabeblack@google.com 88413513Sgabeblack@google.com// Actions 88513513Sgabeblack@google.com''') 88613513Sgabeblack@google.com if self.TBEType != None and self.EntryType != None: 88713513Sgabeblack@google.com for action in self.actions.itervalues(): 88813513Sgabeblack@google.com if "c_code" not in action: 88913513Sgabeblack@google.com continue 89013513Sgabeblack@google.com 89113513Sgabeblack@google.com code(''' 89213511Sgabeblack@google.com/** \\brief ${{action.desc}} */ 89313511Sgabeblack@google.comvoid 89413513Sgabeblack@google.com$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 89513513Sgabeblack@google.com{ 89613513Sgabeblack@google.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 89713511Sgabeblack@google.com ${{action["c_code"]}} 89813511Sgabeblack@google.com} 89913513Sgabeblack@google.com 90013513Sgabeblack@google.com''') 90113513Sgabeblack@google.com elif self.TBEType != None: 90213513Sgabeblack@google.com for action in self.actions.itervalues(): 90313513Sgabeblack@google.com if "c_code" not in action: 90413513Sgabeblack@google.com continue 90513513Sgabeblack@google.com 90613513Sgabeblack@google.com code(''' 90713513Sgabeblack@google.com/** \\brief ${{action.desc}} */ 90813511Sgabeblack@google.comvoid 90913513Sgabeblack@google.com$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr) 91013513Sgabeblack@google.com{ 91113513Sgabeblack@google.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 91213513Sgabeblack@google.com ${{action["c_code"]}} 91313513Sgabeblack@google.com} 91413513Sgabeblack@google.com 91513513Sgabeblack@google.com''') 91613513Sgabeblack@google.com elif self.EntryType != None: 91713513Sgabeblack@google.com for action in self.actions.itervalues(): 91813513Sgabeblack@google.com if "c_code" not in action: 91913513Sgabeblack@google.com continue 92013513Sgabeblack@google.com 92113513Sgabeblack@google.com code(''' 92213513Sgabeblack@google.com/** \\brief ${{action.desc}} */ 92313513Sgabeblack@google.comvoid 92413513Sgabeblack@google.com$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 92513513Sgabeblack@google.com{ 92613513Sgabeblack@google.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 92713513Sgabeblack@google.com ${{action["c_code"]}} 92813513Sgabeblack@google.com} 92913513Sgabeblack@google.com 93013513Sgabeblack@google.com''') 93113513Sgabeblack@google.com else: 93213513Sgabeblack@google.com for action in self.actions.itervalues(): 93313513Sgabeblack@google.com if "c_code" not in action: 93413513Sgabeblack@google.com continue 93513513Sgabeblack@google.com 93613513Sgabeblack@google.com code(''' 93713513Sgabeblack@google.com/** \\brief ${{action.desc}} */ 93813513Sgabeblack@google.comvoid 93913513Sgabeblack@google.com$c_ident::${{action.ident}}(const Address& addr) 94013513Sgabeblack@google.com{ 94113513Sgabeblack@google.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 94213513Sgabeblack@google.com ${{action["c_code"]}} 94313513Sgabeblack@google.com} 94413513Sgabeblack@google.com 94513513Sgabeblack@google.com''') 94613513Sgabeblack@google.com for func in self.functions: 94713513Sgabeblack@google.com code(func.generateCode()) 94813513Sgabeblack@google.com 94913513Sgabeblack@google.com code.write(path, "%s.cc" % c_ident) 95013513Sgabeblack@google.com 95113513Sgabeblack@google.com def printCWakeup(self, path): 95213513Sgabeblack@google.com '''Output the wakeup loop for the events''' 95313513Sgabeblack@google.com 95413513Sgabeblack@google.com code = self.symtab.codeFormatter() 95513513Sgabeblack@google.com ident = self.ident 95613513Sgabeblack@google.com 95713513Sgabeblack@google.com code(''' 95813513Sgabeblack@google.com// Auto generated C++ code started by $__file__:$__line__ 95913513Sgabeblack@google.com// ${ident}: ${{self.short}} 96013513Sgabeblack@google.com 96113513Sgabeblack@google.com#include <cassert> 96213513Sgabeblack@google.com 96313513Sgabeblack@google.com#include "base/misc.hh" 96413513Sgabeblack@google.com#include "debug/RubySlicc.hh" 96513513Sgabeblack@google.com#include "mem/protocol/${ident}_Controller.hh" 96613513Sgabeblack@google.com#include "mem/protocol/${ident}_Event.hh" 96713513Sgabeblack@google.com#include "mem/protocol/${ident}_State.hh" 96813513Sgabeblack@google.com#include "mem/protocol/Types.hh" 96913513Sgabeblack@google.com#include "mem/ruby/common/Global.hh" 97013513Sgabeblack@google.com#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 97113513Sgabeblack@google.com#include "mem/ruby/system/System.hh" 97213513Sgabeblack@google.com 97313513Sgabeblack@google.comusing namespace std; 97413513Sgabeblack@google.com 97513513Sgabeblack@google.comvoid 97613513Sgabeblack@google.com${ident}_Controller::wakeup() 97713513Sgabeblack@google.com{ 97813513Sgabeblack@google.com int counter = 0; 97913513Sgabeblack@google.com while (true) { 98013513Sgabeblack@google.com // Some cases will put us into an infinite loop without this limit 98113513Sgabeblack@google.com assert(counter <= m_transitions_per_cycle); 98213513Sgabeblack@google.com if (counter == m_transitions_per_cycle) { 98313513Sgabeblack@google.com // Count how often we are fully utilized 98413513Sgabeblack@google.com g_system_ptr->getProfiler()->controllerBusy(m_machineID); 98513513Sgabeblack@google.com 98613513Sgabeblack@google.com // Wakeup in another cycle and try again 98713513Sgabeblack@google.com g_eventQueue_ptr->scheduleEvent(this, 1); 98813513Sgabeblack@google.com break; 98913513Sgabeblack@google.com } 99013513Sgabeblack@google.com''') 99113513Sgabeblack@google.com 99213513Sgabeblack@google.com code.indent() 99313513Sgabeblack@google.com code.indent() 99413513Sgabeblack@google.com 99513513Sgabeblack@google.com # InPorts 99613513Sgabeblack@google.com # 99713513Sgabeblack@google.com for port in self.in_ports: 99813513Sgabeblack@google.com code.indent() 99913513Sgabeblack@google.com code('// ${ident}InPort $port') 100013513Sgabeblack@google.com if port.pairs.has_key("rank"): 100113513Sgabeblack@google.com code('m_cur_in_port_rank = ${{port.pairs["rank"]}};') 100213513Sgabeblack@google.com else: 100313513Sgabeblack@google.com code('m_cur_in_port_rank = 0;') 100413513Sgabeblack@google.com code('${{port["c_code_in_port"]}}') 100513513Sgabeblack@google.com code.dedent() 100613513Sgabeblack@google.com 100713513Sgabeblack@google.com code('') 100813513Sgabeblack@google.com 100913513Sgabeblack@google.com code.dedent() 101013513Sgabeblack@google.com code.dedent() 101113513Sgabeblack@google.com code(''' 101213513Sgabeblack@google.com break; // If we got this far, we have nothing left todo 101313513Sgabeblack@google.com } 101413513Sgabeblack@google.com // g_eventQueue_ptr->scheduleEvent(this, 1); 101513513Sgabeblack@google.com} 101613513Sgabeblack@google.com''') 101713513Sgabeblack@google.com 101813513Sgabeblack@google.com code.write(path, "%s_Wakeup.cc" % self.ident) 101913513Sgabeblack@google.com 102013513Sgabeblack@google.com def printCSwitch(self, path): 102113513Sgabeblack@google.com '''Output switch statement for transition table''' 102213513Sgabeblack@google.com 102313513Sgabeblack@google.com code = self.symtab.codeFormatter() 102413513Sgabeblack@google.com ident = self.ident 102513513Sgabeblack@google.com 102613513Sgabeblack@google.com code(''' 102713513Sgabeblack@google.com// Auto generated C++ code started by $__file__:$__line__ 102813513Sgabeblack@google.com// ${ident}: ${{self.short}} 102913513Sgabeblack@google.com 103013513Sgabeblack@google.com#include <cassert> 103113513Sgabeblack@google.com 103213513Sgabeblack@google.com#include "base/misc.hh" 103313513Sgabeblack@google.com#include "base/trace.hh" 103413513Sgabeblack@google.com#include "debug/ProtocolTrace.hh" 103513513Sgabeblack@google.com#include "debug/RubyGenerated.hh" 103613513Sgabeblack@google.com#include "mem/protocol/${ident}_Controller.hh" 103713513Sgabeblack@google.com#include "mem/protocol/${ident}_Event.hh" 103813513Sgabeblack@google.com#include "mem/protocol/${ident}_State.hh" 103913513Sgabeblack@google.com#include "mem/protocol/Types.hh" 104013513Sgabeblack@google.com#include "mem/ruby/common/Global.hh" 104113513Sgabeblack@google.com#include "mem/ruby/system/System.hh" 104213513Sgabeblack@google.com 104313513Sgabeblack@google.com#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 104413513Sgabeblack@google.com 104513513Sgabeblack@google.com#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 104613513Sgabeblack@google.com#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 104713513Sgabeblack@google.com 104813513Sgabeblack@google.comTransitionResult 104913513Sgabeblack@google.com${ident}_Controller::doTransition(${ident}_Event event, 105013513Sgabeblack@google.com''') 105113513Sgabeblack@google.com if self.EntryType != None: 105213513Sgabeblack@google.com code(''' 105313513Sgabeblack@google.com ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 105413513Sgabeblack@google.com''') 105513513Sgabeblack@google.com if self.TBEType != None: 105613513Sgabeblack@google.com code(''' 105713513Sgabeblack@google.com ${{self.TBEType.c_ident}}* m_tbe_ptr, 105813513Sgabeblack@google.com''') 105913513Sgabeblack@google.com code(''' 106013513Sgabeblack@google.com const Address &addr) 106113513Sgabeblack@google.com{ 106213513Sgabeblack@google.com''') 106313513Sgabeblack@google.com if self.TBEType != None and self.EntryType != None: 106413513Sgabeblack@google.com code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 106513513Sgabeblack@google.com elif self.TBEType != None: 106613513Sgabeblack@google.com code('${ident}_State state = getState(m_tbe_ptr, addr);') 106713513Sgabeblack@google.com elif self.EntryType != None: 106813513Sgabeblack@google.com code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 106913513Sgabeblack@google.com else: 107013513Sgabeblack@google.com code('${ident}_State state = getState(addr);') 107113513Sgabeblack@google.com 107213513Sgabeblack@google.com code(''' 107313513Sgabeblack@google.com ${ident}_State next_state = state; 107413513Sgabeblack@google.com 107513513Sgabeblack@google.com DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 107613513Sgabeblack@google.com *this, 107713513Sgabeblack@google.com g_eventQueue_ptr->getTime(), 107813513Sgabeblack@google.com ${ident}_State_to_string(state), 107913513Sgabeblack@google.com ${ident}_Event_to_string(event), 108013513Sgabeblack@google.com addr); 108113513Sgabeblack@google.com 108213513Sgabeblack@google.com TransitionResult result = 108313513Sgabeblack@google.com''') 108413513Sgabeblack@google.com if self.TBEType != None and self.EntryType != None: 108513513Sgabeblack@google.com code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 108613513Sgabeblack@google.com elif self.TBEType != None: 108713513Sgabeblack@google.com code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 108813513Sgabeblack@google.com elif self.EntryType != None: 108913513Sgabeblack@google.com code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 109013513Sgabeblack@google.com else: 109113513Sgabeblack@google.com code('doTransitionWorker(event, state, next_state, addr);') 109213513Sgabeblack@google.com 109313513Sgabeblack@google.com code(''' 109413513Sgabeblack@google.com if (result == TransitionResult_Valid) { 109513513Sgabeblack@google.com DPRINTF(RubyGenerated, "next_state: %s\\n", 109613513Sgabeblack@google.com ${ident}_State_to_string(next_state)); 109713513Sgabeblack@google.com m_profiler.countTransition(state, event); 109813513Sgabeblack@google.com DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 109913513Sgabeblack@google.com curTick(), m_version, "${ident}", 110013513Sgabeblack@google.com ${ident}_Event_to_string(event), 110113513Sgabeblack@google.com ${ident}_State_to_string(state), 110213513Sgabeblack@google.com ${ident}_State_to_string(next_state), 110313513Sgabeblack@google.com addr, GET_TRANSITION_COMMENT()); 110413513Sgabeblack@google.com 110513513Sgabeblack@google.com CLEAR_TRANSITION_COMMENT(); 110613513Sgabeblack@google.com''') 110713513Sgabeblack@google.com if self.TBEType != None and self.EntryType != None: 110813513Sgabeblack@google.com code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 110913513Sgabeblack@google.com code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 111013513Sgabeblack@google.com elif self.TBEType != None: 111113513Sgabeblack@google.com code('setState(m_tbe_ptr, addr, next_state);') 111213513Sgabeblack@google.com code('setAccessPermission(addr, next_state);') 111313513Sgabeblack@google.com elif self.EntryType != None: 111413513Sgabeblack@google.com code('setState(m_cache_entry_ptr, addr, next_state);') 111513513Sgabeblack@google.com code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 111613513Sgabeblack@google.com else: 111713513Sgabeblack@google.com code('setState(addr, next_state);') 111813513Sgabeblack@google.com code('setAccessPermission(addr, next_state);') 111913513Sgabeblack@google.com 112013513Sgabeblack@google.com code(''' 112113513Sgabeblack@google.com } else if (result == TransitionResult_ResourceStall) { 112213513Sgabeblack@google.com DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 112313513Sgabeblack@google.com curTick(), m_version, "${ident}", 112413513Sgabeblack@google.com ${ident}_Event_to_string(event), 112513513Sgabeblack@google.com ${ident}_State_to_string(state), 112613513Sgabeblack@google.com ${ident}_State_to_string(next_state), 112713513Sgabeblack@google.com addr, "Resource Stall"); 112813513Sgabeblack@google.com } else if (result == TransitionResult_ProtocolStall) { 112913513Sgabeblack@google.com DPRINTF(RubyGenerated, "stalling\\n"); 113013513Sgabeblack@google.com DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 113113513Sgabeblack@google.com curTick(), m_version, "${ident}", 113213513Sgabeblack@google.com ${ident}_Event_to_string(event), 113313513Sgabeblack@google.com ${ident}_State_to_string(state), 113413513Sgabeblack@google.com ${ident}_State_to_string(next_state), 113513513Sgabeblack@google.com addr, "Protocol Stall"); 113613513Sgabeblack@google.com } 113713513Sgabeblack@google.com 113813513Sgabeblack@google.com return result; 113913513Sgabeblack@google.com} 114013513Sgabeblack@google.com 114113513Sgabeblack@google.comTransitionResult 114213513Sgabeblack@google.com${ident}_Controller::doTransitionWorker(${ident}_Event event, 114313513Sgabeblack@google.com ${ident}_State state, 114413513Sgabeblack@google.com ${ident}_State& next_state, 114513513Sgabeblack@google.com''') 114613513Sgabeblack@google.com 114713513Sgabeblack@google.com if self.TBEType != None: 114813513Sgabeblack@google.com code(''' 114913513Sgabeblack@google.com ${{self.TBEType.c_ident}}*& m_tbe_ptr, 115013513Sgabeblack@google.com''') 115113513Sgabeblack@google.com if self.EntryType != None: 115213513Sgabeblack@google.com code(''' 115313513Sgabeblack@google.com ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 115413513Sgabeblack@google.com''') 115513513Sgabeblack@google.com code(''' 115613513Sgabeblack@google.com const Address& addr) 115713513Sgabeblack@google.com{ 115813513Sgabeblack@google.com switch(HASH_FUN(state, event)) { 115913513Sgabeblack@google.com''') 116013513Sgabeblack@google.com 116113513Sgabeblack@google.com # This map will allow suppress generating duplicate code 116213513Sgabeblack@google.com cases = orderdict() 116313513Sgabeblack@google.com 116413513Sgabeblack@google.com for trans in self.transitions: 116513513Sgabeblack@google.com case_string = "%s_State_%s, %s_Event_%s" % \ 116613513Sgabeblack@google.com (self.ident, trans.state.ident, self.ident, trans.event.ident) 116713511Sgabeblack@google.com 116813511Sgabeblack@google.com case = self.symtab.codeFormatter() 116913511Sgabeblack@google.com # Only set next_state if it changes 117013513Sgabeblack@google.com if trans.state != trans.nextState: 117113511Sgabeblack@google.com ns_ident = trans.nextState.ident 117213513Sgabeblack@google.com case('next_state = ${ident}_State_${ns_ident};') 117313513Sgabeblack@google.com 117413513Sgabeblack@google.com actions = trans.actions 117513513Sgabeblack@google.com 117613513Sgabeblack@google.com # Check for resources 117713513Sgabeblack@google.com case_sorter = [] 117813511Sgabeblack@google.com res = trans.resources 117913511Sgabeblack@google.com for key,val in res.iteritems(): 118013513Sgabeblack@google.com if key.type.ident != "DNUCAStopTable": 118113513Sgabeblack@google.com val = ''' 118213513Sgabeblack@google.comif (!%s.areNSlotsAvailable(%s)) 118313513Sgabeblack@google.com return TransitionResult_ResourceStall; 118413511Sgabeblack@google.com''' % (key.code, val) 118513513Sgabeblack@google.com case_sorter.append(val) 118613513Sgabeblack@google.com 118713513Sgabeblack@google.com 118813513Sgabeblack@google.com # Emit the code sequences in a sorted order. This makes the 118913511Sgabeblack@google.com # output deterministic (without this the output order can vary 119013511Sgabeblack@google.com # since Map's keys() on a vector of pointers is not deterministic 119113513Sgabeblack@google.com for c in sorted(case_sorter): 119213513Sgabeblack@google.com case("$c") 119313513Sgabeblack@google.com 119413513Sgabeblack@google.com # Figure out if we stall 119513513Sgabeblack@google.com stall = False 119613511Sgabeblack@google.com for action in actions: 119713513Sgabeblack@google.com if action.ident == "z_stall": 119813513Sgabeblack@google.com stall = True 119913511Sgabeblack@google.com break 120013513Sgabeblack@google.com 120113513Sgabeblack@google.com if stall: 120213513Sgabeblack@google.com case('return TransitionResult_ProtocolStall;') 120313511Sgabeblack@google.com else: 120413511Sgabeblack@google.com if self.TBEType != None and self.EntryType != None: 120513511Sgabeblack@google.com for action in actions: 120613511Sgabeblack@google.com case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 120713513Sgabeblack@google.com elif self.TBEType != None: 120813513Sgabeblack@google.com for action in actions: 1209 case('${{action.ident}}(m_tbe_ptr, addr);') 1210 elif self.EntryType != None: 1211 for action in actions: 1212 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1213 else: 1214 for action in actions: 1215 case('${{action.ident}}(addr);') 1216 case('return TransitionResult_Valid;') 1217 1218 case = str(case) 1219 1220 # Look to see if this transition code is unique. 1221 if case not in cases: 1222 cases[case] = [] 1223 1224 cases[case].append(case_string) 1225 1226 # Walk through all of the unique code blocks and spit out the 1227 # corresponding case statement elements 1228 for case,transitions in cases.iteritems(): 1229 # Iterative over all the multiple transitions that share 1230 # the same code 1231 for trans in transitions: 1232 code(' case HASH_FUN($trans):') 1233 code(' $case') 1234 1235 code(''' 1236 default: 1237 fatal("Invalid transition\\n" 1238 "%s time: %d addr: %s event: %s state: %s\\n", 1239 name(), g_eventQueue_ptr->getTime(), addr, event, state); 1240 } 1241 return TransitionResult_Valid; 1242} 1243''') 1244 code.write(path, "%s_Transitions.cc" % self.ident) 1245 1246 def printProfileDumperHH(self, path): 1247 code = self.symtab.codeFormatter() 1248 ident = self.ident 1249 1250 code(''' 1251// Auto generated C++ code started by $__file__:$__line__ 1252// ${ident}: ${{self.short}} 1253 1254#ifndef __${ident}_PROFILE_DUMPER_HH__ 1255#define __${ident}_PROFILE_DUMPER_HH__ 1256 1257#include <cassert> 1258#include <iostream> 1259#include <vector> 1260 1261#include "${ident}_Event.hh" 1262#include "${ident}_Profiler.hh" 1263 1264typedef std::vector<${ident}_Profiler *> ${ident}_profilers; 1265 1266class ${ident}_ProfileDumper 1267{ 1268 public: 1269 ${ident}_ProfileDumper(); 1270 void registerProfiler(${ident}_Profiler* profiler); 1271 void dumpStats(std::ostream& out) const; 1272 1273 private: 1274 ${ident}_profilers m_profilers; 1275}; 1276 1277#endif // __${ident}_PROFILE_DUMPER_HH__ 1278''') 1279 code.write(path, "%s_ProfileDumper.hh" % self.ident) 1280 1281 def printProfileDumperCC(self, path): 1282 code = self.symtab.codeFormatter() 1283 ident = self.ident 1284 1285 code(''' 1286// Auto generated C++ code started by $__file__:$__line__ 1287// ${ident}: ${{self.short}} 1288 1289#include "mem/protocol/${ident}_ProfileDumper.hh" 1290 1291${ident}_ProfileDumper::${ident}_ProfileDumper() 1292{ 1293} 1294 1295void 1296${ident}_ProfileDumper::registerProfiler(${ident}_Profiler* profiler) 1297{ 1298 m_profilers.push_back(profiler); 1299} 1300 1301void 1302${ident}_ProfileDumper::dumpStats(std::ostream& out) const 1303{ 1304 out << " --- ${ident} ---\\n"; 1305 out << " - Event Counts -\\n"; 1306 for (${ident}_Event event = ${ident}_Event_FIRST; 1307 event < ${ident}_Event_NUM; 1308 ++event) { 1309 out << (${ident}_Event) event << " ["; 1310 uint64 total = 0; 1311 for (int i = 0; i < m_profilers.size(); i++) { 1312 out << m_profilers[i]->getEventCount(event) << " "; 1313 total += m_profilers[i]->getEventCount(event); 1314 } 1315 out << "] " << total << "\\n"; 1316 } 1317 out << "\\n"; 1318 out << " - Transitions -\\n"; 1319 for (${ident}_State state = ${ident}_State_FIRST; 1320 state < ${ident}_State_NUM; 1321 ++state) { 1322 for (${ident}_Event event = ${ident}_Event_FIRST; 1323 event < ${ident}_Event_NUM; 1324 ++event) { 1325 if (m_profilers[0]->isPossible(state, event)) { 1326 out << (${ident}_State) state << " " 1327 << (${ident}_Event) event << " ["; 1328 uint64 total = 0; 1329 for (int i = 0; i < m_profilers.size(); i++) { 1330 out << m_profilers[i]->getTransitionCount(state, event) << " "; 1331 total += m_profilers[i]->getTransitionCount(state, event); 1332 } 1333 out << "] " << total << "\\n"; 1334 } 1335 } 1336 out << "\\n"; 1337 } 1338} 1339''') 1340 code.write(path, "%s_ProfileDumper.cc" % self.ident) 1341 1342 def printProfilerHH(self, path): 1343 code = self.symtab.codeFormatter() 1344 ident = self.ident 1345 1346 code(''' 1347// Auto generated C++ code started by $__file__:$__line__ 1348// ${ident}: ${{self.short}} 1349 1350#ifndef __${ident}_PROFILER_HH__ 1351#define __${ident}_PROFILER_HH__ 1352 1353#include <cassert> 1354#include <iostream> 1355 1356#include "mem/protocol/${ident}_Event.hh" 1357#include "mem/protocol/${ident}_State.hh" 1358#include "mem/ruby/common/Global.hh" 1359 1360class ${ident}_Profiler 1361{ 1362 public: 1363 ${ident}_Profiler(); 1364 void setVersion(int version); 1365 void countTransition(${ident}_State state, ${ident}_Event event); 1366 void possibleTransition(${ident}_State state, ${ident}_Event event); 1367 uint64 getEventCount(${ident}_Event event); 1368 bool isPossible(${ident}_State state, ${ident}_Event event); 1369 uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); 1370 void clearStats(); 1371 1372 private: 1373 int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 1374 int m_event_counters[${ident}_Event_NUM]; 1375 bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 1376 int m_version; 1377}; 1378 1379#endif // __${ident}_PROFILER_HH__ 1380''') 1381 code.write(path, "%s_Profiler.hh" % self.ident) 1382 1383 def printProfilerCC(self, path): 1384 code = self.symtab.codeFormatter() 1385 ident = self.ident 1386 1387 code(''' 1388// Auto generated C++ code started by $__file__:$__line__ 1389// ${ident}: ${{self.short}} 1390 1391#include <cassert> 1392 1393#include "mem/protocol/${ident}_Profiler.hh" 1394 1395${ident}_Profiler::${ident}_Profiler() 1396{ 1397 for (int state = 0; state < ${ident}_State_NUM; state++) { 1398 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1399 m_possible[state][event] = false; 1400 m_counters[state][event] = 0; 1401 } 1402 } 1403 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1404 m_event_counters[event] = 0; 1405 } 1406} 1407 1408void 1409${ident}_Profiler::setVersion(int version) 1410{ 1411 m_version = version; 1412} 1413 1414void 1415${ident}_Profiler::clearStats() 1416{ 1417 for (int state = 0; state < ${ident}_State_NUM; state++) { 1418 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1419 m_counters[state][event] = 0; 1420 } 1421 } 1422 1423 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1424 m_event_counters[event] = 0; 1425 } 1426} 1427void 1428${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) 1429{ 1430 assert(m_possible[state][event]); 1431 m_counters[state][event]++; 1432 m_event_counters[event]++; 1433} 1434void 1435${ident}_Profiler::possibleTransition(${ident}_State state, 1436 ${ident}_Event event) 1437{ 1438 m_possible[state][event] = true; 1439} 1440 1441uint64 1442${ident}_Profiler::getEventCount(${ident}_Event event) 1443{ 1444 return m_event_counters[event]; 1445} 1446 1447bool 1448${ident}_Profiler::isPossible(${ident}_State state, ${ident}_Event event) 1449{ 1450 return m_possible[state][event]; 1451} 1452 1453uint64 1454${ident}_Profiler::getTransitionCount(${ident}_State state, 1455 ${ident}_Event event) 1456{ 1457 return m_counters[state][event]; 1458} 1459 1460''') 1461 code.write(path, "%s_Profiler.cc" % self.ident) 1462 1463 # ************************** 1464 # ******* HTML Files ******* 1465 # ************************** 1466 def frameRef(self, click_href, click_target, over_href, over_num, text): 1467 code = self.symtab.codeFormatter(fix_newlines=False) 1468 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1469 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1470 parent.frames[$over_num].location='$over_href' 1471 }\"> 1472 ${{html.formatShorthand(text)}} 1473 </A>""") 1474 return str(code) 1475 1476 def writeHTMLFiles(self, path): 1477 # Create table with no row hilighted 1478 self.printHTMLTransitions(path, None) 1479 1480 # Generate transition tables 1481 for state in self.states.itervalues(): 1482 self.printHTMLTransitions(path, state) 1483 1484 # Generate action descriptions 1485 for action in self.actions.itervalues(): 1486 name = "%s_action_%s.html" % (self.ident, action.ident) 1487 code = html.createSymbol(action, "Action") 1488 code.write(path, name) 1489 1490 # Generate state descriptions 1491 for state in self.states.itervalues(): 1492 name = "%s_State_%s.html" % (self.ident, state.ident) 1493 code = html.createSymbol(state, "State") 1494 code.write(path, name) 1495 1496 # Generate event descriptions 1497 for event in self.events.itervalues(): 1498 name = "%s_Event_%s.html" % (self.ident, event.ident) 1499 code = html.createSymbol(event, "Event") 1500 code.write(path, name) 1501 1502 def printHTMLTransitions(self, path, active_state): 1503 code = self.symtab.codeFormatter() 1504 1505 code(''' 1506<HTML> 1507<BODY link="blue" vlink="blue"> 1508 1509<H1 align="center">${{html.formatShorthand(self.short)}}: 1510''') 1511 code.indent() 1512 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1513 mid = machine.ident 1514 if i != 0: 1515 extra = " - " 1516 else: 1517 extra = "" 1518 if machine == self: 1519 code('$extra$mid') 1520 else: 1521 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1522 code.dedent() 1523 1524 code(""" 1525</H1> 1526 1527<TABLE border=1> 1528<TR> 1529 <TH> </TH> 1530""") 1531 1532 for event in self.events.itervalues(): 1533 href = "%s_Event_%s.html" % (self.ident, event.ident) 1534 ref = self.frameRef(href, "Status", href, "1", event.short) 1535 code('<TH bgcolor=white>$ref</TH>') 1536 1537 code('</TR>') 1538 # -- Body of table 1539 for state in self.states.itervalues(): 1540 # -- Each row 1541 if state == active_state: 1542 color = "yellow" 1543 else: 1544 color = "white" 1545 1546 click = "%s_table_%s.html" % (self.ident, state.ident) 1547 over = "%s_State_%s.html" % (self.ident, state.ident) 1548 text = html.formatShorthand(state.short) 1549 ref = self.frameRef(click, "Table", over, "1", state.short) 1550 code(''' 1551<TR> 1552 <TH bgcolor=$color>$ref</TH> 1553''') 1554 1555 # -- One column for each event 1556 for event in self.events.itervalues(): 1557 trans = self.table.get((state,event), None) 1558 if trans is None: 1559 # This is the no transition case 1560 if state == active_state: 1561 color = "#C0C000" 1562 else: 1563 color = "lightgrey" 1564 1565 code('<TD bgcolor=$color> </TD>') 1566 continue 1567 1568 next = trans.nextState 1569 stall_action = False 1570 1571 # -- Get the actions 1572 for action in trans.actions: 1573 if action.ident == "z_stall" or \ 1574 action.ident == "zz_recycleMandatoryQueue": 1575 stall_action = True 1576 1577 # -- Print out "actions/next-state" 1578 if stall_action: 1579 if state == active_state: 1580 color = "#C0C000" 1581 else: 1582 color = "lightgrey" 1583 1584 elif active_state and next.ident == active_state.ident: 1585 color = "aqua" 1586 elif state == active_state: 1587 color = "yellow" 1588 else: 1589 color = "white" 1590 1591 code('<TD bgcolor=$color>') 1592 for action in trans.actions: 1593 href = "%s_action_%s.html" % (self.ident, action.ident) 1594 ref = self.frameRef(href, "Status", href, "1", 1595 action.short) 1596 code(' $ref') 1597 if next != state: 1598 if trans.actions: 1599 code('/') 1600 click = "%s_table_%s.html" % (self.ident, next.ident) 1601 over = "%s_State_%s.html" % (self.ident, next.ident) 1602 ref = self.frameRef(click, "Table", over, "1", next.short) 1603 code("$ref") 1604 code("</TD>") 1605 1606 # -- Each row 1607 if state == active_state: 1608 color = "yellow" 1609 else: 1610 color = "white" 1611 1612 click = "%s_table_%s.html" % (self.ident, state.ident) 1613 over = "%s_State_%s.html" % (self.ident, state.ident) 1614 ref = self.frameRef(click, "Table", over, "1", state.short) 1615 code(''' 1616 <TH bgcolor=$color>$ref</TH> 1617</TR> 1618''') 1619 code(''' 1620<!- Column footer-> 1621<TR> 1622 <TH> </TH> 1623''') 1624 1625 for event in self.events.itervalues(): 1626 href = "%s_Event_%s.html" % (self.ident, event.ident) 1627 ref = self.frameRef(href, "Status", href, "1", event.short) 1628 code('<TH bgcolor=white>$ref</TH>') 1629 code(''' 1630</TR> 1631</TABLE> 1632</BODY></HTML> 1633''') 1634 1635 1636 if active_state: 1637 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1638 else: 1639 name = "%s_table.html" % self.ident 1640 code.write(path, name) 1641 1642__all__ = [ "StateMachine" ] 1643