StateMachine.py revision 8641
1955SN/A# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 2955SN/A# Copyright (c) 2009 The Hewlett-Packard Development Company 37816Ssteve.reinhardt@amd.com# All rights reserved. 45871Snate@binkert.org# 51762SN/A# Redistribution and use in source and binary forms, with or without 6955SN/A# modification, are permitted provided that the following conditions are 7955SN/A# met: redistributions of source code must retain the above copyright 8955SN/A# notice, this list of conditions and the following disclaimer; 9955SN/A# redistributions in binary form must reproduce the above copyright 10955SN/A# notice, this list of conditions and the following disclaimer in the 11955SN/A# documentation and/or other materials provided with the distribution; 12955SN/A# neither the name of the copyright holders nor the names of its 13955SN/A# contributors may be used to endorse or promote products derived from 14955SN/A# this software without specific prior written permission. 15955SN/A# 16955SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17955SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A 28955SN/Afrom m5.util import orderdict 29955SN/A 302665Ssaidi@eecs.umich.edufrom slicc.symbols.Symbol import Symbol 312665Ssaidi@eecs.umich.edufrom slicc.symbols.Var import Var 325863Snate@binkert.orgimport slicc.generate.html as html 33955SN/Aimport re 34955SN/A 35955SN/Apython_class_map = {"int": "Int", 36955SN/A "std::string": "String", 37955SN/A "bool": "Bool", 388878Ssteve.reinhardt@amd.com "CacheMemory": "RubyCache", 392632Sstever@eecs.umich.edu "WireBuffer": "RubyWireBuffer", 408878Ssteve.reinhardt@amd.com "Sequencer": "RubySequencer", 412632Sstever@eecs.umich.edu "DirectoryMemory": "RubyDirectoryMemory", 42955SN/A "MemoryControl": "RubyMemoryControl", 438878Ssteve.reinhardt@amd.com "DMASequencer": "DMASequencer" 442632Sstever@eecs.umich.edu } 452761Sstever@eecs.umich.edu 462632Sstever@eecs.umich.educlass StateMachine(Symbol): 472632Sstever@eecs.umich.edu def __init__(self, symtab, ident, location, pairs, config_parameters): 482632Sstever@eecs.umich.edu super(StateMachine, self).__init__(symtab, ident, location, pairs) 492761Sstever@eecs.umich.edu self.table = None 502761Sstever@eecs.umich.edu self.config_parameters = config_parameters 512761Sstever@eecs.umich.edu 528878Ssteve.reinhardt@amd.com for param in config_parameters: 538878Ssteve.reinhardt@amd.com if param.pointer: 542761Sstever@eecs.umich.edu var = Var(symtab, param.name, location, param.type_ast.type, 552761Sstever@eecs.umich.edu "(*m_%s_ptr)" % param.name, {}, self) 562761Sstever@eecs.umich.edu else: 572761Sstever@eecs.umich.edu var = Var(symtab, param.name, location, param.type_ast.type, 582761Sstever@eecs.umich.edu "m_%s" % param.name, {}, self) 598878Ssteve.reinhardt@amd.com self.symtab.registerSym(param.name, var) 608878Ssteve.reinhardt@amd.com 612632Sstever@eecs.umich.edu self.states = orderdict() 622632Sstever@eecs.umich.edu self.events = orderdict() 638878Ssteve.reinhardt@amd.com self.actions = orderdict() 648878Ssteve.reinhardt@amd.com self.transitions = [] 652632Sstever@eecs.umich.edu self.in_ports = [] 66955SN/A self.functions = [] 67955SN/A self.objects = [] 68955SN/A self.TBEType = None 695863Snate@binkert.org self.EntryType = None 705863Snate@binkert.org 715863Snate@binkert.org self.message_buffer_names = [] 725863Snate@binkert.org 735863Snate@binkert.org def __repr__(self): 745863Snate@binkert.org return "[StateMachine: %s]" % self.ident 755863Snate@binkert.org 765863Snate@binkert.org def addState(self, state): 775863Snate@binkert.org assert self.table is None 785863Snate@binkert.org self.states[state.ident] = state 795863Snate@binkert.org 808878Ssteve.reinhardt@amd.com def addEvent(self, event): 815863Snate@binkert.org assert self.table is None 825863Snate@binkert.org self.events[event.ident] = event 835863Snate@binkert.org 845863Snate@binkert.org def addAction(self, action): 855863Snate@binkert.org assert self.table is None 865863Snate@binkert.org 875863Snate@binkert.org # Check for duplicate action 885863Snate@binkert.org for other in self.actions.itervalues(): 895863Snate@binkert.org if action.ident == other.ident: 905863Snate@binkert.org action.warning("Duplicate action definition: %s" % action.ident) 915863Snate@binkert.org action.error("Duplicate action definition: %s" % action.ident) 925863Snate@binkert.org if action.short == other.short: 935863Snate@binkert.org other.warning("Duplicate action shorthand: %s" % other.ident) 945863Snate@binkert.org other.warning(" shorthand = %s" % other.short) 955863Snate@binkert.org action.warning("Duplicate action shorthand: %s" % action.ident) 968878Ssteve.reinhardt@amd.com action.error(" shorthand = %s" % action.short) 975863Snate@binkert.org 985863Snate@binkert.org self.actions[action.ident] = action 995863Snate@binkert.org 1006654Snate@binkert.org def addTransition(self, trans): 101955SN/A assert self.table is None 1025396Ssaidi@eecs.umich.edu self.transitions.append(trans) 1035863Snate@binkert.org 1045863Snate@binkert.org def addInPort(self, var): 1054202Sbinkertn@umich.edu self.in_ports.append(var) 1065863Snate@binkert.org 1075863Snate@binkert.org def addFunc(self, func): 1085863Snate@binkert.org # register func in the symbol table 1095863Snate@binkert.org self.symtab.registerSym(str(func), func) 110955SN/A self.functions.append(func) 1116654Snate@binkert.org 1125273Sstever@gmail.com def addObject(self, obj): 1135871Snate@binkert.org self.objects.append(obj) 1145273Sstever@gmail.com 1156655Snate@binkert.org def addType(self, type): 1168878Ssteve.reinhardt@amd.com type_ident = '%s' % type.c_ident 1176655Snate@binkert.org 1186655Snate@binkert.org if type_ident == "%s_TBE" %self.ident: 1199219Spower.jg@gmail.com if self.TBEType != None: 1206655Snate@binkert.org self.error("Multiple Transaction Buffer types in a " \ 1215871Snate@binkert.org "single machine."); 1226654Snate@binkert.org self.TBEType = type 1238947Sandreas.hansson@arm.com 1245396Ssaidi@eecs.umich.edu elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 1258120Sgblack@eecs.umich.edu if self.EntryType != None: 1268120Sgblack@eecs.umich.edu self.error("Multiple AbstractCacheEntry types in a " \ 1278120Sgblack@eecs.umich.edu "single machine."); 1288120Sgblack@eecs.umich.edu self.EntryType = type 1298120Sgblack@eecs.umich.edu 1308120Sgblack@eecs.umich.edu # Needs to be called before accessing the table 1318120Sgblack@eecs.umich.edu def buildTable(self): 1328120Sgblack@eecs.umich.edu assert self.table is None 1338879Ssteve.reinhardt@amd.com 1348879Ssteve.reinhardt@amd.com table = {} 1358879Ssteve.reinhardt@amd.com 1368879Ssteve.reinhardt@amd.com for trans in self.transitions: 1378879Ssteve.reinhardt@amd.com # Track which actions we touch so we know if we use them 1388879Ssteve.reinhardt@amd.com # all -- really this should be done for all symbols as 1398879Ssteve.reinhardt@amd.com # part of the symbol table, then only trigger it for 1408879Ssteve.reinhardt@amd.com # Actions, States, Events, etc. 1418879Ssteve.reinhardt@amd.com 1428879Ssteve.reinhardt@amd.com for action in trans.actions: 1438879Ssteve.reinhardt@amd.com action.used = True 1448879Ssteve.reinhardt@amd.com 1458879Ssteve.reinhardt@amd.com index = (trans.state, trans.event) 1468120Sgblack@eecs.umich.edu if index in table: 1478120Sgblack@eecs.umich.edu table[index].warning("Duplicate transition: %s" % table[index]) 1488120Sgblack@eecs.umich.edu trans.error("Duplicate transition: %s" % trans) 1498120Sgblack@eecs.umich.edu table[index] = trans 1508120Sgblack@eecs.umich.edu 1518120Sgblack@eecs.umich.edu # Look at all actions to make sure we used them all 1528120Sgblack@eecs.umich.edu for action in self.actions.itervalues(): 1538120Sgblack@eecs.umich.edu if not action.used: 1548120Sgblack@eecs.umich.edu error_msg = "Unused action: %s" % action.ident 1558120Sgblack@eecs.umich.edu if "desc" in action: 1568120Sgblack@eecs.umich.edu error_msg += ", " + action.desc 1578120Sgblack@eecs.umich.edu action.warning(error_msg) 1588120Sgblack@eecs.umich.edu self.table = table 1598120Sgblack@eecs.umich.edu 1608879Ssteve.reinhardt@amd.com def writeCodeFiles(self, path): 1618879Ssteve.reinhardt@amd.com self.printControllerPython(path) 1628879Ssteve.reinhardt@amd.com self.printControllerHH(path) 1638879Ssteve.reinhardt@amd.com self.printControllerCC(path) 1648879Ssteve.reinhardt@amd.com self.printCSwitch(path) 1658879Ssteve.reinhardt@amd.com self.printCWakeup(path) 1668879Ssteve.reinhardt@amd.com self.printProfilerCC(path) 1678879Ssteve.reinhardt@amd.com self.printProfilerHH(path) 1689227Sandreas.hansson@arm.com self.printProfileDumperCC(path) 1699227Sandreas.hansson@arm.com self.printProfileDumperHH(path) 1708879Ssteve.reinhardt@amd.com 1718879Ssteve.reinhardt@amd.com def printControllerPython(self, path): 1728879Ssteve.reinhardt@amd.com code = self.symtab.codeFormatter() 1738879Ssteve.reinhardt@amd.com ident = self.ident 1748120Sgblack@eecs.umich.edu py_ident = "%s_Controller" % ident 1758947Sandreas.hansson@arm.com c_ident = "%s_Controller" % self.ident 1767816Ssteve.reinhardt@amd.com code(''' 1775871Snate@binkert.orgfrom m5.params import * 1785871Snate@binkert.orgfrom m5.SimObject import SimObject 1796121Snate@binkert.orgfrom Controller import RubyController 1805871Snate@binkert.org 1815871Snate@binkert.orgclass $py_ident(RubyController): 1829119Sandreas.hansson@arm.com type = '$py_ident' 1839119Sandreas.hansson@arm.com''') 184955SN/A code.indent() 1855871Snate@binkert.org for param in self.config_parameters: 1865871Snate@binkert.org dflt_str = '' 1875871Snate@binkert.org if param.default is not None: 1885871Snate@binkert.org dflt_str = str(param.default) + ', ' 189955SN/A if python_class_map.has_key(param.type_ast.type.c_ident): 1906121Snate@binkert.org python_type = python_class_map[param.type_ast.type.c_ident] 1918881Smarc.orr@gmail.com code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")') 1926121Snate@binkert.org else: 1936121Snate@binkert.org self.error("Unknown c++ to python class conversion for c++ " \ 1941533SN/A "type: '%s'. Please update the python_class_map " \ 1959239Sandreas.hansson@arm.com "in StateMachine.py", param.type_ast.type.c_ident) 1969239Sandreas.hansson@arm.com code.dedent() 1979239Sandreas.hansson@arm.com code.write(path, '%s.py' % py_ident) 1989239Sandreas.hansson@arm.com 1999239Sandreas.hansson@arm.com 2009239Sandreas.hansson@arm.com def printControllerHH(self, path): 2019239Sandreas.hansson@arm.com '''Output the method declarations for the class declaration''' 2029239Sandreas.hansson@arm.com code = self.symtab.codeFormatter() 2039239Sandreas.hansson@arm.com ident = self.ident 2049239Sandreas.hansson@arm.com c_ident = "%s_Controller" % self.ident 2059239Sandreas.hansson@arm.com 2069239Sandreas.hansson@arm.com self.message_buffer_names = [] 2076655Snate@binkert.org 2086655Snate@binkert.org code(''' 2096655Snate@binkert.org/** \\file $c_ident.hh 2106655Snate@binkert.org * 2115871Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 2125871Snate@binkert.org * Created by slicc definition of Module "${{self.short}}" 2135863Snate@binkert.org */ 2145871Snate@binkert.org 2158878Ssteve.reinhardt@amd.com#ifndef __${ident}_CONTROLLER_HH__ 2165871Snate@binkert.org#define __${ident}_CONTROLLER_HH__ 2175871Snate@binkert.org 2185871Snate@binkert.org#include <iostream> 2195863Snate@binkert.org#include <sstream> 2206121Snate@binkert.org#include <string> 2215863Snate@binkert.org 2225871Snate@binkert.org#include "mem/protocol/${ident}_ProfileDumper.hh" 2238336Ssteve.reinhardt@amd.com#include "mem/protocol/${ident}_Profiler.hh" 2248336Ssteve.reinhardt@amd.com#include "mem/protocol/TransitionResult.hh" 2258336Ssteve.reinhardt@amd.com#include "mem/protocol/Types.hh" 2268336Ssteve.reinhardt@amd.com#include "mem/ruby/common/Consumer.hh" 2274678Snate@binkert.org#include "mem/ruby/common/Global.hh" 2288336Ssteve.reinhardt@amd.com#include "mem/ruby/slicc_interface/AbstractController.hh" 2298336Ssteve.reinhardt@amd.com#include "params/$c_ident.hh" 2308336Ssteve.reinhardt@amd.com''') 2314678Snate@binkert.org 2324678Snate@binkert.org seen_types = set() 2334678Snate@binkert.org for var in self.objects: 2344678Snate@binkert.org if var.type.ident not in seen_types and not var.type.isPrimitive: 2357827Snate@binkert.org code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 2367827Snate@binkert.org seen_types.add(var.type.ident) 2378336Ssteve.reinhardt@amd.com 2384678Snate@binkert.org # for adding information to the protocol debug trace 2398336Ssteve.reinhardt@amd.com code(''' 2408336Ssteve.reinhardt@amd.comextern std::stringstream ${ident}_transitionComment; 2418336Ssteve.reinhardt@amd.com 2428336Ssteve.reinhardt@amd.comclass $c_ident : public AbstractController 2438336Ssteve.reinhardt@amd.com{ 2448336Ssteve.reinhardt@amd.com// the coherence checker needs to call isBlockExclusive() and isBlockShared() 2455871Snate@binkert.org// making the Chip a friend class is an easy way to do this for now 2465871Snate@binkert.org 2478336Ssteve.reinhardt@amd.compublic: 2488336Ssteve.reinhardt@amd.com typedef ${c_ident}Params Params; 2498336Ssteve.reinhardt@amd.com $c_ident(const Params *p); 2508336Ssteve.reinhardt@amd.com static int getNumControllers(); 2518336Ssteve.reinhardt@amd.com void init(); 2525871Snate@binkert.org MessageBuffer* getMandatoryQueue() const; 2538336Ssteve.reinhardt@amd.com const int & getVersion() const; 2548336Ssteve.reinhardt@amd.com const std::string toString() const; 2558336Ssteve.reinhardt@amd.com const std::string getName() const; 2568336Ssteve.reinhardt@amd.com const MachineType getMachineType() const; 2578336Ssteve.reinhardt@amd.com void stallBuffer(MessageBuffer* buf, Address addr); 2584678Snate@binkert.org void wakeUpBuffers(Address addr); 2595871Snate@binkert.org void wakeUpAllBuffers(); 2604678Snate@binkert.org void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; } 2618336Ssteve.reinhardt@amd.com void print(std::ostream& out) const; 2628336Ssteve.reinhardt@amd.com void printConfig(std::ostream& out) const; 2638336Ssteve.reinhardt@amd.com void wakeup(); 2648336Ssteve.reinhardt@amd.com void printStats(std::ostream& out) const; 2658336Ssteve.reinhardt@amd.com void clearStats(); 2668336Ssteve.reinhardt@amd.com void blockOnQueue(Address addr, MessageBuffer* port); 2678336Ssteve.reinhardt@amd.com void unblock(Address addr); 2688336Ssteve.reinhardt@amd.com 2698336Ssteve.reinhardt@amd.comprivate: 2708336Ssteve.reinhardt@amd.com''') 2718336Ssteve.reinhardt@amd.com 2728336Ssteve.reinhardt@amd.com code.indent() 2738336Ssteve.reinhardt@amd.com # added by SS 2748336Ssteve.reinhardt@amd.com for param in self.config_parameters: 2758336Ssteve.reinhardt@amd.com if param.pointer: 2768336Ssteve.reinhardt@amd.com code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 2778336Ssteve.reinhardt@amd.com else: 2785871Snate@binkert.org code('${{param.type_ast.type}} m_${{param.ident}};') 2796121Snate@binkert.org 280955SN/A code(''' 281955SN/Aint m_number_of_TBEs; 2822632Sstever@eecs.umich.edu 2832632Sstever@eecs.umich.eduTransitionResult doTransition(${ident}_Event event, 284955SN/A''') 285955SN/A 286955SN/A if self.EntryType != None: 287955SN/A code(''' 2888878Ssteve.reinhardt@amd.com ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 289955SN/A''') 2902632Sstever@eecs.umich.edu if self.TBEType != None: 2912632Sstever@eecs.umich.edu code(''' 2922632Sstever@eecs.umich.edu ${{self.TBEType.c_ident}}* m_tbe_ptr, 2932632Sstever@eecs.umich.edu''') 2942632Sstever@eecs.umich.edu 2952632Sstever@eecs.umich.edu code(''' 2962632Sstever@eecs.umich.edu const Address& addr); 2978268Ssteve.reinhardt@amd.com 2988268Ssteve.reinhardt@amd.comTransitionResult doTransitionWorker(${ident}_Event event, 2998268Ssteve.reinhardt@amd.com ${ident}_State state, 3008268Ssteve.reinhardt@amd.com ${ident}_State& next_state, 3018268Ssteve.reinhardt@amd.com''') 3028268Ssteve.reinhardt@amd.com 3038268Ssteve.reinhardt@amd.com if self.TBEType != None: 3042632Sstever@eecs.umich.edu code(''' 3052632Sstever@eecs.umich.edu ${{self.TBEType.c_ident}}*& m_tbe_ptr, 3062632Sstever@eecs.umich.edu''') 3072632Sstever@eecs.umich.edu if self.EntryType != None: 3088268Ssteve.reinhardt@amd.com code(''' 3092632Sstever@eecs.umich.edu ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 3108268Ssteve.reinhardt@amd.com''') 3118268Ssteve.reinhardt@amd.com 3128268Ssteve.reinhardt@amd.com code(''' 3138268Ssteve.reinhardt@amd.com const Address& addr); 3143718Sstever@eecs.umich.edu 3152634Sstever@eecs.umich.edustd::string m_name; 3162634Sstever@eecs.umich.eduint m_transitions_per_cycle; 3175863Snate@binkert.orgint m_buffer_size; 3182638Sstever@eecs.umich.eduint m_recycle_latency; 3198268Ssteve.reinhardt@amd.comstd::map<std::string, std::string> m_cfg; 3202632Sstever@eecs.umich.eduNodeID m_version; 3212632Sstever@eecs.umich.eduNetwork* m_net_ptr; 3222632Sstever@eecs.umich.eduMachineID m_machineID; 3232632Sstever@eecs.umich.edubool m_is_blocking; 3242632Sstever@eecs.umich.edustd::map<Address, MessageBuffer*> m_block_map; 3251858SN/Atypedef std::vector<MessageBuffer*> MsgVecType; 3263716Sstever@eecs.umich.edutypedef m5::hash_map< Address, MsgVecType* > WaitingBufType; 3272638Sstever@eecs.umich.eduWaitingBufType m_waiting_buffers; 3282638Sstever@eecs.umich.eduint m_max_in_port_rank; 3292638Sstever@eecs.umich.eduint m_cur_in_port_rank; 3302638Sstever@eecs.umich.edustatic ${ident}_ProfileDumper s_profileDumper; 3312638Sstever@eecs.umich.edu${ident}_Profiler m_profiler; 3322638Sstever@eecs.umich.edustatic int m_num_controllers; 3332638Sstever@eecs.umich.edu 3345863Snate@binkert.org// Internal functions 3355863Snate@binkert.org''') 3365863Snate@binkert.org 337955SN/A for func in self.functions: 3385341Sstever@gmail.com proto = func.prototype 3395341Sstever@gmail.com if proto: 3405863Snate@binkert.org code('$proto') 3417756SAli.Saidi@ARM.com 3425341Sstever@gmail.com if self.EntryType != None: 3436121Snate@binkert.org code(''' 3444494Ssaidi@eecs.umich.edu 3456121Snate@binkert.org// Set and Reset for cache_entry variable 3461105SN/Avoid set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 3472667Sstever@eecs.umich.eduvoid unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 3482667Sstever@eecs.umich.edu''') 3492667Sstever@eecs.umich.edu 3502667Sstever@eecs.umich.edu if self.TBEType != None: 3516121Snate@binkert.org code(''' 3522667Sstever@eecs.umich.edu 3535341Sstever@gmail.com// Set and Reset for tbe variable 3545863Snate@binkert.orgvoid set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 3555341Sstever@gmail.comvoid unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 3565341Sstever@gmail.com''') 3575341Sstever@gmail.com 3588120Sgblack@eecs.umich.edu code(''' 3595341Sstever@gmail.com 3608120Sgblack@eecs.umich.edu// Actions 3615341Sstever@gmail.com''') 3628120Sgblack@eecs.umich.edu if self.TBEType != None and self.EntryType != None: 3636121Snate@binkert.org for action in self.actions.itervalues(): 3646121Snate@binkert.org code('/** \\brief ${{action.desc}} */') 3658980Ssteve.reinhardt@amd.com code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 3665397Ssaidi@eecs.umich.edu elif self.TBEType != None: 3675397Ssaidi@eecs.umich.edu for action in self.actions.itervalues(): 3687727SAli.Saidi@ARM.com code('/** \\brief ${{action.desc}} */') 3698268Ssteve.reinhardt@amd.com code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr);') 3706168Snate@binkert.org elif self.EntryType != None: 3715341Sstever@gmail.com for action in self.actions.itervalues(): 3728120Sgblack@eecs.umich.edu code('/** \\brief ${{action.desc}} */') 3738120Sgblack@eecs.umich.edu code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 3748120Sgblack@eecs.umich.edu else: 3756814Sgblack@eecs.umich.edu for action in self.actions.itervalues(): 3765863Snate@binkert.org code('/** \\brief ${{action.desc}} */') 3778120Sgblack@eecs.umich.edu code('void ${{action.ident}}(const Address& addr);') 3785341Sstever@gmail.com 3795863Snate@binkert.org # the controller internal variables 3808268Ssteve.reinhardt@amd.com code(''' 3816121Snate@binkert.org 3826121Snate@binkert.org// Objects 3838268Ssteve.reinhardt@amd.com''') 3845742Snate@binkert.org for var in self.objects: 3855742Snate@binkert.org th = var.get("template_hack", "") 3865341Sstever@gmail.com code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') 3875742Snate@binkert.org 3885742Snate@binkert.org if var.type.ident == "MessageBuffer": 3895341Sstever@gmail.com self.message_buffer_names.append("m_%s_ptr" % var.c_ident) 3906017Snate@binkert.org 3916121Snate@binkert.org code.dedent() 3926017Snate@binkert.org code('};') 3937816Ssteve.reinhardt@amd.com code('#endif // __${ident}_CONTROLLER_H__') 3947756SAli.Saidi@ARM.com code.write(path, '%s.hh' % c_ident) 3957756SAli.Saidi@ARM.com 3967756SAli.Saidi@ARM.com def printControllerCC(self, path): 3977756SAli.Saidi@ARM.com '''Output the actions for performing the actions''' 3987756SAli.Saidi@ARM.com 3997756SAli.Saidi@ARM.com code = self.symtab.codeFormatter() 4007756SAli.Saidi@ARM.com ident = self.ident 4017756SAli.Saidi@ARM.com c_ident = "%s_Controller" % self.ident 4027816Ssteve.reinhardt@amd.com 4037816Ssteve.reinhardt@amd.com code(''' 4047816Ssteve.reinhardt@amd.com/** \\file $c_ident.cc 4057816Ssteve.reinhardt@amd.com * 4067816Ssteve.reinhardt@amd.com * Auto generated C++ code started by $__file__:$__line__ 4077816Ssteve.reinhardt@amd.com * Created by slicc definition of Module "${{self.short}}" 4087816Ssteve.reinhardt@amd.com */ 4097816Ssteve.reinhardt@amd.com 4107816Ssteve.reinhardt@amd.com#include <cassert> 4117816Ssteve.reinhardt@amd.com#include <sstream> 4127756SAli.Saidi@ARM.com#include <string> 4137816Ssteve.reinhardt@amd.com 4147816Ssteve.reinhardt@amd.com#include "base/compiler.hh" 4157816Ssteve.reinhardt@amd.com#include "base/cprintf.hh" 4167816Ssteve.reinhardt@amd.com#include "debug/RubyGenerated.hh" 4177816Ssteve.reinhardt@amd.com#include "debug/RubySlicc.hh" 4187816Ssteve.reinhardt@amd.com#include "mem/protocol/${ident}_Controller.hh" 4197816Ssteve.reinhardt@amd.com#include "mem/protocol/${ident}_Event.hh" 4207816Ssteve.reinhardt@amd.com#include "mem/protocol/${ident}_State.hh" 4217816Ssteve.reinhardt@amd.com#include "mem/protocol/Types.hh" 4227816Ssteve.reinhardt@amd.com#include "mem/ruby/common/Global.hh" 4237816Ssteve.reinhardt@amd.com#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 4247816Ssteve.reinhardt@amd.com#include "mem/ruby/system/System.hh" 4257816Ssteve.reinhardt@amd.com 4267816Ssteve.reinhardt@amd.comusing namespace std; 4277816Ssteve.reinhardt@amd.com''') 4287816Ssteve.reinhardt@amd.com 4297816Ssteve.reinhardt@amd.com # include object classes 4307816Ssteve.reinhardt@amd.com seen_types = set() 4317816Ssteve.reinhardt@amd.com for var in self.objects: 4327816Ssteve.reinhardt@amd.com if var.type.ident not in seen_types and not var.type.isPrimitive: 4337816Ssteve.reinhardt@amd.com code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 4347816Ssteve.reinhardt@amd.com seen_types.add(var.type.ident) 4357816Ssteve.reinhardt@amd.com 4367816Ssteve.reinhardt@amd.com code(''' 4377816Ssteve.reinhardt@amd.com$c_ident * 4387816Ssteve.reinhardt@amd.com${c_ident}Params::create() 4397816Ssteve.reinhardt@amd.com{ 4407816Ssteve.reinhardt@amd.com return new $c_ident(this); 4417816Ssteve.reinhardt@amd.com} 4427816Ssteve.reinhardt@amd.com 4437816Ssteve.reinhardt@amd.comint $c_ident::m_num_controllers = 0; 4447816Ssteve.reinhardt@amd.com${ident}_ProfileDumper $c_ident::s_profileDumper; 4457816Ssteve.reinhardt@amd.com 4467816Ssteve.reinhardt@amd.com// for adding information to the protocol debug trace 4477816Ssteve.reinhardt@amd.comstringstream ${ident}_transitionComment; 4487816Ssteve.reinhardt@amd.com#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 4497816Ssteve.reinhardt@amd.com 4507816Ssteve.reinhardt@amd.com/** \\brief constructor */ 4517816Ssteve.reinhardt@amd.com$c_ident::$c_ident(const Params *p) 4527816Ssteve.reinhardt@amd.com : AbstractController(p) 4537816Ssteve.reinhardt@amd.com{ 4547816Ssteve.reinhardt@amd.com m_version = p->version; 4557816Ssteve.reinhardt@amd.com m_transitions_per_cycle = p->transitions_per_cycle; 4567816Ssteve.reinhardt@amd.com m_buffer_size = p->buffer_size; 4577816Ssteve.reinhardt@amd.com m_recycle_latency = p->recycle_latency; 4587816Ssteve.reinhardt@amd.com m_number_of_TBEs = p->number_of_TBEs; 4597816Ssteve.reinhardt@amd.com m_is_blocking = false; 4607816Ssteve.reinhardt@amd.com m_name = "${ident}"; 4617816Ssteve.reinhardt@amd.com''') 4627816Ssteve.reinhardt@amd.com # 4637816Ssteve.reinhardt@amd.com # max_port_rank is used to size vectors and thus should be one plus the 4647816Ssteve.reinhardt@amd.com # largest port rank 4657816Ssteve.reinhardt@amd.com # 4667816Ssteve.reinhardt@amd.com max_port_rank = self.in_ports[0].pairs["max_port_rank"] + 1 4677816Ssteve.reinhardt@amd.com code(' m_max_in_port_rank = $max_port_rank;') 4687816Ssteve.reinhardt@amd.com code.indent() 4697816Ssteve.reinhardt@amd.com 4707816Ssteve.reinhardt@amd.com # 4717816Ssteve.reinhardt@amd.com # After initializing the universal machine parameters, initialize the 4727816Ssteve.reinhardt@amd.com # this machines config parameters. Also detemine if these configuration 4737816Ssteve.reinhardt@amd.com # params include a sequencer. This information will be used later for 4748947Sandreas.hansson@arm.com # contecting the sequencer back to the L1 cache controller. 4758947Sandreas.hansson@arm.com # 4767756SAli.Saidi@ARM.com contains_dma_sequencer = False 4778120Sgblack@eecs.umich.edu sequencers = [] 4787756SAli.Saidi@ARM.com for param in self.config_parameters: 4797756SAli.Saidi@ARM.com if param.name == "dma_sequencer": 4807756SAli.Saidi@ARM.com contains_dma_sequencer = True 4817756SAli.Saidi@ARM.com elif re.compile("sequencer").search(param.name): 4827816Ssteve.reinhardt@amd.com sequencers.append(param.name) 4837816Ssteve.reinhardt@amd.com if param.pointer: 4847816Ssteve.reinhardt@amd.com code('m_${{param.name}}_ptr = p->${{param.name}};') 4857816Ssteve.reinhardt@amd.com else: 4867816Ssteve.reinhardt@amd.com code('m_${{param.name}} = p->${{param.name}};') 4877816Ssteve.reinhardt@amd.com 4887816Ssteve.reinhardt@amd.com # 4897816Ssteve.reinhardt@amd.com # For the l1 cache controller, add the special atomic support which 4907816Ssteve.reinhardt@amd.com # includes passing the sequencer a pointer to the controller. 4917816Ssteve.reinhardt@amd.com # 4927756SAli.Saidi@ARM.com if self.ident == "L1Cache": 4937756SAli.Saidi@ARM.com if not sequencers: 4949227Sandreas.hansson@arm.com self.error("The L1Cache controller must include the sequencer " \ 4959227Sandreas.hansson@arm.com "configuration parameter") 4969227Sandreas.hansson@arm.com 4979227Sandreas.hansson@arm.com for seq in sequencers: 4986654Snate@binkert.org code(''' 4996654Snate@binkert.orgm_${{seq}}_ptr->setController(this); 5005871Snate@binkert.org ''') 5016121Snate@binkert.org # 5026121Snate@binkert.org # For the DMA controller, pass the sequencer a pointer to the 5036121Snate@binkert.org # controller. 5048946Sandreas.hansson@arm.com # 5058737Skoansin.tan@gmail.com if self.ident == "DMA": 5063940Ssaidi@eecs.umich.edu if not contains_dma_sequencer: 5073918Ssaidi@eecs.umich.edu self.error("The DMA controller must include the sequencer " \ 5083918Ssaidi@eecs.umich.edu "configuration parameter") 5091858SN/A 5106121Snate@binkert.org code(''' 5117739Sgblack@eecs.umich.edum_dma_sequencer_ptr->setController(this); 5127739Sgblack@eecs.umich.edu''') 5136143Snate@binkert.org 5147618SAli.Saidi@arm.com code('m_num_controllers++;') 5157618SAli.Saidi@arm.com for var in self.objects: 5167618SAli.Saidi@arm.com if var.ident.find("mandatoryQueue") >= 0: 5177618SAli.Saidi@arm.com code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();') 5188614Sgblack@eecs.umich.edu 5197618SAli.Saidi@arm.com code.dedent() 5207618SAli.Saidi@arm.com code(''' 5217618SAli.Saidi@arm.com} 5227739Sgblack@eecs.umich.edu 5239224Sandreas.hansson@arm.comvoid 5249224Sandreas.hansson@arm.com$c_ident::init() 5259224Sandreas.hansson@arm.com{ 5268946Sandreas.hansson@arm.com MachineType machine_type; 5279227Sandreas.hansson@arm.com int base; 5289227Sandreas.hansson@arm.com 5299227Sandreas.hansson@arm.com m_machineID.type = MachineType_${ident}; 5309227Sandreas.hansson@arm.com m_machineID.num = m_version; 5319227Sandreas.hansson@arm.com 5329227Sandreas.hansson@arm.com // initialize objects 5339227Sandreas.hansson@arm.com m_profiler.setVersion(m_version); 5349227Sandreas.hansson@arm.com s_profileDumper.registerProfiler(&m_profiler); 5359227Sandreas.hansson@arm.com 5369227Sandreas.hansson@arm.com''') 5379227Sandreas.hansson@arm.com 5389227Sandreas.hansson@arm.com code.indent() 5399227Sandreas.hansson@arm.com for var in self.objects: 5409227Sandreas.hansson@arm.com vtype = var.type 5419227Sandreas.hansson@arm.com vid = "m_%s_ptr" % var.c_ident 5429227Sandreas.hansson@arm.com if "network" not in var: 5439227Sandreas.hansson@arm.com # Not a network port object 5449227Sandreas.hansson@arm.com if "primitive" in vtype: 5456121Snate@binkert.org code('$vid = new ${{vtype.c_ident}};') 5463940Ssaidi@eecs.umich.edu if "default" in var: 5476121Snate@binkert.org code('(*$vid) = ${{var["default"]}};') 5487739Sgblack@eecs.umich.edu else: 5497739Sgblack@eecs.umich.edu # Normal Object 5507739Sgblack@eecs.umich.edu # added by SS 5517739Sgblack@eecs.umich.edu if "factory" in var: 5527739Sgblack@eecs.umich.edu code('$vid = ${{var["factory"]}};') 5537739Sgblack@eecs.umich.edu elif var.ident.find("mandatoryQueue") < 0: 5548737Skoansin.tan@gmail.com th = var.get("template_hack", "") 5558737Skoansin.tan@gmail.com expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 5568737Skoansin.tan@gmail.com 5578737Skoansin.tan@gmail.com args = "" 5588737Skoansin.tan@gmail.com if "non_obj" not in vtype and not vtype.isEnumeration: 5598737Skoansin.tan@gmail.com if expr.find("TBETable") >= 0: 5608737Skoansin.tan@gmail.com args = "m_number_of_TBEs" 5618737Skoansin.tan@gmail.com else: 5628737Skoansin.tan@gmail.com args = var.get("constructor_hack", "") 5638737Skoansin.tan@gmail.com 5648737Skoansin.tan@gmail.com code('$expr($args);') 5658737Skoansin.tan@gmail.com 5668737Skoansin.tan@gmail.com code('assert($vid != NULL);') 5678737Skoansin.tan@gmail.com 5688737Skoansin.tan@gmail.com if "default" in var: 5698737Skoansin.tan@gmail.com code('*$vid = ${{var["default"]}}; // Object default') 5708737Skoansin.tan@gmail.com elif "default" in vtype: 5718737Skoansin.tan@gmail.com comment = "Type %s default" % vtype.ident 5728946Sandreas.hansson@arm.com code('*$vid = ${{vtype["default"]}}; // $comment') 5738946Sandreas.hansson@arm.com 5748946Sandreas.hansson@arm.com # Set ordering 5758946Sandreas.hansson@arm.com if "ordered" in var and "trigger_queue" not in var: 5769224Sandreas.hansson@arm.com # A buffer 5779224Sandreas.hansson@arm.com code('$vid->setOrdering(${{var["ordered"]}});') 5788946Sandreas.hansson@arm.com 5798946Sandreas.hansson@arm.com # Set randomization 5803918Ssaidi@eecs.umich.edu if "random" in var: 5819068SAli.Saidi@ARM.com # A buffer 5829068SAli.Saidi@ARM.com code('$vid->setRandomization(${{var["random"]}});') 5839068SAli.Saidi@ARM.com 5849068SAli.Saidi@ARM.com # Set Priority 5859068SAli.Saidi@ARM.com if vtype.isBuffer and \ 5869068SAli.Saidi@ARM.com "rank" in var and "trigger_queue" not in var: 5879068SAli.Saidi@ARM.com code('$vid->setPriority(${{var["rank"]}});') 5889068SAli.Saidi@ARM.com 5899068SAli.Saidi@ARM.com else: 5909068SAli.Saidi@ARM.com # Network port object 5919068SAli.Saidi@ARM.com network = var["network"] 5929068SAli.Saidi@ARM.com ordered = var["ordered"] 5939068SAli.Saidi@ARM.com vnet = var["virtual_network"] 5949068SAli.Saidi@ARM.com vnet_type = var["vnet_type"] 5959068SAli.Saidi@ARM.com 5969068SAli.Saidi@ARM.com assert var.machine is not None 5973918Ssaidi@eecs.umich.edu code(''' 5983918Ssaidi@eecs.umich.edumachine_type = string_to_MachineType("${{var.machine.ident}}"); 5996157Snate@binkert.orgbase = MachineType_base_number(machine_type); 6006157Snate@binkert.org$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type"); 6016157Snate@binkert.org''') 6026157Snate@binkert.org 6035397Ssaidi@eecs.umich.edu code('assert($vid != NULL);') 6045397Ssaidi@eecs.umich.edu 6056121Snate@binkert.org # Set ordering 6066121Snate@binkert.org if "ordered" in var: 6076121Snate@binkert.org # A buffer 6086121Snate@binkert.org code('$vid->setOrdering(${{var["ordered"]}});') 6096121Snate@binkert.org 6106121Snate@binkert.org # Set randomization 6115397Ssaidi@eecs.umich.edu if "random" in var: 6121851SN/A # A buffer 6131851SN/A code('$vid->setRandomization(${{var["random"]}});') 6147739Sgblack@eecs.umich.edu 615955SN/A # Set Priority 6163053Sstever@eecs.umich.edu if "rank" in var: 6176121Snate@binkert.org code('$vid->setPriority(${{var["rank"]}})') 6183053Sstever@eecs.umich.edu 6193053Sstever@eecs.umich.edu # Set buffer size 6203053Sstever@eecs.umich.edu if vtype.isBuffer: 6213053Sstever@eecs.umich.edu code(''' 6223053Sstever@eecs.umich.eduif (m_buffer_size > 0) { 6239072Sandreas.hansson@arm.com $vid->resize(m_buffer_size); 6243053Sstever@eecs.umich.edu} 6254742Sstever@eecs.umich.edu''') 6264742Sstever@eecs.umich.edu 6273053Sstever@eecs.umich.edu # set description (may be overriden later by port def) 6283053Sstever@eecs.umich.edu code(''' 6293053Sstever@eecs.umich.edu$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]"); 6308960Ssteve.reinhardt@amd.com 6316654Snate@binkert.org''') 6323053Sstever@eecs.umich.edu 6333053Sstever@eecs.umich.edu if vtype.isBuffer: 6343053Sstever@eecs.umich.edu if "recycle_latency" in var: 6353053Sstever@eecs.umich.edu code('$vid->setRecycleLatency(${{var["recycle_latency"]}});') 6362667Sstever@eecs.umich.edu else: 6374554Sbinkertn@umich.edu code('$vid->setRecycleLatency(m_recycle_latency);') 6386121Snate@binkert.org 6392667Sstever@eecs.umich.edu 6404554Sbinkertn@umich.edu # Set the queue consumers 6414554Sbinkertn@umich.edu code() 6424554Sbinkertn@umich.edu for port in self.in_ports: 6436121Snate@binkert.org code('${{port.code}}.setConsumer(this);') 6444554Sbinkertn@umich.edu 6454554Sbinkertn@umich.edu # Set the queue descriptions 6464554Sbinkertn@umich.edu code() 6474781Snate@binkert.org for port in self.in_ports: 6484554Sbinkertn@umich.edu code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");') 6494554Sbinkertn@umich.edu 6502667Sstever@eecs.umich.edu # Initialize the transition profiling 6514554Sbinkertn@umich.edu code() 6524554Sbinkertn@umich.edu for trans in self.transitions: 6534554Sbinkertn@umich.edu # Figure out if we stall 6544554Sbinkertn@umich.edu stall = False 6552667Sstever@eecs.umich.edu for action in trans.actions: 6564554Sbinkertn@umich.edu if action.ident == "z_stall": 6572667Sstever@eecs.umich.edu stall = True 6584554Sbinkertn@umich.edu 6596121Snate@binkert.org # Only possible if it is not a 'z' case 6602667Sstever@eecs.umich.edu if not stall: 6615522Snate@binkert.org state = "%s_State_%s" % (self.ident, trans.state.ident) 6625522Snate@binkert.org event = "%s_Event_%s" % (self.ident, trans.event.ident) 6635522Snate@binkert.org code('m_profiler.possibleTransition($state, $event);') 6645522Snate@binkert.org 6655522Snate@binkert.org code.dedent() 6665522Snate@binkert.org code('}') 6675522Snate@binkert.org 6685522Snate@binkert.org has_mandatory_q = False 6695522Snate@binkert.org for port in self.in_ports: 6705522Snate@binkert.org if port.code.find("mandatoryQueue_ptr") >= 0: 6715522Snate@binkert.org has_mandatory_q = True 6725522Snate@binkert.org 6735522Snate@binkert.org if has_mandatory_q: 6745522Snate@binkert.org mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident 6755522Snate@binkert.org else: 6765522Snate@binkert.org mq_ident = "NULL" 6775522Snate@binkert.org 6785522Snate@binkert.org code(''' 6795522Snate@binkert.orgint 6805522Snate@binkert.org$c_ident::getNumControllers() 6815522Snate@binkert.org{ 6825522Snate@binkert.org return m_num_controllers; 6835522Snate@binkert.org} 6845522Snate@binkert.org 6855522Snate@binkert.orgMessageBuffer* 6865522Snate@binkert.org$c_ident::getMandatoryQueue() const 6879255SAndreas.Sandberg@arm.com{ 6889255SAndreas.Sandberg@arm.com return $mq_ident; 6899255SAndreas.Sandberg@arm.com} 6909255SAndreas.Sandberg@arm.com 6919255SAndreas.Sandberg@arm.comconst int & 6929255SAndreas.Sandberg@arm.com$c_ident::getVersion() const 6939255SAndreas.Sandberg@arm.com{ 6949255SAndreas.Sandberg@arm.com return m_version; 6959255SAndreas.Sandberg@arm.com} 6969255SAndreas.Sandberg@arm.com 6979255SAndreas.Sandberg@arm.comconst string 6989255SAndreas.Sandberg@arm.com$c_ident::toString() const 6992638Sstever@eecs.umich.edu{ 7002638Sstever@eecs.umich.edu return "$c_ident"; 7016121Snate@binkert.org} 7023716Sstever@eecs.umich.edu 7035522Snate@binkert.orgconst string 7049255SAndreas.Sandberg@arm.com$c_ident::getName() const 7059255SAndreas.Sandberg@arm.com{ 7069255SAndreas.Sandberg@arm.com return m_name; 7075522Snate@binkert.org} 7085522Snate@binkert.org 7095522Snate@binkert.orgconst MachineType 7105522Snate@binkert.org$c_ident::getMachineType() const 7111858SN/A{ 7129255SAndreas.Sandberg@arm.com return MachineType_${ident}; 7139255SAndreas.Sandberg@arm.com} 7149255SAndreas.Sandberg@arm.com 7155227Ssaidi@eecs.umich.eduvoid 7165227Ssaidi@eecs.umich.edu$c_ident::stallBuffer(MessageBuffer* buf, Address addr) 7175227Ssaidi@eecs.umich.edu{ 7185227Ssaidi@eecs.umich.edu if (m_waiting_buffers.count(addr) == 0) { 7196654Snate@binkert.org MsgVecType* msgVec = new MsgVecType; 7206654Snate@binkert.org msgVec->resize(m_max_in_port_rank, NULL); 7217769SAli.Saidi@ARM.com m_waiting_buffers[addr] = msgVec; 7227769SAli.Saidi@ARM.com } 7237769SAli.Saidi@ARM.com (*(m_waiting_buffers[addr]))[m_cur_in_port_rank] = buf; 7247769SAli.Saidi@ARM.com} 7255227Ssaidi@eecs.umich.edu 7265227Ssaidi@eecs.umich.eduvoid 7275227Ssaidi@eecs.umich.edu$c_ident::wakeUpBuffers(Address addr) 7285204Sstever@gmail.com{ 7295204Sstever@gmail.com if (m_waiting_buffers.count(addr) > 0) { 7305204Sstever@gmail.com // 7315204Sstever@gmail.com // Wake up all possible lower rank (i.e. lower priority) buffers that could 7325204Sstever@gmail.com // be waiting on this message. 7335204Sstever@gmail.com // 7345204Sstever@gmail.com for (int in_port_rank = m_cur_in_port_rank - 1; 7355204Sstever@gmail.com in_port_rank >= 0; 7365204Sstever@gmail.com in_port_rank--) { 7375204Sstever@gmail.com if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) { 7385204Sstever@gmail.com (*(m_waiting_buffers[addr]))[in_port_rank]->reanalyzeMessages(addr); 7395204Sstever@gmail.com } 7405204Sstever@gmail.com } 7415204Sstever@gmail.com delete m_waiting_buffers[addr]; 7425204Sstever@gmail.com m_waiting_buffers.erase(addr); 7435204Sstever@gmail.com } 7445204Sstever@gmail.com} 7456121Snate@binkert.org 7465204Sstever@gmail.comvoid 7473118Sstever@eecs.umich.edu$c_ident::wakeUpAllBuffers() 7483118Sstever@eecs.umich.edu{ 7493118Sstever@eecs.umich.edu // 7503118Sstever@eecs.umich.edu // Wake up all possible buffers that could be waiting on any message. 7513118Sstever@eecs.umich.edu // 7525863Snate@binkert.org 7533118Sstever@eecs.umich.edu std::vector<MsgVecType*> wokeUpMsgVecs; 7545863Snate@binkert.org 7553118Sstever@eecs.umich.edu if(m_waiting_buffers.size() > 0) { 7567457Snate@binkert.org for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin(); 7577457Snate@binkert.org buf_iter != m_waiting_buffers.end(); 7585863Snate@binkert.org ++buf_iter) { 7595863Snate@binkert.org for (MsgVecType::iterator vec_iter = buf_iter->second->begin(); 7605863Snate@binkert.org vec_iter != buf_iter->second->end(); 7615863Snate@binkert.org ++vec_iter) { 7625863Snate@binkert.org if (*vec_iter != NULL) { 7635863Snate@binkert.org (*vec_iter)->reanalyzeAllMessages(); 7645863Snate@binkert.org } 7656003Snate@binkert.org } 7665863Snate@binkert.org wokeUpMsgVecs.push_back(buf_iter->second); 7675863Snate@binkert.org } 7685863Snate@binkert.org 7696120Snate@binkert.org for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin(); 7705863Snate@binkert.org wb_iter != wokeUpMsgVecs.end(); 7715863Snate@binkert.org ++wb_iter) { 7725863Snate@binkert.org delete (*wb_iter); 7738655Sandreas.hansson@arm.com } 7748655Sandreas.hansson@arm.com 7758655Sandreas.hansson@arm.com m_waiting_buffers.clear(); 7768655Sandreas.hansson@arm.com } 7778655Sandreas.hansson@arm.com} 7788655Sandreas.hansson@arm.com 7798655Sandreas.hansson@arm.comvoid 7808655Sandreas.hansson@arm.com$c_ident::blockOnQueue(Address addr, MessageBuffer* port) 7816120Snate@binkert.org{ 7825863Snate@binkert.org m_is_blocking = true; 7836121Snate@binkert.org m_block_map[addr] = port; 7846121Snate@binkert.org} 7855863Snate@binkert.org 7867727SAli.Saidi@ARM.comvoid 7877727SAli.Saidi@ARM.com$c_ident::unblock(Address addr) 7887727SAli.Saidi@ARM.com{ 7897727SAli.Saidi@ARM.com m_block_map.erase(addr); 7907727SAli.Saidi@ARM.com if (m_block_map.size() == 0) { 7917727SAli.Saidi@ARM.com m_is_blocking = false; 7925863Snate@binkert.org } 7933118Sstever@eecs.umich.edu} 7945863Snate@binkert.org 7959239Sandreas.hansson@arm.comvoid 7963118Sstever@eecs.umich.edu$c_ident::print(ostream& out) const 7973118Sstever@eecs.umich.edu{ 7985863Snate@binkert.org out << "[$c_ident " << m_version << "]"; 7995863Snate@binkert.org} 8005863Snate@binkert.org 8015863Snate@binkert.orgvoid 8023118Sstever@eecs.umich.edu$c_ident::printConfig(ostream& out) const 8033483Ssaidi@eecs.umich.edu{ 8043494Ssaidi@eecs.umich.edu out << "$c_ident config: " << m_name << endl; 8053494Ssaidi@eecs.umich.edu out << " version: " << m_version << endl; 8063483Ssaidi@eecs.umich.edu map<string, string>::const_iterator it; 8073483Ssaidi@eecs.umich.edu for (it = m_cfg.begin(); it != m_cfg.end(); it++) 8083483Ssaidi@eecs.umich.edu out << " " << it->first << ": " << it->second << endl; 8093053Sstever@eecs.umich.edu} 8103053Sstever@eecs.umich.edu 8113918Ssaidi@eecs.umich.eduvoid 8123053Sstever@eecs.umich.edu$c_ident::printStats(ostream& out) const 8133053Sstever@eecs.umich.edu{ 8143053Sstever@eecs.umich.edu''') 8153053Sstever@eecs.umich.edu # 8163053Sstever@eecs.umich.edu # Cache and Memory Controllers have specific profilers associated with 8177840Snate@binkert.org # them. Print out these stats before dumping state transition stats. 8187865Sgblack@eecs.umich.edu # 8197865Sgblack@eecs.umich.edu for param in self.config_parameters: 8207865Sgblack@eecs.umich.edu if param.type_ast.type.ident == "CacheMemory" or \ 8217865Sgblack@eecs.umich.edu param.type_ast.type.ident == "DirectoryMemory" or \ 8227865Sgblack@eecs.umich.edu param.type_ast.type.ident == "MemoryControl": 8237840Snate@binkert.org assert(param.pointer) 8249045SAli.Saidi@ARM.com code(' m_${{param.ident}}_ptr->printStats(out);') 8259045SAli.Saidi@ARM.com 8269045SAli.Saidi@ARM.com code(''' 8279045SAli.Saidi@ARM.com if (m_version == 0) { 8289045SAli.Saidi@ARM.com s_profileDumper.dumpStats(out); 8299045SAli.Saidi@ARM.com } 8309071Sandreas.hansson@arm.com} 8319071Sandreas.hansson@arm.com 8329045SAli.Saidi@ARM.comvoid $c_ident::clearStats() { 8337840Snate@binkert.org''') 8347840Snate@binkert.org # 8357840Snate@binkert.org # Cache and Memory Controllers have specific profilers associated with 8361858SN/A # them. These stats must be cleared too. 8371858SN/A # 8381858SN/A for param in self.config_parameters: 8391858SN/A if param.type_ast.type.ident == "CacheMemory" or \ 8401858SN/A param.type_ast.type.ident == "MemoryControl": 8411858SN/A assert(param.pointer) 8425863Snate@binkert.org code(' m_${{param.ident}}_ptr->clearStats();') 8435863Snate@binkert.org 8445863Snate@binkert.org code(''' 8455863Snate@binkert.org m_profiler.clearStats(); 8466121Snate@binkert.org} 8471858SN/A''') 8485863Snate@binkert.org 8495863Snate@binkert.org if self.EntryType != None: 8505863Snate@binkert.org code(''' 8515863Snate@binkert.org 8525863Snate@binkert.org// Set and Reset for cache_entry variable 8532139SN/Avoid 8544202Sbinkertn@umich.edu$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 8554202Sbinkertn@umich.edu{ 8562139SN/A m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 8576994Snate@binkert.org} 8586994Snate@binkert.org 8596994Snate@binkert.orgvoid 8606994Snate@binkert.org$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 8616994Snate@binkert.org{ 8626994Snate@binkert.org m_cache_entry_ptr = 0; 8636994Snate@binkert.org} 8646994Snate@binkert.org''') 8656994Snate@binkert.org 8666994Snate@binkert.org if self.TBEType != None: 8676994Snate@binkert.org code(''' 8686994Snate@binkert.org 8696994Snate@binkert.org// Set and Reset for tbe variable 8706994Snate@binkert.orgvoid 8716994Snate@binkert.org$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 8726994Snate@binkert.org{ 8736994Snate@binkert.org m_tbe_ptr = m_new_tbe; 8746994Snate@binkert.org} 8756994Snate@binkert.org 8766994Snate@binkert.orgvoid 8776994Snate@binkert.org$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 8786994Snate@binkert.org{ 8796994Snate@binkert.org m_tbe_ptr = NULL; 8806994Snate@binkert.org} 8816994Snate@binkert.org''') 8826994Snate@binkert.org 8836994Snate@binkert.org code(''' 8846994Snate@binkert.org 8852155SN/A// Actions 8865863Snate@binkert.org''') 8871869SN/A if self.TBEType != None and self.EntryType != None: 8881869SN/A for action in self.actions.itervalues(): 8895863Snate@binkert.org if "c_code" not in action: 8905863Snate@binkert.org continue 8914202Sbinkertn@umich.edu 8926108Snate@binkert.org code(''' 8936108Snate@binkert.org/** \\brief ${{action.desc}} */ 8946108Snate@binkert.orgvoid 8956108Snate@binkert.org$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 8969219Spower.jg@gmail.com{ 8979219Spower.jg@gmail.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 8989219Spower.jg@gmail.com ${{action["c_code"]}} 8999219Spower.jg@gmail.com} 9009219Spower.jg@gmail.com 9019219Spower.jg@gmail.com''') 9029219Spower.jg@gmail.com elif self.TBEType != None: 9039219Spower.jg@gmail.com for action in self.actions.itervalues(): 9044202Sbinkertn@umich.edu if "c_code" not in action: 9055863Snate@binkert.org continue 9068474Sgblack@eecs.umich.edu 9078474Sgblack@eecs.umich.edu code(''' 9085742Snate@binkert.org/** \\brief ${{action.desc}} */ 9098268Ssteve.reinhardt@amd.comvoid 9108268Ssteve.reinhardt@amd.com$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr) 9118268Ssteve.reinhardt@amd.com{ 9125742Snate@binkert.org DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9135341Sstever@gmail.com ${{action["c_code"]}} 9148474Sgblack@eecs.umich.edu} 9158474Sgblack@eecs.umich.edu 9165342Sstever@gmail.com''') 9174202Sbinkertn@umich.edu elif self.EntryType != None: 9184202Sbinkertn@umich.edu for action in self.actions.itervalues(): 9194202Sbinkertn@umich.edu if "c_code" not in action: 9205863Snate@binkert.org continue 9215863Snate@binkert.org 9226994Snate@binkert.org code(''' 9236994Snate@binkert.org/** \\brief ${{action.desc}} */ 9246994Snate@binkert.orgvoid 9255863Snate@binkert.org$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 9265863Snate@binkert.org{ 9275863Snate@binkert.org DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9285863Snate@binkert.org ${{action["c_code"]}} 9295863Snate@binkert.org} 9305863Snate@binkert.org 9315863Snate@binkert.org''') 9325863Snate@binkert.org else: 9337840Snate@binkert.org for action in self.actions.itervalues(): 9345863Snate@binkert.org if "c_code" not in action: 9355952Ssaidi@eecs.umich.edu continue 9369219Spower.jg@gmail.com 9379219Spower.jg@gmail.com code(''' 9381869SN/A/** \\brief ${{action.desc}} */ 9391858SN/Avoid 9405863Snate@binkert.org$c_ident::${{action.ident}}(const Address& addr) 9419044SAli.Saidi@ARM.com{ 9429219Spower.jg@gmail.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9439255SAndreas.Sandberg@arm.com ${{action["c_code"]}} 9441858SN/A} 945955SN/A 946955SN/A''') 9471869SN/A for func in self.functions: 9481869SN/A code(func.generateCode()) 9491869SN/A 9501869SN/A code.write(path, "%s.cc" % c_ident) 9511869SN/A 9525863Snate@binkert.org def printCWakeup(self, path): 9535863Snate@binkert.org '''Output the wakeup loop for the events''' 9545863Snate@binkert.org 9551869SN/A code = self.symtab.codeFormatter() 9565863Snate@binkert.org ident = self.ident 9571869SN/A 9585863Snate@binkert.org code(''' 9591869SN/A// Auto generated C++ code started by $__file__:$__line__ 9601869SN/A// ${ident}: ${{self.short}} 9611869SN/A 9621869SN/A#include <cassert> 9638483Sgblack@eecs.umich.edu 9641869SN/A#include "base/misc.hh" 9651869SN/A#include "debug/RubySlicc.hh" 9661869SN/A#include "mem/protocol/${ident}_Controller.hh" 9671869SN/A#include "mem/protocol/${ident}_Event.hh" 9685863Snate@binkert.org#include "mem/protocol/${ident}_State.hh" 9695863Snate@binkert.org#include "mem/protocol/Types.hh" 9701869SN/A#include "mem/ruby/common/Global.hh" 9715863Snate@binkert.org#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 9725863Snate@binkert.org#include "mem/ruby/system/System.hh" 9733356Sbinkertn@umich.edu 9743356Sbinkertn@umich.eduusing namespace std; 9753356Sbinkertn@umich.edu 9763356Sbinkertn@umich.eduvoid 9773356Sbinkertn@umich.edu${ident}_Controller::wakeup() 9784781Snate@binkert.org{ 9795863Snate@binkert.org int counter = 0; 9805863Snate@binkert.org while (true) { 9811869SN/A // Some cases will put us into an infinite loop without this limit 9821869SN/A assert(counter <= m_transitions_per_cycle); 9831869SN/A if (counter == m_transitions_per_cycle) { 9846121Snate@binkert.org // Count how often we are fully utilized 9851869SN/A g_system_ptr->getProfiler()->controllerBusy(m_machineID); 9862638Sstever@eecs.umich.edu 9876121Snate@binkert.org // Wakeup in another cycle and try again 9886121Snate@binkert.org g_eventQueue_ptr->scheduleEvent(this, 1); 9892638Sstever@eecs.umich.edu break; 9905749Scws3k@cs.virginia.edu } 9916121Snate@binkert.org''') 9926121Snate@binkert.org 9935749Scws3k@cs.virginia.edu code.indent() 9941869SN/A code.indent() 9951869SN/A 9963546Sgblack@eecs.umich.edu # InPorts 9973546Sgblack@eecs.umich.edu # 9983546Sgblack@eecs.umich.edu for port in self.in_ports: 9993546Sgblack@eecs.umich.edu code.indent() 10006121Snate@binkert.org code('// ${ident}InPort $port') 10015863Snate@binkert.org if port.pairs.has_key("rank"): 10023546Sgblack@eecs.umich.edu code('m_cur_in_port_rank = ${{port.pairs["rank"]}};') 10033546Sgblack@eecs.umich.edu else: 10043546Sgblack@eecs.umich.edu code('m_cur_in_port_rank = 0;') 10053546Sgblack@eecs.umich.edu code('${{port["c_code_in_port"]}}') 10064781Snate@binkert.org code.dedent() 10074781Snate@binkert.org 10086658Snate@binkert.org code('') 10096658Snate@binkert.org 10104781Snate@binkert.org code.dedent() 10113546Sgblack@eecs.umich.edu code.dedent() 10123546Sgblack@eecs.umich.edu code(''' 10133546Sgblack@eecs.umich.edu break; // If we got this far, we have nothing left todo 10143546Sgblack@eecs.umich.edu } 10157756SAli.Saidi@ARM.com // g_eventQueue_ptr->scheduleEvent(this, 1); 10167816Ssteve.reinhardt@amd.com} 10173546Sgblack@eecs.umich.edu''') 10183546Sgblack@eecs.umich.edu 10193546Sgblack@eecs.umich.edu code.write(path, "%s_Wakeup.cc" % self.ident) 10203546Sgblack@eecs.umich.edu 10214202Sbinkertn@umich.edu def printCSwitch(self, path): 10223546Sgblack@eecs.umich.edu '''Output switch statement for transition table''' 10233546Sgblack@eecs.umich.edu 10243546Sgblack@eecs.umich.edu code = self.symtab.codeFormatter() 1025955SN/A ident = self.ident 1026955SN/A 1027955SN/A code(''' 1028955SN/A// Auto generated C++ code started by $__file__:$__line__ 10295863Snate@binkert.org// ${ident}: ${{self.short}} 10305863Snate@binkert.org 10315343Sstever@gmail.com#include <cassert> 10325343Sstever@gmail.com 10336121Snate@binkert.org#include "base/misc.hh" 10345863Snate@binkert.org#include "base/trace.hh" 10354773Snate@binkert.org#include "debug/ProtocolTrace.hh" 10365863Snate@binkert.org#include "debug/RubyGenerated.hh" 10372632Sstever@eecs.umich.edu#include "mem/protocol/${ident}_Controller.hh" 10385863Snate@binkert.org#include "mem/protocol/${ident}_Event.hh" 10392023SN/A#include "mem/protocol/${ident}_State.hh" 10405863Snate@binkert.org#include "mem/protocol/Types.hh" 10415863Snate@binkert.org#include "mem/ruby/common/Global.hh" 10425863Snate@binkert.org#include "mem/ruby/system/System.hh" 10435863Snate@binkert.org 10445863Snate@binkert.org#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 10455863Snate@binkert.org 10465863Snate@binkert.org#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 10475863Snate@binkert.org#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 10485863Snate@binkert.org 10492632Sstever@eecs.umich.eduTransitionResult 10505863Snate@binkert.org${ident}_Controller::doTransition(${ident}_Event event, 10512023SN/A''') 10522632Sstever@eecs.umich.edu if self.EntryType != None: 10535863Snate@binkert.org code(''' 10545342Sstever@gmail.com ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 10555863Snate@binkert.org''') 10562632Sstever@eecs.umich.edu if self.TBEType != None: 10575863Snate@binkert.org code(''' 10585863Snate@binkert.org ${{self.TBEType.c_ident}}* m_tbe_ptr, 10598267Ssteve.reinhardt@amd.com''') 10608120Sgblack@eecs.umich.edu code(''' 10618267Ssteve.reinhardt@amd.com const Address &addr) 10628267Ssteve.reinhardt@amd.com{ 10638267Ssteve.reinhardt@amd.com''') 10648267Ssteve.reinhardt@amd.com if self.TBEType != None and self.EntryType != None: 10658267Ssteve.reinhardt@amd.com code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 10668267Ssteve.reinhardt@amd.com elif self.TBEType != None: 10678267Ssteve.reinhardt@amd.com code('${ident}_State state = getState(m_tbe_ptr, addr);') 10688267Ssteve.reinhardt@amd.com elif self.EntryType != None: 10698267Ssteve.reinhardt@amd.com code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 10705863Snate@binkert.org else: 10715863Snate@binkert.org code('${ident}_State state = getState(addr);') 10725863Snate@binkert.org 10732632Sstever@eecs.umich.edu code(''' 10748267Ssteve.reinhardt@amd.com ${ident}_State next_state = state; 10758267Ssteve.reinhardt@amd.com 10768267Ssteve.reinhardt@amd.com DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 10772632Sstever@eecs.umich.edu *this, 10781888SN/A g_eventQueue_ptr->getTime(), 10795863Snate@binkert.org ${ident}_State_to_string(state), 10805863Snate@binkert.org ${ident}_Event_to_string(event), 10811858SN/A addr); 10828120Sgblack@eecs.umich.edu 10838120Sgblack@eecs.umich.edu TransitionResult result = 10847756SAli.Saidi@ARM.com''') 10852598SN/A if self.TBEType != None and self.EntryType != None: 10865863Snate@binkert.org code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 10871858SN/A elif self.TBEType != None: 10881858SN/A code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 10891858SN/A elif self.EntryType != None: 10905863Snate@binkert.org code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 10911858SN/A else: 10921858SN/A code('doTransitionWorker(event, state, next_state, addr);') 10931858SN/A 10945863Snate@binkert.org code(''' 10951871SN/A if (result == TransitionResult_Valid) { 10961858SN/A DPRINTF(RubyGenerated, "next_state: %s\\n", 10971858SN/A ${ident}_State_to_string(next_state)); 10981858SN/A m_profiler.countTransition(state, event); 10991858SN/A DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 11005863Snate@binkert.org curTick(), m_version, "${ident}", 11015863Snate@binkert.org ${ident}_Event_to_string(event), 11021869SN/A ${ident}_State_to_string(state), 11031965SN/A ${ident}_State_to_string(next_state), 11047739Sgblack@eecs.umich.edu addr, GET_TRANSITION_COMMENT()); 11051965SN/A 11069045SAli.Saidi@ARM.com CLEAR_TRANSITION_COMMENT(); 11079045SAli.Saidi@ARM.com''') 11089045SAli.Saidi@ARM.com if self.TBEType != None and self.EntryType != None: 11092761Sstever@eecs.umich.edu code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 11105863Snate@binkert.org code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 11111869SN/A elif self.TBEType != None: 11125863Snate@binkert.org code('setState(m_tbe_ptr, addr, next_state);') 11132667Sstever@eecs.umich.edu code('setAccessPermission(addr, next_state);') 11141869SN/A elif self.EntryType != None: 11151869SN/A code('setState(m_cache_entry_ptr, addr, next_state);') 11162929Sktlim@umich.edu code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 11172929Sktlim@umich.edu else: 11185863Snate@binkert.org code('setState(addr, next_state);') 11192929Sktlim@umich.edu code('setAccessPermission(addr, next_state);') 1120955SN/A 11218120Sgblack@eecs.umich.edu code(''' 11228120Sgblack@eecs.umich.edu } else if (result == TransitionResult_ResourceStall) { 11238120Sgblack@eecs.umich.edu DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 11248120Sgblack@eecs.umich.edu curTick(), m_version, "${ident}", 11258120Sgblack@eecs.umich.edu ${ident}_Event_to_string(event), 11268120Sgblack@eecs.umich.edu ${ident}_State_to_string(state), 11278120Sgblack@eecs.umich.edu ${ident}_State_to_string(next_state), 11288120Sgblack@eecs.umich.edu addr, "Resource Stall"); 11298120Sgblack@eecs.umich.edu } else if (result == TransitionResult_ProtocolStall) { 11308120Sgblack@eecs.umich.edu DPRINTF(RubyGenerated, "stalling\\n"); 11318120Sgblack@eecs.umich.edu DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 11328120Sgblack@eecs.umich.edu curTick(), m_version, "${ident}", 1133 ${ident}_Event_to_string(event), 1134 ${ident}_State_to_string(state), 1135 ${ident}_State_to_string(next_state), 1136 addr, "Protocol Stall"); 1137 } 1138 1139 return result; 1140} 1141 1142TransitionResult 1143${ident}_Controller::doTransitionWorker(${ident}_Event event, 1144 ${ident}_State state, 1145 ${ident}_State& next_state, 1146''') 1147 1148 if self.TBEType != None: 1149 code(''' 1150 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 1151''') 1152 if self.EntryType != None: 1153 code(''' 1154 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 1155''') 1156 code(''' 1157 const Address& addr) 1158{ 1159 switch(HASH_FUN(state, event)) { 1160''') 1161 1162 # This map will allow suppress generating duplicate code 1163 cases = orderdict() 1164 1165 for trans in self.transitions: 1166 case_string = "%s_State_%s, %s_Event_%s" % \ 1167 (self.ident, trans.state.ident, self.ident, trans.event.ident) 1168 1169 case = self.symtab.codeFormatter() 1170 # Only set next_state if it changes 1171 if trans.state != trans.nextState: 1172 ns_ident = trans.nextState.ident 1173 case('next_state = ${ident}_State_${ns_ident};') 1174 1175 actions = trans.actions 1176 1177 # Check for resources 1178 case_sorter = [] 1179 res = trans.resources 1180 for key,val in res.iteritems(): 1181 if key.type.ident != "DNUCAStopTable": 1182 val = ''' 1183if (!%s.areNSlotsAvailable(%s)) 1184 return TransitionResult_ResourceStall; 1185''' % (key.code, val) 1186 case_sorter.append(val) 1187 1188 1189 # Emit the code sequences in a sorted order. This makes the 1190 # output deterministic (without this the output order can vary 1191 # since Map's keys() on a vector of pointers is not deterministic 1192 for c in sorted(case_sorter): 1193 case("$c") 1194 1195 # Figure out if we stall 1196 stall = False 1197 for action in actions: 1198 if action.ident == "z_stall": 1199 stall = True 1200 break 1201 1202 if stall: 1203 case('return TransitionResult_ProtocolStall;') 1204 else: 1205 if self.TBEType != None and self.EntryType != None: 1206 for action in actions: 1207 case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 1208 elif self.TBEType != None: 1209 for action in actions: 1210 case('${{action.ident}}(m_tbe_ptr, addr);') 1211 elif self.EntryType != None: 1212 for action in actions: 1213 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1214 else: 1215 for action in actions: 1216 case('${{action.ident}}(addr);') 1217 case('return TransitionResult_Valid;') 1218 1219 case = str(case) 1220 1221 # Look to see if this transition code is unique. 1222 if case not in cases: 1223 cases[case] = [] 1224 1225 cases[case].append(case_string) 1226 1227 # Walk through all of the unique code blocks and spit out the 1228 # corresponding case statement elements 1229 for case,transitions in cases.iteritems(): 1230 # Iterative over all the multiple transitions that share 1231 # the same code 1232 for trans in transitions: 1233 code(' case HASH_FUN($trans):') 1234 code(' $case') 1235 1236 code(''' 1237 default: 1238 fatal("Invalid transition\\n" 1239 "%s time: %d addr: %s event: %s state: %s\\n", 1240 name(), g_eventQueue_ptr->getTime(), addr, event, state); 1241 } 1242 return TransitionResult_Valid; 1243} 1244''') 1245 code.write(path, "%s_Transitions.cc" % self.ident) 1246 1247 def printProfileDumperHH(self, path): 1248 code = self.symtab.codeFormatter() 1249 ident = self.ident 1250 1251 code(''' 1252// Auto generated C++ code started by $__file__:$__line__ 1253// ${ident}: ${{self.short}} 1254 1255#ifndef __${ident}_PROFILE_DUMPER_HH__ 1256#define __${ident}_PROFILE_DUMPER_HH__ 1257 1258#include <cassert> 1259#include <iostream> 1260#include <vector> 1261 1262#include "${ident}_Event.hh" 1263#include "${ident}_Profiler.hh" 1264 1265typedef std::vector<${ident}_Profiler *> ${ident}_profilers; 1266 1267class ${ident}_ProfileDumper 1268{ 1269 public: 1270 ${ident}_ProfileDumper(); 1271 void registerProfiler(${ident}_Profiler* profiler); 1272 void dumpStats(std::ostream& out) const; 1273 1274 private: 1275 ${ident}_profilers m_profilers; 1276}; 1277 1278#endif // __${ident}_PROFILE_DUMPER_HH__ 1279''') 1280 code.write(path, "%s_ProfileDumper.hh" % self.ident) 1281 1282 def printProfileDumperCC(self, path): 1283 code = self.symtab.codeFormatter() 1284 ident = self.ident 1285 1286 code(''' 1287// Auto generated C++ code started by $__file__:$__line__ 1288// ${ident}: ${{self.short}} 1289 1290#include "mem/protocol/${ident}_ProfileDumper.hh" 1291 1292${ident}_ProfileDumper::${ident}_ProfileDumper() 1293{ 1294} 1295 1296void 1297${ident}_ProfileDumper::registerProfiler(${ident}_Profiler* profiler) 1298{ 1299 m_profilers.push_back(profiler); 1300} 1301 1302void 1303${ident}_ProfileDumper::dumpStats(std::ostream& out) const 1304{ 1305 out << " --- ${ident} ---\\n"; 1306 out << " - Event Counts -\\n"; 1307 for (${ident}_Event event = ${ident}_Event_FIRST; 1308 event < ${ident}_Event_NUM; 1309 ++event) { 1310 out << (${ident}_Event) event << " ["; 1311 uint64 total = 0; 1312 for (int i = 0; i < m_profilers.size(); i++) { 1313 out << m_profilers[i]->getEventCount(event) << " "; 1314 total += m_profilers[i]->getEventCount(event); 1315 } 1316 out << "] " << total << "\\n"; 1317 } 1318 out << "\\n"; 1319 out << " - Transitions -\\n"; 1320 for (${ident}_State state = ${ident}_State_FIRST; 1321 state < ${ident}_State_NUM; 1322 ++state) { 1323 for (${ident}_Event event = ${ident}_Event_FIRST; 1324 event < ${ident}_Event_NUM; 1325 ++event) { 1326 if (m_profilers[0]->isPossible(state, event)) { 1327 out << (${ident}_State) state << " " 1328 << (${ident}_Event) event << " ["; 1329 uint64 total = 0; 1330 for (int i = 0; i < m_profilers.size(); i++) { 1331 out << m_profilers[i]->getTransitionCount(state, event) << " "; 1332 total += m_profilers[i]->getTransitionCount(state, event); 1333 } 1334 out << "] " << total << "\\n"; 1335 } 1336 } 1337 out << "\\n"; 1338 } 1339} 1340''') 1341 code.write(path, "%s_ProfileDumper.cc" % self.ident) 1342 1343 def printProfilerHH(self, path): 1344 code = self.symtab.codeFormatter() 1345 ident = self.ident 1346 1347 code(''' 1348// Auto generated C++ code started by $__file__:$__line__ 1349// ${ident}: ${{self.short}} 1350 1351#ifndef __${ident}_PROFILER_HH__ 1352#define __${ident}_PROFILER_HH__ 1353 1354#include <cassert> 1355#include <iostream> 1356 1357#include "mem/protocol/${ident}_Event.hh" 1358#include "mem/protocol/${ident}_State.hh" 1359#include "mem/ruby/common/TypeDefines.hh" 1360 1361class ${ident}_Profiler 1362{ 1363 public: 1364 ${ident}_Profiler(); 1365 void setVersion(int version); 1366 void countTransition(${ident}_State state, ${ident}_Event event); 1367 void possibleTransition(${ident}_State state, ${ident}_Event event); 1368 uint64 getEventCount(${ident}_Event event); 1369 bool isPossible(${ident}_State state, ${ident}_Event event); 1370 uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); 1371 void clearStats(); 1372 1373 private: 1374 int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 1375 int m_event_counters[${ident}_Event_NUM]; 1376 bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 1377 int m_version; 1378}; 1379 1380#endif // __${ident}_PROFILER_HH__ 1381''') 1382 code.write(path, "%s_Profiler.hh" % self.ident) 1383 1384 def printProfilerCC(self, path): 1385 code = self.symtab.codeFormatter() 1386 ident = self.ident 1387 1388 code(''' 1389// Auto generated C++ code started by $__file__:$__line__ 1390// ${ident}: ${{self.short}} 1391 1392#include <cassert> 1393 1394#include "mem/protocol/${ident}_Profiler.hh" 1395 1396${ident}_Profiler::${ident}_Profiler() 1397{ 1398 for (int state = 0; state < ${ident}_State_NUM; state++) { 1399 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1400 m_possible[state][event] = false; 1401 m_counters[state][event] = 0; 1402 } 1403 } 1404 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1405 m_event_counters[event] = 0; 1406 } 1407} 1408 1409void 1410${ident}_Profiler::setVersion(int version) 1411{ 1412 m_version = version; 1413} 1414 1415void 1416${ident}_Profiler::clearStats() 1417{ 1418 for (int state = 0; state < ${ident}_State_NUM; state++) { 1419 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1420 m_counters[state][event] = 0; 1421 } 1422 } 1423 1424 for (int event = 0; event < ${ident}_Event_NUM; event++) { 1425 m_event_counters[event] = 0; 1426 } 1427} 1428void 1429${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) 1430{ 1431 assert(m_possible[state][event]); 1432 m_counters[state][event]++; 1433 m_event_counters[event]++; 1434} 1435void 1436${ident}_Profiler::possibleTransition(${ident}_State state, 1437 ${ident}_Event event) 1438{ 1439 m_possible[state][event] = true; 1440} 1441 1442uint64 1443${ident}_Profiler::getEventCount(${ident}_Event event) 1444{ 1445 return m_event_counters[event]; 1446} 1447 1448bool 1449${ident}_Profiler::isPossible(${ident}_State state, ${ident}_Event event) 1450{ 1451 return m_possible[state][event]; 1452} 1453 1454uint64 1455${ident}_Profiler::getTransitionCount(${ident}_State state, 1456 ${ident}_Event event) 1457{ 1458 return m_counters[state][event]; 1459} 1460 1461''') 1462 code.write(path, "%s_Profiler.cc" % self.ident) 1463 1464 # ************************** 1465 # ******* HTML Files ******* 1466 # ************************** 1467 def frameRef(self, click_href, click_target, over_href, over_num, text): 1468 code = self.symtab.codeFormatter(fix_newlines=False) 1469 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1470 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1471 parent.frames[$over_num].location='$over_href' 1472 }\"> 1473 ${{html.formatShorthand(text)}} 1474 </A>""") 1475 return str(code) 1476 1477 def writeHTMLFiles(self, path): 1478 # Create table with no row hilighted 1479 self.printHTMLTransitions(path, None) 1480 1481 # Generate transition tables 1482 for state in self.states.itervalues(): 1483 self.printHTMLTransitions(path, state) 1484 1485 # Generate action descriptions 1486 for action in self.actions.itervalues(): 1487 name = "%s_action_%s.html" % (self.ident, action.ident) 1488 code = html.createSymbol(action, "Action") 1489 code.write(path, name) 1490 1491 # Generate state descriptions 1492 for state in self.states.itervalues(): 1493 name = "%s_State_%s.html" % (self.ident, state.ident) 1494 code = html.createSymbol(state, "State") 1495 code.write(path, name) 1496 1497 # Generate event descriptions 1498 for event in self.events.itervalues(): 1499 name = "%s_Event_%s.html" % (self.ident, event.ident) 1500 code = html.createSymbol(event, "Event") 1501 code.write(path, name) 1502 1503 def printHTMLTransitions(self, path, active_state): 1504 code = self.symtab.codeFormatter() 1505 1506 code(''' 1507<HTML> 1508<BODY link="blue" vlink="blue"> 1509 1510<H1 align="center">${{html.formatShorthand(self.short)}}: 1511''') 1512 code.indent() 1513 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1514 mid = machine.ident 1515 if i != 0: 1516 extra = " - " 1517 else: 1518 extra = "" 1519 if machine == self: 1520 code('$extra$mid') 1521 else: 1522 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1523 code.dedent() 1524 1525 code(""" 1526</H1> 1527 1528<TABLE border=1> 1529<TR> 1530 <TH> </TH> 1531""") 1532 1533 for event in self.events.itervalues(): 1534 href = "%s_Event_%s.html" % (self.ident, event.ident) 1535 ref = self.frameRef(href, "Status", href, "1", event.short) 1536 code('<TH bgcolor=white>$ref</TH>') 1537 1538 code('</TR>') 1539 # -- Body of table 1540 for state in self.states.itervalues(): 1541 # -- Each row 1542 if state == active_state: 1543 color = "yellow" 1544 else: 1545 color = "white" 1546 1547 click = "%s_table_%s.html" % (self.ident, state.ident) 1548 over = "%s_State_%s.html" % (self.ident, state.ident) 1549 text = html.formatShorthand(state.short) 1550 ref = self.frameRef(click, "Table", over, "1", state.short) 1551 code(''' 1552<TR> 1553 <TH bgcolor=$color>$ref</TH> 1554''') 1555 1556 # -- One column for each event 1557 for event in self.events.itervalues(): 1558 trans = self.table.get((state,event), None) 1559 if trans is None: 1560 # This is the no transition case 1561 if state == active_state: 1562 color = "#C0C000" 1563 else: 1564 color = "lightgrey" 1565 1566 code('<TD bgcolor=$color> </TD>') 1567 continue 1568 1569 next = trans.nextState 1570 stall_action = False 1571 1572 # -- Get the actions 1573 for action in trans.actions: 1574 if action.ident == "z_stall" or \ 1575 action.ident == "zz_recycleMandatoryQueue": 1576 stall_action = True 1577 1578 # -- Print out "actions/next-state" 1579 if stall_action: 1580 if state == active_state: 1581 color = "#C0C000" 1582 else: 1583 color = "lightgrey" 1584 1585 elif active_state and next.ident == active_state.ident: 1586 color = "aqua" 1587 elif state == active_state: 1588 color = "yellow" 1589 else: 1590 color = "white" 1591 1592 code('<TD bgcolor=$color>') 1593 for action in trans.actions: 1594 href = "%s_action_%s.html" % (self.ident, action.ident) 1595 ref = self.frameRef(href, "Status", href, "1", 1596 action.short) 1597 code(' $ref') 1598 if next != state: 1599 if trans.actions: 1600 code('/') 1601 click = "%s_table_%s.html" % (self.ident, next.ident) 1602 over = "%s_State_%s.html" % (self.ident, next.ident) 1603 ref = self.frameRef(click, "Table", over, "1", next.short) 1604 code("$ref") 1605 code("</TD>") 1606 1607 # -- Each row 1608 if state == active_state: 1609 color = "yellow" 1610 else: 1611 color = "white" 1612 1613 click = "%s_table_%s.html" % (self.ident, state.ident) 1614 over = "%s_State_%s.html" % (self.ident, state.ident) 1615 ref = self.frameRef(click, "Table", over, "1", state.short) 1616 code(''' 1617 <TH bgcolor=$color>$ref</TH> 1618</TR> 1619''') 1620 code(''' 1621<!- Column footer-> 1622<TR> 1623 <TH> </TH> 1624''') 1625 1626 for event in self.events.itervalues(): 1627 href = "%s_Event_%s.html" % (self.ident, event.ident) 1628 ref = self.frameRef(href, "Status", href, "1", event.short) 1629 code('<TH bgcolor=white>$ref</TH>') 1630 code(''' 1631</TR> 1632</TABLE> 1633</BODY></HTML> 1634''') 1635 1636 1637 if active_state: 1638 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1639 else: 1640 name = "%s_table.html" % self.ident 1641 code.write(path, name) 1642 1643__all__ = [ "StateMachine" ] 1644