StateMachine.py revision 9102:5464eb9a684b
15703SN/A# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 25703SN/A# Copyright (c) 2009 The Hewlett-Packard Development Company 35703SN/A# All rights reserved. 49988Snilay@cs.wisc.edu# 58825Snilay@cs.wisc.edu# Redistribution and use in source and binary forms, with or without 69988Snilay@cs.wisc.edu# modification, are permitted provided that the following conditions are 77935SN/A# met: redistributions of source code must retain the above copyright 87935SN/A# notice, this list of conditions and the following disclaimer; 97935SN/A# redistributions in binary form must reproduce the above copyright 105703SN/A# notice, this list of conditions and the following disclaimer in the 115703SN/A# documentation and/or other materials provided with the distribution; 125703SN/A# neither the name of the copyright holders nor the names of its 1310315Snilay@cs.wisc.edu# contributors may be used to endorse or promote products derived from 145703SN/A# this software without specific prior written permission. 155703SN/A# 169885Sstever@gmail.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179885Sstever@gmail.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810513SAli.Saidi@ARM.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199988Snilay@cs.wisc.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205703SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110513SAli.Saidi@ARM.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210315Snilay@cs.wisc.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237670SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410242Ssteve.reinhardt@amd.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255703SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269449SAli.Saidi@ARM.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278464SN/A 288721SN/Afrom m5.util import orderdict 2910513SAli.Saidi@ARM.com 3010513SAli.Saidi@ARM.comfrom slicc.symbols.Symbol import Symbol 315703SN/Afrom slicc.symbols.Var import Var 325703SN/Aimport slicc.generate.html as html 335703SN/Aimport re 347935SN/A 357935SN/Apython_class_map = {"int": "Int", 367935SN/A "std::string": "String", 377935SN/A "bool": "Bool", 387935SN/A "CacheMemory": "RubyCache", 397935SN/A "WireBuffer": "RubyWireBuffer", 407935SN/A "Sequencer": "RubySequencer", 418983Snate@binkert.org "DirectoryMemory": "RubyDirectoryMemory", 425703SN/A "MemoryControl": "MemoryControl", 435703SN/A "DMASequencer": "DMASequencer" 445703SN/A } 459885Sstever@gmail.com 465703SN/Aclass StateMachine(Symbol): 479988Snilay@cs.wisc.edu def __init__(self, symtab, ident, location, pairs, config_parameters): 488721SN/A super(StateMachine, self).__init__(symtab, ident, location, pairs) 498721SN/A self.table = None 508721SN/A self.config_parameters = config_parameters 518983Snate@binkert.org 528983Snate@binkert.org for param in config_parameters: 535703SN/A if param.pointer: 549885Sstever@gmail.com var = Var(symtab, param.name, location, param.type_ast.type, 559885Sstever@gmail.com "(*m_%s_ptr)" % param.name, {}, self) 569885Sstever@gmail.com else: 5710315Snilay@cs.wisc.edu var = Var(symtab, param.name, location, param.type_ast.type, 589988Snilay@cs.wisc.edu "m_%s" % param.name, {}, self) 5910315Snilay@cs.wisc.edu self.symtab.registerSym(param.name, var) 609885Sstever@gmail.com 619885Sstever@gmail.com self.states = orderdict() 625703SN/A self.events = orderdict() 635703SN/A self.actions = orderdict() 649481Snilay@cs.wisc.edu self.transitions = [] 655703SN/A self.in_ports = [] 665703SN/A self.functions = [] 678241SN/A self.objects = [] 688241SN/A self.TBEType = None 695703SN/A self.EntryType = None 705703SN/A 715703SN/A self.message_buffer_names = [] 725703SN/A 739481Snilay@cs.wisc.edu def __repr__(self): 745703SN/A return "[StateMachine: %s]" % self.ident 755876SN/A 769885Sstever@gmail.com def addState(self, state): 775703SN/A assert self.table is None 785703SN/A self.states[state.ident] = state 795703SN/A 805703SN/A def addEvent(self, event): 815703SN/A assert self.table is None 825703SN/A self.events[event.ident] = event 835703SN/A 845703SN/A def addAction(self, action): 855703SN/A assert self.table is None 865703SN/A 875703SN/A # Check for duplicate action 885703SN/A for other in self.actions.itervalues(): 895703SN/A if action.ident == other.ident: 905703SN/A action.warning("Duplicate action definition: %s" % action.ident) 919988Snilay@cs.wisc.edu action.error("Duplicate action definition: %s" % action.ident) 929988Snilay@cs.wisc.edu if action.short == other.short: 9310451Snilay@cs.wisc.edu other.warning("Duplicate action shorthand: %s" % other.ident) 945703SN/A other.warning(" shorthand = %s" % other.short) 955703SN/A action.warning("Duplicate action shorthand: %s" % action.ident) 965703SN/A action.error(" shorthand = %s" % action.short) 975703SN/A 985703SN/A self.actions[action.ident] = action 995703SN/A 1005703SN/A def addTransition(self, trans): 1015703SN/A assert self.table is None 1025703SN/A self.transitions.append(trans) 1035703SN/A 1045703SN/A def addInPort(self, var): 1055703SN/A self.in_ports.append(var) 1069348SAli.Saidi@ARM.com 1075703SN/A def addFunc(self, func): 1085703SN/A # register func in the symbol table 1095703SN/A self.symtab.registerSym(str(func), func) 1105703SN/A self.functions.append(func) 1115703SN/A 1125703SN/A def addObject(self, obj): 1135703SN/A self.objects.append(obj) 1148825Snilay@cs.wisc.edu 1155703SN/A def addType(self, type): 1169924Ssteve.reinhardt@amd.com type_ident = '%s' % type.c_ident 1175703SN/A 1185703SN/A if type_ident == "%s_TBE" %self.ident: 1195703SN/A if self.TBEType != None: 1205703SN/A self.error("Multiple Transaction Buffer types in a " \ 1215703SN/A "single machine."); 1225703SN/A self.TBEType = type 1235703SN/A 1245703SN/A elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 1255703SN/A if self.EntryType != None: 1265703SN/A self.error("Multiple AbstractCacheEntry types in a " \ 1275703SN/A "single machine."); 1285703SN/A self.EntryType = type 1299661SAli.Saidi@ARM.com 1305703SN/A # Needs to be called before accessing the table 1315703SN/A def buildTable(self): 1325703SN/A assert self.table is None 1335703SN/A 1345703SN/A table = {} 1355703SN/A 1365703SN/A for trans in self.transitions: 1375703SN/A # Track which actions we touch so we know if we use them 1385703SN/A # all -- really this should be done for all symbols as 13910242Ssteve.reinhardt@amd.com # part of the symbol table, then only trigger it for 1405703SN/A # Actions, States, Events, etc. 1418521SN/A 1429449SAli.Saidi@ARM.com for action in trans.actions: 1435703SN/A action.used = True 1445703SN/A 1455703SN/A index = (trans.state, trans.event) 1465703SN/A if index in table: 1478825Snilay@cs.wisc.edu table[index].warning("Duplicate transition: %s" % table[index]) 1485703SN/A trans.error("Duplicate transition: %s" % trans) 1495703SN/A table[index] = trans 1505703SN/A 1519481Snilay@cs.wisc.edu # Look at all actions to make sure we used them all 1529481Snilay@cs.wisc.edu for action in self.actions.itervalues(): 1539481Snilay@cs.wisc.edu if not action.used: 1549481Snilay@cs.wisc.edu error_msg = "Unused action: %s" % action.ident 1559481Snilay@cs.wisc.edu if "desc" in action: 1569481Snilay@cs.wisc.edu error_msg += ", " + action.desc 1579481Snilay@cs.wisc.edu action.warning(error_msg) 1589988Snilay@cs.wisc.edu self.table = table 1599481Snilay@cs.wisc.edu 1609481Snilay@cs.wisc.edu def writeCodeFiles(self, path): 1619481Snilay@cs.wisc.edu self.printControllerPython(path) 1629481Snilay@cs.wisc.edu self.printControllerHH(path) 1639481Snilay@cs.wisc.edu self.printControllerCC(path) 1649481Snilay@cs.wisc.edu self.printCSwitch(path) 1659481Snilay@cs.wisc.edu self.printCWakeup(path) 1669481Snilay@cs.wisc.edu self.printProfilerCC(path) 1679481Snilay@cs.wisc.edu self.printProfilerHH(path) 1685703SN/A self.printProfileDumperCC(path) 1695703SN/A self.printProfileDumperHH(path) 1709885Sstever@gmail.com 1718983Snate@binkert.org def printControllerPython(self, path): 1725703SN/A code = self.symtab.codeFormatter() 1739885Sstever@gmail.com ident = self.ident 1749988Snilay@cs.wisc.edu py_ident = "%s_Controller" % ident 1756123SN/A c_ident = "%s_Controller" % self.ident 1769348SAli.Saidi@ARM.com code(''' 1778135SN/Afrom m5.params import * 1785703SN/Afrom m5.SimObject import SimObject 1795703SN/Afrom Controller import RubyController 1805876SN/A 1818835SAli.Saidi@ARM.comclass $py_ident(RubyController): 1829348SAli.Saidi@ARM.com type = '$py_ident' 18310036SAli.Saidi@ARM.com''') 1845703SN/A code.indent() 1858835SAli.Saidi@ARM.com for param in self.config_parameters: 1869885Sstever@gmail.com dflt_str = '' 1875703SN/A if param.default is not None: 1885703SN/A dflt_str = str(param.default) + ', ' 1895703SN/A if python_class_map.has_key(param.type_ast.type.c_ident): 1905703SN/A python_type = python_class_map[param.type_ast.type.c_ident] 1919348SAli.Saidi@ARM.com code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")') 1925703SN/A else: 1939885Sstever@gmail.com self.error("Unknown c++ to python class conversion for c++ " \ 1949885Sstever@gmail.com "type: '%s'. Please update the python_class_map " \ 1959885Sstever@gmail.com "in StateMachine.py", param.type_ast.type.c_ident) 1969885Sstever@gmail.com code.dedent() 1979885Sstever@gmail.com code.write(path, '%s.py' % py_ident) 1989988Snilay@cs.wisc.edu 1999885Sstever@gmail.com 20010036SAli.Saidi@ARM.com def printControllerHH(self, path): 2019885Sstever@gmail.com '''Output the method declarations for the class declaration''' 2029885Sstever@gmail.com code = self.symtab.codeFormatter() 2035703SN/A ident = self.ident 2046024SN/A c_ident = "%s_Controller" % self.ident 2059988Snilay@cs.wisc.edu 2065703SN/A self.message_buffer_names = [] 2075703SN/A 2085703SN/A code(''' 2095703SN/A/** \\file $c_ident.hh 2107761SN/A * 2117761SN/A * Auto generated C++ code started by $__file__:$__line__ 2129988Snilay@cs.wisc.edu * Created by slicc definition of Module "${{self.short}}" 2135703SN/A */ 2145703SN/A 2155703SN/A#ifndef __${ident}_CONTROLLER_HH__ 2165703SN/A#define __${ident}_CONTROLLER_HH__ 2175703SN/A 2189988Snilay@cs.wisc.edu#include <iostream> 2195703SN/A#include <sstream> 2205703SN/A#include <string> 2215703SN/A 2225703SN/A#include "mem/protocol/${ident}_ProfileDumper.hh" 2239988Snilay@cs.wisc.edu#include "mem/protocol/${ident}_Profiler.hh" 2245703SN/A#include "mem/protocol/TransitionResult.hh" 2255703SN/A#include "mem/protocol/Types.hh" 2265703SN/A#include "mem/ruby/common/Consumer.hh" 2275703SN/A#include "mem/ruby/common/Global.hh" 2285703SN/A#include "mem/ruby/slicc_interface/AbstractController.hh" 2295703SN/A#include "params/$c_ident.hh" 2305703SN/A''') 2315703SN/A 2329988Snilay@cs.wisc.edu seen_types = set() 2335703SN/A for var in self.objects: 2345703SN/A if var.type.ident not in seen_types and not var.type.isPrimitive: 2355703SN/A code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 2365703SN/A seen_types.add(var.type.ident) 2379988Snilay@cs.wisc.edu 2385703SN/A # for adding information to the protocol debug trace 2395703SN/A code(''' 2405703SN/Aextern std::stringstream ${ident}_transitionComment; 2415703SN/A 2425703SN/Aclass $c_ident : public AbstractController 2435703SN/A{ 2449988Snilay@cs.wisc.edu// the coherence checker needs to call isBlockExclusive() and isBlockShared() 2455703SN/A// making the Chip a friend class is an easy way to do this for now 2465703SN/A 2475703SN/Apublic: 2485703SN/A typedef ${c_ident}Params Params; 2495703SN/A $c_ident(const Params *p); 2505703SN/A static int getNumControllers(); 2515703SN/A void init(); 2525703SN/A MessageBuffer* getMandatoryQueue() const; 2539988Snilay@cs.wisc.edu const int & getVersion() const; 2545703SN/A const std::string toString() const; 2555703SN/A const std::string getName() const; 2565703SN/A void stallBuffer(MessageBuffer* buf, Address addr); 2575703SN/A void wakeUpBuffers(Address addr); 2589988Snilay@cs.wisc.edu void wakeUpAllBuffers(); 2595703SN/A void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; } 2605703SN/A void print(std::ostream& out) const; 2615703SN/A void printConfig(std::ostream& out) const; 2625703SN/A void wakeup(); 2635703SN/A void printStats(std::ostream& out) const; 2645703SN/A void clearStats(); 2659988Snilay@cs.wisc.edu void blockOnQueue(Address addr, MessageBuffer* port); 2665703SN/A void unblock(Address addr); 2675703SN/A void recordCacheTrace(int cntrl, CacheRecorder* tr); 2685703SN/A Sequencer* getSequencer() const; 2695703SN/A 2705703SN/Aprivate: 2715703SN/A''') 2729988Snilay@cs.wisc.edu 2735703SN/A code.indent() 2745703SN/A # added by SS 2755703SN/A for param in self.config_parameters: 2765703SN/A if param.pointer: 2775703SN/A code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 2785703SN/A else: 2795703SN/A code('${{param.type_ast.type}} m_${{param.ident}};') 2805703SN/A 2819988Snilay@cs.wisc.edu code(''' 2825703SN/Aint m_number_of_TBEs; 2835703SN/A 2845703SN/ATransitionResult doTransition(${ident}_Event event, 2855703SN/A''') 2869988Snilay@cs.wisc.edu 2875703SN/A if self.EntryType != None: 2885703SN/A code(''' 2895703SN/A ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 2905703SN/A''') 2915703SN/A if self.TBEType != None: 2925703SN/A code(''' 2939988Snilay@cs.wisc.edu ${{self.TBEType.c_ident}}* m_tbe_ptr, 2945703SN/A''') 2955703SN/A 2965703SN/A code(''' 2975703SN/A const Address& addr); 2985703SN/A 2995703SN/ATransitionResult doTransitionWorker(${ident}_Event event, 3009988Snilay@cs.wisc.edu ${ident}_State state, 3015703SN/A ${ident}_State& next_state, 3025703SN/A''') 3035703SN/A 3045703SN/A if self.TBEType != None: 3055703SN/A code(''' 3065703SN/A ${{self.TBEType.c_ident}}*& m_tbe_ptr, 3075703SN/A''') 3085703SN/A if self.EntryType != None: 3099988Snilay@cs.wisc.edu code(''' 3105703SN/A ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 3115703SN/A''') 3125703SN/A 3135703SN/A code(''' 3149988Snilay@cs.wisc.edu const Address& addr); 3155703SN/A 3165703SN/Astd::string m_name; 3175703SN/Aint m_transitions_per_cycle; 3185703SN/Aint m_buffer_size; 3195703SN/Aint m_recycle_latency; 3205703SN/Astd::map<std::string, std::string> m_cfg; 3217761SN/ANodeID m_version; 3227761SN/ANetwork* m_net_ptr; 3239988Snilay@cs.wisc.eduMachineID m_machineID; 3247761SN/Abool m_is_blocking; 3255703SN/Astd::map<Address, MessageBuffer*> m_block_map; 3267761SN/Atypedef std::vector<MessageBuffer*> MsgVecType; 3275703SN/Atypedef std::map< Address, MsgVecType* > WaitingBufType; 3289988Snilay@cs.wisc.eduWaitingBufType m_waiting_buffers; 3295703SN/Aint m_max_in_port_rank; 3307761SN/Aint m_cur_in_port_rank; 3317761SN/Astatic ${ident}_ProfileDumper s_profileDumper; 3327761SN/A${ident}_Profiler m_profiler; 3337761SN/Astatic int m_num_controllers; 3347761SN/A 3359988Snilay@cs.wisc.edu// Internal functions 3367761SN/A''') 3377761SN/A 3387761SN/A for func in self.functions: 3397761SN/A proto = func.prototype 3407761SN/A if proto: 3417761SN/A code('$proto') 3429988Snilay@cs.wisc.edu 3437761SN/A if self.EntryType != None: 3447761SN/A code(''' 3457761SN/A 3467761SN/A// Set and Reset for cache_entry variable 3477761SN/Avoid set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 3487761SN/Avoid unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 3499988Snilay@cs.wisc.edu''') 3507761SN/A 3517761SN/A if self.TBEType != None: 3527761SN/A code(''' 3537761SN/A 3547761SN/A// Set and Reset for tbe variable 3557761SN/Avoid set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 3569988Snilay@cs.wisc.eduvoid unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 3577761SN/A''') 3587761SN/A 3597761SN/A code(''' 3607761SN/A 3617761SN/A// Actions 3627761SN/A''') 3639988Snilay@cs.wisc.edu if self.TBEType != None and self.EntryType != None: 3647761SN/A for action in self.actions.itervalues(): 3657761SN/A code('/** \\brief ${{action.desc}} */') 3667761SN/A code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 3677761SN/A elif self.TBEType != None: 3687761SN/A for action in self.actions.itervalues(): 3697761SN/A code('/** \\brief ${{action.desc}} */') 3709988Snilay@cs.wisc.edu code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr);') 3717761SN/A elif self.EntryType != None: 3727761SN/A for action in self.actions.itervalues(): 3737761SN/A code('/** \\brief ${{action.desc}} */') 3747761SN/A code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') 3757761SN/A else: 3767761SN/A for action in self.actions.itervalues(): 3779988Snilay@cs.wisc.edu code('/** \\brief ${{action.desc}} */') 3787761SN/A code('void ${{action.ident}}(const Address& addr);') 3797761SN/A 3807761SN/A # the controller internal variables 3817761SN/A code(''' 3827761SN/A 3837761SN/A// Objects 3849988Snilay@cs.wisc.edu''') 3857761SN/A for var in self.objects: 3867761SN/A th = var.get("template_hack", "") 3877761SN/A code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') 3887761SN/A 3897761SN/A if var.type.ident == "MessageBuffer": 3907761SN/A self.message_buffer_names.append("m_%s_ptr" % var.c_ident) 3919988Snilay@cs.wisc.edu 3927761SN/A code.dedent() 3937761SN/A code('};') 3947761SN/A code('#endif // __${ident}_CONTROLLER_H__') 3957761SN/A code.write(path, '%s.hh' % c_ident) 3967761SN/A 3977761SN/A def printControllerCC(self, path): 3989988Snilay@cs.wisc.edu '''Output the actions for performing the actions''' 3997761SN/A 4007761SN/A code = self.symtab.codeFormatter() 4017761SN/A ident = self.ident 4027761SN/A c_ident = "%s_Controller" % self.ident 4037761SN/A 4047761SN/A code(''' 4059988Snilay@cs.wisc.edu/** \\file $c_ident.cc 4067761SN/A * 4077761SN/A * Auto generated C++ code started by $__file__:$__line__ 4087761SN/A * Created by slicc definition of Module "${{self.short}}" 4097761SN/A */ 4107761SN/A 4117761SN/A#include <sys/types.h> 4129988Snilay@cs.wisc.edu#include <unistd.h> 4137761SN/A 4147761SN/A#include <cassert> 4157761SN/A#include <sstream> 4167761SN/A#include <string> 4177761SN/A 4187761SN/A#include "base/compiler.hh" 4199988Snilay@cs.wisc.edu#include "base/cprintf.hh" 4207761SN/A#include "debug/RubyGenerated.hh" 4217761SN/A#include "debug/RubySlicc.hh" 4227761SN/A#include "mem/protocol/${ident}_Controller.hh" 4237761SN/A#include "mem/protocol/${ident}_Event.hh" 4247761SN/A#include "mem/protocol/${ident}_State.hh" 4257761SN/A#include "mem/protocol/Types.hh" 4269988Snilay@cs.wisc.edu#include "mem/ruby/common/Global.hh" 4277761SN/A#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 4287761SN/A#include "mem/ruby/system/System.hh" 4297761SN/A 4307761SN/Ausing namespace std; 4317761SN/A''') 4327761SN/A 4339988Snilay@cs.wisc.edu # include object classes 4347761SN/A seen_types = set() 4357761SN/A for var in self.objects: 4367761SN/A if var.type.ident not in seen_types and not var.type.isPrimitive: 4377761SN/A code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 4387761SN/A seen_types.add(var.type.ident) 4397761SN/A 4409988Snilay@cs.wisc.edu code(''' 4417761SN/A$c_ident * 4427761SN/A${c_ident}Params::create() 4437761SN/A{ 4447761SN/A return new $c_ident(this); 4457761SN/A} 4467761SN/A 4479988Snilay@cs.wisc.eduint $c_ident::m_num_controllers = 0; 4487761SN/A${ident}_ProfileDumper $c_ident::s_profileDumper; 4497761SN/A 4507761SN/A// for adding information to the protocol debug trace 4517761SN/Astringstream ${ident}_transitionComment; 4527761SN/A#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 4537761SN/A 4549988Snilay@cs.wisc.edu/** \\brief constructor */ 4557761SN/A$c_ident::$c_ident(const Params *p) 4567761SN/A : AbstractController(p) 4577761SN/A{ 4587761SN/A m_version = p->version; 4597761SN/A m_transitions_per_cycle = p->transitions_per_cycle; 4607761SN/A m_buffer_size = p->buffer_size; 4619988Snilay@cs.wisc.edu m_recycle_latency = p->recycle_latency; 4627761SN/A m_number_of_TBEs = p->number_of_TBEs; 4637761SN/A m_is_blocking = false; 4645703SN/A m_name = "${ident}"; 4655703SN/A''') 4665703SN/A # 4675703SN/A # max_port_rank is used to size vectors and thus should be one plus the 4687761SN/A # largest port rank 4697761SN/A # 4709988Snilay@cs.wisc.edu max_port_rank = self.in_ports[0].pairs["max_port_rank"] + 1 4717761SN/A code(' m_max_in_port_rank = $max_port_rank;') 4725703SN/A code.indent() 4737761SN/A 4745703SN/A # 4759988Snilay@cs.wisc.edu # After initializing the universal machine parameters, initialize the 4765703SN/A # this machines config parameters. Also detemine if these configuration 4775703SN/A # params include a sequencer. This information will be used later for 4785703SN/A # contecting the sequencer back to the L1 cache controller. 4795703SN/A # 4805703SN/A contains_dma_sequencer = False 4815703SN/A sequencers = [] 4827761SN/A for param in self.config_parameters: 4837761SN/A if param.name == "dma_sequencer": 4849988Snilay@cs.wisc.edu contains_dma_sequencer = True 4857761SN/A elif re.compile("sequencer").search(param.name): 4867761SN/A sequencers.append(param.name) 4877761SN/A if param.pointer: 4887761SN/A code('m_${{param.name}}_ptr = p->${{param.name}};') 4899988Snilay@cs.wisc.edu else: 4907761SN/A code('m_${{param.name}} = p->${{param.name}};') 4917761SN/A 4927761SN/A # 4937761SN/A # For the l1 cache controller, add the special atomic support which 4947761SN/A # includes passing the sequencer a pointer to the controller. 4957761SN/A # 4969988Snilay@cs.wisc.edu if self.ident == "L1Cache": 4977761SN/A if not sequencers: 4987761SN/A self.error("The L1Cache controller must include the sequencer " \ 4997761SN/A "configuration parameter") 5007761SN/A 5017761SN/A for seq in sequencers: 5027761SN/A code(''' 5035703SN/Am_${{seq}}_ptr->setController(this); 5045703SN/A ''') 5059988Snilay@cs.wisc.edu 5067761SN/A else: 5075703SN/A for seq in sequencers: 5087761SN/A code(''' 5095703SN/Am_${{seq}}_ptr->setController(this); 5109988Snilay@cs.wisc.edu ''') 5115703SN/A 5125703SN/A # 5135703SN/A # For the DMA controller, pass the sequencer a pointer to the 5145703SN/A # controller. 5155703SN/A # 5165703SN/A if self.ident == "DMA": 5179885Sstever@gmail.com if not contains_dma_sequencer: 5188983Snate@binkert.org self.error("The DMA controller must include the sequencer " \ 5195703SN/A "configuration parameter") 5209885Sstever@gmail.com 5219988Snilay@cs.wisc.edu code(''' 5226123SN/Am_dma_sequencer_ptr->setController(this); 5239348SAli.Saidi@ARM.com''') 5248135SN/A 5255703SN/A code('m_num_controllers++;') 5265703SN/A for var in self.objects: 5275876SN/A if var.ident.find("mandatoryQueue") >= 0: 5288835SAli.Saidi@ARM.com code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();') 5299348SAli.Saidi@ARM.com 53010036SAli.Saidi@ARM.com code.dedent() 5315703SN/A code(''' 5328835SAli.Saidi@ARM.com} 5339885Sstever@gmail.com 5345703SN/Avoid 5355703SN/A$c_ident::init() 5365703SN/A{ 5375703SN/A MachineType machine_type; 5389348SAli.Saidi@ARM.com int base; 5395703SN/A 5409885Sstever@gmail.com m_machineID.type = MachineType_${ident}; 5419885Sstever@gmail.com m_machineID.num = m_version; 5429885Sstever@gmail.com 5439885Sstever@gmail.com // initialize objects 5449885Sstever@gmail.com m_profiler.setVersion(m_version); 5459988Snilay@cs.wisc.edu s_profileDumper.registerProfiler(&m_profiler); 5469885Sstever@gmail.com 54710036SAli.Saidi@ARM.com''') 5489885Sstever@gmail.com 5499885Sstever@gmail.com code.indent() 5505703SN/A for var in self.objects: 5515703SN/A vtype = var.type 5529988Snilay@cs.wisc.edu vid = "m_%s_ptr" % var.c_ident 5535703SN/A if "network" not in var: 5549348SAli.Saidi@ARM.com # Not a network port object 5559348SAli.Saidi@ARM.com if "primitive" in vtype: 5569988Snilay@cs.wisc.edu code('$vid = new ${{vtype.c_ident}};') 55710036SAli.Saidi@ARM.com if "default" in var: 5589348SAli.Saidi@ARM.com code('(*$vid) = ${{var["default"]}};') 5595703SN/A else: 5606024SN/A # Normal Object 5619988Snilay@cs.wisc.edu # added by SS 5625703SN/A if "factory" in var: 5635703SN/A code('$vid = ${{var["factory"]}};') 5649348SAli.Saidi@ARM.com elif var.ident.find("mandatoryQueue") < 0: 5659348SAli.Saidi@ARM.com th = var.get("template_hack", "") 5669885Sstever@gmail.com expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 5679348SAli.Saidi@ARM.com 5689348SAli.Saidi@ARM.com args = "" 5699885Sstever@gmail.com if "non_obj" not in vtype and not vtype.isEnumeration: 5709988Snilay@cs.wisc.edu if expr.find("TBETable") >= 0: 5719348SAli.Saidi@ARM.com args = "m_number_of_TBEs" 5729348SAli.Saidi@ARM.com else: 5739348SAli.Saidi@ARM.com args = var.get("constructor_hack", "") 5749348SAli.Saidi@ARM.com 5759348SAli.Saidi@ARM.com code('$expr($args);') 5769348SAli.Saidi@ARM.com 5779348SAli.Saidi@ARM.com code('assert($vid != NULL);') 5789348SAli.Saidi@ARM.com 57910036SAli.Saidi@ARM.com if "default" in var: 5809348SAli.Saidi@ARM.com code('*$vid = ${{var["default"]}}; // Object default') 5819348SAli.Saidi@ARM.com elif "default" in vtype: 5829885Sstever@gmail.com comment = "Type %s default" % vtype.ident 5839348SAli.Saidi@ARM.com code('*$vid = ${{vtype["default"]}}; // $comment') 5849348SAli.Saidi@ARM.com 5859348SAli.Saidi@ARM.com # Set ordering 5869348SAli.Saidi@ARM.com if "ordered" in var and "trigger_queue" not in var: 5879449SAli.Saidi@ARM.com # A buffer 5889348SAli.Saidi@ARM.com code('$vid->setOrdering(${{var["ordered"]}});') 5899885Sstever@gmail.com 5909885Sstever@gmail.com # Set randomization 5919885Sstever@gmail.com if "random" in var: 5929885Sstever@gmail.com # A buffer 5939885Sstever@gmail.com code('$vid->setRandomization(${{var["random"]}});') 5949988Snilay@cs.wisc.edu 5959885Sstever@gmail.com # Set Priority 59610036SAli.Saidi@ARM.com if vtype.isBuffer and \ 5979885Sstever@gmail.com "rank" in var and "trigger_queue" not in var: 5989885Sstever@gmail.com code('$vid->setPriority(${{var["rank"]}});') 5999348SAli.Saidi@ARM.com 60010451Snilay@cs.wisc.edu else: 6019885Sstever@gmail.com # Network port object 6029988Snilay@cs.wisc.edu network = var["network"] 6039348SAli.Saidi@ARM.com ordered = var["ordered"] 60410451Snilay@cs.wisc.edu vnet = var["virtual_network"] 6059536SAli.Saidi@ARM.com vnet_type = var["vnet_type"] 6069348SAli.Saidi@ARM.com 6079348SAli.Saidi@ARM.com assert var.machine is not None 6089348SAli.Saidi@ARM.com code(''' 6099348SAli.Saidi@ARM.commachine_type = string_to_MachineType("${{var.machine.ident}}"); 6109348SAli.Saidi@ARM.combase = MachineType_base_number(machine_type); 6115703SN/A$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type"); 6125703SN/A''') 6139988Snilay@cs.wisc.edu 6145703SN/A code('assert($vid != NULL);') 6159885Sstever@gmail.com 6169885Sstever@gmail.com # Set ordering 6179885Sstever@gmail.com if "ordered" in var: 61810315Snilay@cs.wisc.edu # A buffer 6199988Snilay@cs.wisc.edu code('$vid->setOrdering(${{var["ordered"]}});') 62010315Snilay@cs.wisc.edu 6219885Sstever@gmail.com # Set randomization 6229885Sstever@gmail.com if "random" in var: 6235703SN/A # A buffer 6245703SN/A code('$vid->setRandomization(${{var["random"]}});') 6255703SN/A 6265703SN/A # Set Priority 6275703SN/A if "rank" in var: 6289988Snilay@cs.wisc.edu code('$vid->setPriority(${{var["rank"]}})') 6295703SN/A 6305703SN/A # Set buffer size 6315703SN/A if vtype.isBuffer: 6325703SN/A code(''' 6335703SN/Aif (m_buffer_size > 0) { 6345703SN/A $vid->resize(m_buffer_size); 6359988Snilay@cs.wisc.edu} 6365876SN/A''') 6375703SN/A 6385703SN/A # set description (may be overriden later by port def) 6395703SN/A code(''' 6405703SN/A$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]"); 6415703SN/A 6429988Snilay@cs.wisc.edu''') 64310513SAli.Saidi@ARM.com 6445703SN/A if vtype.isBuffer: 6455703SN/A if "recycle_latency" in var: 6465703SN/A code('$vid->setRecycleLatency(${{var["recycle_latency"]}});') 6475703SN/A else: 6485703SN/A code('$vid->setRecycleLatency(m_recycle_latency);') 6495703SN/A 6505703SN/A 6519988Snilay@cs.wisc.edu # Set the queue consumers 6525703SN/A code() 6535703SN/A for port in self.in_ports: 6545703SN/A code('${{port.code}}.setConsumer(this);') 6555703SN/A 6565703SN/A # Set the queue descriptions 6575703SN/A code() 6589988Snilay@cs.wisc.edu for port in self.in_ports: 6595876SN/A code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");') 6605703SN/A 6615703SN/A # Initialize the transition profiling 6625703SN/A code() 6635703SN/A for trans in self.transitions: 6645703SN/A # Figure out if we stall 6659988Snilay@cs.wisc.edu stall = False 66610513SAli.Saidi@ARM.com for action in trans.actions: 6675703SN/A if action.ident == "z_stall": 6685703SN/A stall = True 66910315Snilay@cs.wisc.edu 67010315Snilay@cs.wisc.edu # Only possible if it is not a 'z' case 67110315Snilay@cs.wisc.edu if not stall: 67210315Snilay@cs.wisc.edu state = "%s_State_%s" % (self.ident, trans.state.ident) 67310315Snilay@cs.wisc.edu event = "%s_Event_%s" % (self.ident, trans.event.ident) 67410315Snilay@cs.wisc.edu code('m_profiler.possibleTransition($state, $event);') 67510315Snilay@cs.wisc.edu 67610315Snilay@cs.wisc.edu code.dedent() 6775703SN/A code('}') 6785703SN/A 6799988Snilay@cs.wisc.edu has_mandatory_q = False 6805703SN/A for port in self.in_ports: 6815703SN/A if port.code.find("mandatoryQueue_ptr") >= 0: 6825703SN/A has_mandatory_q = True 68310451Snilay@cs.wisc.edu 6849885Sstever@gmail.com if has_mandatory_q: 6859988Snilay@cs.wisc.edu mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident 6865703SN/A else: 6877524SN/A mq_ident = "NULL" 6889096Sandreas.hansson@arm.com 6895703SN/A seq_ident = "NULL" 6908983Snate@binkert.org for param in self.config_parameters: 6918983Snate@binkert.org if param.name == "sequencer": 6925703SN/A assert(param.pointer) 6935703SN/A seq_ident = "m_%s_ptr" % param.name 6945703SN/A 6959885Sstever@gmail.com code(''' 6969449SAli.Saidi@ARM.comint 6975703SN/A$c_ident::getNumControllers() 6989885Sstever@gmail.com{ 6999988Snilay@cs.wisc.edu return m_num_controllers; 7006123SN/A} 7019348SAli.Saidi@ARM.com 7028135SN/AMessageBuffer* 7035703SN/A$c_ident::getMandatoryQueue() const 7045703SN/A{ 7055876SN/A return $mq_ident; 7068835SAli.Saidi@ARM.com} 7079348SAli.Saidi@ARM.com 70810036SAli.Saidi@ARM.comSequencer* 7095703SN/A$c_ident::getSequencer() const 7108835SAli.Saidi@ARM.com{ 7119885Sstever@gmail.com return $seq_ident; 7125703SN/A} 7135703SN/A 7145703SN/Aconst int & 7158983Snate@binkert.org$c_ident::getVersion() const 7169449SAli.Saidi@ARM.com{ 7175703SN/A return m_version; 7189885Sstever@gmail.com} 7199885Sstever@gmail.com 7209885Sstever@gmail.comconst string 7219885Sstever@gmail.com$c_ident::toString() const 7229885Sstever@gmail.com{ 7239988Snilay@cs.wisc.edu return "$c_ident"; 7249885Sstever@gmail.com} 72510036SAli.Saidi@ARM.com 7269885Sstever@gmail.comconst string 7279885Sstever@gmail.com$c_ident::getName() const 7285703SN/A{ 72910451Snilay@cs.wisc.edu return m_name; 7306123SN/A} 7319885Sstever@gmail.com 7329988Snilay@cs.wisc.eduvoid 7335703SN/A$c_ident::stallBuffer(MessageBuffer* buf, Address addr) 73410451Snilay@cs.wisc.edu{ 7359536SAli.Saidi@ARM.com if (m_waiting_buffers.count(addr) == 0) { 7367524SN/A MsgVecType* msgVec = new MsgVecType; 7379096Sandreas.hansson@arm.com msgVec->resize(m_max_in_port_rank, NULL); 7386123SN/A m_waiting_buffers[addr] = msgVec; 7399134Ssaidi@eecs.umich.edu } 7409449SAli.Saidi@ARM.com (*(m_waiting_buffers[addr]))[m_cur_in_port_rank] = buf; 7415703SN/A} 7426123SN/A 7435703SN/Avoid 7449885Sstever@gmail.com$c_ident::wakeUpBuffers(Address addr) 7459988Snilay@cs.wisc.edu{ 7468464SN/A if (m_waiting_buffers.count(addr) > 0) { 7475703SN/A // 7489348SAli.Saidi@ARM.com // Wake up all possible lower rank (i.e. lower priority) buffers that could 7495703SN/A // be waiting on this message. 7505703SN/A // 7515703SN/A for (int in_port_rank = m_cur_in_port_rank - 1; 7525703SN/A in_port_rank >= 0; 7535703SN/A in_port_rank--) { 7545703SN/A if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) { 7555703SN/A (*(m_waiting_buffers[addr]))[in_port_rank]->reanalyzeMessages(addr); 7565703SN/A } 7575703SN/A } 7585703SN/A delete m_waiting_buffers[addr]; 7595703SN/A m_waiting_buffers.erase(addr); 7605703SN/A } 76110242Ssteve.reinhardt@amd.com} 76210451Snilay@cs.wisc.edu 76310451Snilay@cs.wisc.eduvoid 76410451Snilay@cs.wisc.edu$c_ident::wakeUpAllBuffers() 76510451Snilay@cs.wisc.edu{ 76610451Snilay@cs.wisc.edu // 76710451Snilay@cs.wisc.edu // Wake up all possible buffers that could be waiting on any message. 76810451Snilay@cs.wisc.edu // 76910451Snilay@cs.wisc.edu 77010451Snilay@cs.wisc.edu std::vector<MsgVecType*> wokeUpMsgVecs; 77110451Snilay@cs.wisc.edu 77210451Snilay@cs.wisc.edu if(m_waiting_buffers.size() > 0) { 77310451Snilay@cs.wisc.edu for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin(); 77410451Snilay@cs.wisc.edu buf_iter != m_waiting_buffers.end(); 77510451Snilay@cs.wisc.edu ++buf_iter) { 77610451Snilay@cs.wisc.edu for (MsgVecType::iterator vec_iter = buf_iter->second->begin(); 77710451Snilay@cs.wisc.edu vec_iter != buf_iter->second->end(); 77810451Snilay@cs.wisc.edu ++vec_iter) { 77910451Snilay@cs.wisc.edu if (*vec_iter != NULL) { 78010451Snilay@cs.wisc.edu (*vec_iter)->reanalyzeAllMessages(); 78110451Snilay@cs.wisc.edu } 78210451Snilay@cs.wisc.edu } 78310451Snilay@cs.wisc.edu wokeUpMsgVecs.push_back(buf_iter->second); 78410451Snilay@cs.wisc.edu } 78510451Snilay@cs.wisc.edu 7869536SAli.Saidi@ARM.com for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin(); 78710242Ssteve.reinhardt@amd.com wb_iter != wokeUpMsgVecs.end(); 78810451Snilay@cs.wisc.edu ++wb_iter) { 7899348SAli.Saidi@ARM.com delete (*wb_iter); 7909885Sstever@gmail.com } 7919620Snilay@cs.wisc.edu 7929885Sstever@gmail.com m_waiting_buffers.clear(); 7939885Sstever@gmail.com } 7949885Sstever@gmail.com} 7959885Sstever@gmail.com 79610513SAli.Saidi@ARM.comvoid 7979885Sstever@gmail.com$c_ident::blockOnQueue(Address addr, MessageBuffer* port) 79810451Snilay@cs.wisc.edu{ 7999988Snilay@cs.wisc.edu m_is_blocking = true; 8008983Snate@binkert.org m_block_map[addr] = port; 80110242Ssteve.reinhardt@amd.com} 8029536SAli.Saidi@ARM.com 80310242Ssteve.reinhardt@amd.comvoid 8045703SN/A$c_ident::unblock(Address addr) 80510242Ssteve.reinhardt@amd.com{ 8065703SN/A m_block_map.erase(addr); 8079348SAli.Saidi@ARM.com if (m_block_map.size() == 0) { 8089348SAli.Saidi@ARM.com m_is_blocking = false; 8099885Sstever@gmail.com } 8109885Sstever@gmail.com} 8119536SAli.Saidi@ARM.com 81210451Snilay@cs.wisc.eduvoid 81310242Ssteve.reinhardt@amd.com$c_ident::print(ostream& out) const 8149536SAli.Saidi@ARM.com{ 81510451Snilay@cs.wisc.edu out << "[$c_ident " << m_version << "]"; 8169988Snilay@cs.wisc.edu} 8179536SAli.Saidi@ARM.com 8189348SAli.Saidi@ARM.comvoid 81910242Ssteve.reinhardt@amd.com$c_ident::printConfig(ostream& out) const 8209536SAli.Saidi@ARM.com{ 82110242Ssteve.reinhardt@amd.com out << "$c_ident config: " << m_name << endl; 82210451Snilay@cs.wisc.edu out << " version: " << m_version << endl; 82310242Ssteve.reinhardt@amd.com map<string, string>::const_iterator it; 82410242Ssteve.reinhardt@amd.com for (it = m_cfg.begin(); it != m_cfg.end(); it++) 82510242Ssteve.reinhardt@amd.com out << " " << it->first << ": " << it->second << endl; 8269536SAli.Saidi@ARM.com} 82710242Ssteve.reinhardt@amd.com 82810451Snilay@cs.wisc.eduvoid 82910451Snilay@cs.wisc.edu$c_ident::printStats(ostream& out) const 83010451Snilay@cs.wisc.edu{ 83110451Snilay@cs.wisc.edu''') 83210242Ssteve.reinhardt@amd.com # 83310242Ssteve.reinhardt@amd.com # Cache and Memory Controllers have specific profilers associated with 83410242Ssteve.reinhardt@amd.com # them. Print out these stats before dumping state transition stats. 8358983Snate@binkert.org # 8365703SN/A for param in self.config_parameters: 8375703SN/A if param.type_ast.type.ident == "CacheMemory" or \ 8385703SN/A param.type_ast.type.ident == "DirectoryMemory" or \ 8395703SN/A param.type_ast.type.ident == "MemoryControl": 8405703SN/A assert(param.pointer) 8419988Snilay@cs.wisc.edu code(' m_${{param.ident}}_ptr->printStats(out);') 8425703SN/A 8435703SN/A code(''' 8445703SN/A if (m_version == 0) { 8455703SN/A s_profileDumper.dumpStats(out); 8469988Snilay@cs.wisc.edu } 84710513SAli.Saidi@ARM.com} 8485703SN/A 8495703SN/Avoid $c_ident::clearStats() { 8505703SN/A''') 8515703SN/A # 8529988Snilay@cs.wisc.edu # Cache and Memory Controllers have specific profilers associated with 8535703SN/A # them. These stats must be cleared too. 8545703SN/A # 8555703SN/A for param in self.config_parameters: 8565703SN/A if param.type_ast.type.ident == "CacheMemory" or \ 8575703SN/A param.type_ast.type.ident == "MemoryControl": 8585703SN/A assert(param.pointer) 8595703SN/A code(' m_${{param.ident}}_ptr->clearStats();') 8605703SN/A 8619988Snilay@cs.wisc.edu code(''' 8625703SN/A m_profiler.clearStats(); 8635703SN/A} 8645703SN/A''') 8655703SN/A 8665703SN/A if self.EntryType != None: 8679885Sstever@gmail.com code(''' 8685703SN/A 8695703SN/A// Set and Reset for cache_entry variable 8709988Snilay@cs.wisc.eduvoid 8715703SN/A$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 8729348SAli.Saidi@ARM.com{ 8735703SN/A m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 8745703SN/A} 8755703SN/A 8768983Snate@binkert.orgvoid 8775703SN/A$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 8785703SN/A{ 8795703SN/A m_cache_entry_ptr = 0; 8809885Sstever@gmail.com} 8819988Snilay@cs.wisc.edu''') 8825703SN/A 8839348SAli.Saidi@ARM.com if self.TBEType != None: 8845703SN/A code(''' 8855703SN/A 8868983Snate@binkert.org// Set and Reset for tbe variable 8875703SN/Avoid 8885703SN/A$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 8895703SN/A{ 8905703SN/A m_tbe_ptr = m_new_tbe; 8915876SN/A} 8925703SN/A 8935703SN/Avoid 8945876SN/A$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 8955703SN/A{ 8965703SN/A m_tbe_ptr = NULL; 8975876SN/A} 8985703SN/A''') 8995703SN/A 9005876SN/A code(''' 9015703SN/A 9025703SN/Avoid 9035876SN/A$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr) 9045703SN/A{ 9055703SN/A''') 9065876SN/A # 9075703SN/A # Record cache contents for all associated caches. 9085703SN/A # 9095703SN/A code.indent() 9109988Snilay@cs.wisc.edu for param in self.config_parameters: 9115703SN/A if param.type_ast.type.ident == "CacheMemory": 9125703SN/A assert(param.pointer) 9135703SN/A code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);') 9145703SN/A 9155703SN/A code.dedent() 9165703SN/A code(''' 9175703SN/A} 9185703SN/A 9195703SN/A// Actions 92010451Snilay@cs.wisc.edu''') 9219988Snilay@cs.wisc.edu if self.TBEType != None and self.EntryType != None: 9229988Snilay@cs.wisc.edu for action in self.actions.itervalues(): 9239988Snilay@cs.wisc.edu if "c_code" not in action: 9249988Snilay@cs.wisc.edu continue 9259988Snilay@cs.wisc.edu 9269988Snilay@cs.wisc.edu code(''' 9279988Snilay@cs.wisc.edu/** \\brief ${{action.desc}} */ 9289988Snilay@cs.wisc.eduvoid 9299988Snilay@cs.wisc.edu$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 9309988Snilay@cs.wisc.edu{ 9319988Snilay@cs.wisc.edu DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9329988Snilay@cs.wisc.edu ${{action["c_code"]}} 9339988Snilay@cs.wisc.edu} 9349988Snilay@cs.wisc.edu 9359988Snilay@cs.wisc.edu''') 9365703SN/A elif self.TBEType != None: 9375703SN/A for action in self.actions.itervalues(): 9389988Snilay@cs.wisc.edu if "c_code" not in action: 9399988Snilay@cs.wisc.edu continue 9409988Snilay@cs.wisc.edu 9419988Snilay@cs.wisc.edu code(''' 9429988Snilay@cs.wisc.edu/** \\brief ${{action.desc}} */ 9439988Snilay@cs.wisc.eduvoid 9449988Snilay@cs.wisc.edu$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr) 9459988Snilay@cs.wisc.edu{ 9469988Snilay@cs.wisc.edu DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9479988Snilay@cs.wisc.edu ${{action["c_code"]}} 9489988Snilay@cs.wisc.edu} 9499988Snilay@cs.wisc.edu 9509988Snilay@cs.wisc.edu''') 9519988Snilay@cs.wisc.edu elif self.EntryType != None: 9529988Snilay@cs.wisc.edu for action in self.actions.itervalues(): 9539988Snilay@cs.wisc.edu if "c_code" not in action: 9549988Snilay@cs.wisc.edu continue 9555703SN/A 9565703SN/A code(''' 9575703SN/A/** \\brief ${{action.desc}} */ 9585703SN/Avoid 9595703SN/A$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 9605703SN/A{ 9615703SN/A DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9629885Sstever@gmail.com ${{action["c_code"]}} 9635703SN/A} 9645703SN/A 9655703SN/A''') 9665703SN/A else: 9675703SN/A for action in self.actions.itervalues(): 9685703SN/A if "c_code" not in action: 9695703SN/A continue 9705703SN/A 9719988Snilay@cs.wisc.edu code(''' 9725703SN/A/** \\brief ${{action.desc}} */ 9735703SN/Avoid 9745703SN/A$c_ident::${{action.ident}}(const Address& addr) 9755703SN/A{ 9765703SN/A DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9779348SAli.Saidi@ARM.com ${{action["c_code"]}} 9785703SN/A} 9795703SN/A 9805703SN/A''') 9815703SN/A for func in self.functions: 9825703SN/A code(func.generateCode()) 9835703SN/A 9845703SN/A code.write(path, "%s.cc" % c_ident) 9855703SN/A 9865703SN/A def printCWakeup(self, path): 9875703SN/A '''Output the wakeup loop for the events''' 9888983Snate@binkert.org 9898983Snate@binkert.org code = self.symtab.codeFormatter() 9908983Snate@binkert.org ident = self.ident 9915703SN/A 9925703SN/A code(''' 9935703SN/A// Auto generated C++ code started by $__file__:$__line__ 9949885Sstever@gmail.com// ${ident}: ${{self.short}} 9959988Snilay@cs.wisc.edu 9968464SN/A#include <sys/types.h> 9975703SN/A#include <unistd.h> 9989348SAli.Saidi@ARM.com 9995703SN/A#include <cassert> 10005703SN/A 10015703SN/A#include "base/misc.hh" 10025703SN/A#include "debug/RubySlicc.hh" 10035703SN/A#include "mem/protocol/${ident}_Controller.hh" 10045703SN/A#include "mem/protocol/${ident}_Event.hh" 10055703SN/A#include "mem/protocol/${ident}_State.hh" 10065703SN/A#include "mem/protocol/Types.hh" 10075703SN/A#include "mem/ruby/common/Global.hh" 10088983Snate@binkert.org#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" 10095703SN/A#include "mem/ruby/system/System.hh" 10105703SN/A 10115703SN/Ausing namespace std; 10129885Sstever@gmail.com 10139988Snilay@cs.wisc.eduvoid 10148464SN/A${ident}_Controller::wakeup() 10155703SN/A{ 10169348SAli.Saidi@ARM.com int counter = 0; 10175703SN/A while (true) { 10185703SN/A // Some cases will put us into an infinite loop without this limit 10195703SN/A assert(counter <= m_transitions_per_cycle); 10205703SN/A if (counter == m_transitions_per_cycle) { 10215703SN/A // Count how often we are fully utilized 10225703SN/A g_system_ptr->getProfiler()->controllerBusy(m_machineID); 10235703SN/A 10245703SN/A // Wakeup in another cycle and try again 10255703SN/A g_eventQueue_ptr->scheduleEvent(this, 1); 10268983Snate@binkert.org break; 10275703SN/A } 10285703SN/A''') 10295703SN/A 10309885Sstever@gmail.com code.indent() 10319988Snilay@cs.wisc.edu code.indent() 10328464SN/A 10335703SN/A # InPorts 10349348SAli.Saidi@ARM.com # 10355703SN/A for port in self.in_ports: 10365703SN/A code.indent() 10375703SN/A code('// ${ident}InPort $port') 10385703SN/A if port.pairs.has_key("rank"): 10395703SN/A code('m_cur_in_port_rank = ${{port.pairs["rank"]}};') 10405703SN/A else: 10415703SN/A code('m_cur_in_port_rank = 0;') 10425703SN/A code('${{port["c_code_in_port"]}}') 10435703SN/A code.dedent() 10448983Snate@binkert.org 10455703SN/A code('') 10465703SN/A 10475703SN/A code.dedent() 10489885Sstever@gmail.com code.dedent() 10499988Snilay@cs.wisc.edu code(''' 10508464SN/A break; // If we got this far, we have nothing left todo 10515703SN/A } 10529348SAli.Saidi@ARM.com // g_eventQueue_ptr->scheduleEvent(this, 1); 10535703SN/A} 10545703SN/A''') 10555703SN/A 10565703SN/A code.write(path, "%s_Wakeup.cc" % self.ident) 10575703SN/A 10585703SN/A def printCSwitch(self, path): 10595703SN/A '''Output switch statement for transition table''' 10605703SN/A 10615703SN/A code = self.symtab.codeFormatter() 10628983Snate@binkert.org ident = self.ident 10635703SN/A 10645703SN/A code(''' 10655703SN/A// Auto generated C++ code started by $__file__:$__line__ 10669885Sstever@gmail.com// ${ident}: ${{self.short}} 10679988Snilay@cs.wisc.edu 10688464SN/A#include <cassert> 10695703SN/A 10709348SAli.Saidi@ARM.com#include "base/misc.hh" 10715703SN/A#include "base/trace.hh" 10725703SN/A#include "debug/ProtocolTrace.hh" 10735703SN/A#include "debug/RubyGenerated.hh" 10745703SN/A#include "mem/protocol/${ident}_Controller.hh" 10755703SN/A#include "mem/protocol/${ident}_Event.hh" 10765703SN/A#include "mem/protocol/${ident}_State.hh" 10775703SN/A#include "mem/protocol/Types.hh" 10785703SN/A#include "mem/ruby/common/Global.hh" 10795703SN/A#include "mem/ruby/system/System.hh" 10808983Snate@binkert.org 10815703SN/A#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 10825703SN/A 10835703SN/A#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 10849885Sstever@gmail.com#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 10859988Snilay@cs.wisc.edu 10868464SN/ATransitionResult 10875703SN/A${ident}_Controller::doTransition(${ident}_Event event, 10889348SAli.Saidi@ARM.com''') 10895703SN/A if self.EntryType != None: 10905703SN/A code(''' 10915703SN/A ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 10925703SN/A''') 10935703SN/A if self.TBEType != None: 10945703SN/A code(''' 10955703SN/A ${{self.TBEType.c_ident}}* m_tbe_ptr, 10965703SN/A''') 10975703SN/A code(''' 10988983Snate@binkert.org const Address &addr) 10995703SN/A{ 11005703SN/A''') 11015703SN/A if self.TBEType != None and self.EntryType != None: 11029885Sstever@gmail.com code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 11039988Snilay@cs.wisc.edu elif self.TBEType != None: 11048464SN/A code('${ident}_State state = getState(m_tbe_ptr, addr);') 11055703SN/A elif self.EntryType != None: 11069348SAli.Saidi@ARM.com code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 11075703SN/A else: 11085703SN/A code('${ident}_State state = getState(addr);') 11095703SN/A 11105703SN/A code(''' 11115703SN/A ${ident}_State next_state = state; 11125703SN/A 11135703SN/A DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 11145703SN/A *this, 11155703SN/A g_eventQueue_ptr->getTime(), 11168983Snate@binkert.org ${ident}_State_to_string(state), 11175703SN/A ${ident}_Event_to_string(event), 11185703SN/A addr); 11195703SN/A 11209885Sstever@gmail.com TransitionResult result = 11219988Snilay@cs.wisc.edu''') 11228464SN/A if self.TBEType != None and self.EntryType != None: 11235703SN/A code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 11249348SAli.Saidi@ARM.com elif self.TBEType != None: 11255703SN/A code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 11265703SN/A elif self.EntryType != None: 11275703SN/A code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 11285703SN/A else: 11295703SN/A code('doTransitionWorker(event, state, next_state, addr);') 11305703SN/A 11315703SN/A code(''' 11325703SN/A if (result == TransitionResult_Valid) { 11335703SN/A DPRINTF(RubyGenerated, "next_state: %s\\n", 11348983Snate@binkert.org ${ident}_State_to_string(next_state)); 11355703SN/A m_profiler.countTransition(state, event); 11365703SN/A DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 11375703SN/A curTick(), m_version, "${ident}", 11389885Sstever@gmail.com ${ident}_Event_to_string(event), 11399988Snilay@cs.wisc.edu ${ident}_State_to_string(state), 11408464SN/A ${ident}_State_to_string(next_state), 11415703SN/A addr, GET_TRANSITION_COMMENT()); 11429348SAli.Saidi@ARM.com 11435703SN/A CLEAR_TRANSITION_COMMENT(); 11445703SN/A''') 11455703SN/A if self.TBEType != None and self.EntryType != None: 11465703SN/A code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 11475703SN/A code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 11485703SN/A elif self.TBEType != None: 11495703SN/A code('setState(m_tbe_ptr, addr, next_state);') 11505703SN/A code('setAccessPermission(addr, next_state);') 11515703SN/A elif self.EntryType != None: 11528983Snate@binkert.org code('setState(m_cache_entry_ptr, addr, next_state);') 11535703SN/A code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 11545703SN/A else: 11555703SN/A code('setState(addr, next_state);') 11569885Sstever@gmail.com code('setAccessPermission(addr, next_state);') 11579988Snilay@cs.wisc.edu 11588464SN/A code(''' 11595703SN/A } else if (result == TransitionResult_ResourceStall) { 11609348SAli.Saidi@ARM.com DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 11615703SN/A curTick(), m_version, "${ident}", 11625703SN/A ${ident}_Event_to_string(event), 11635703SN/A ${ident}_State_to_string(state), 11645703SN/A ${ident}_State_to_string(next_state), 11655703SN/A addr, "Resource Stall"); 11665703SN/A } else if (result == TransitionResult_ProtocolStall) { 11675703SN/A DPRINTF(RubyGenerated, "stalling\\n"); 11685703SN/A DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 11695703SN/A curTick(), m_version, "${ident}", 11708983Snate@binkert.org ${ident}_Event_to_string(event), 11715703SN/A ${ident}_State_to_string(state), 11725703SN/A ${ident}_State_to_string(next_state), 11735703SN/A addr, "Protocol Stall"); 11749885Sstever@gmail.com } 11759988Snilay@cs.wisc.edu 11768464SN/A return result; 11775703SN/A} 11789348SAli.Saidi@ARM.com 11795703SN/ATransitionResult 11805703SN/A${ident}_Controller::doTransitionWorker(${ident}_Event event, 11815703SN/A ${ident}_State state, 11825703SN/A ${ident}_State& next_state, 11835703SN/A''') 11845703SN/A 11855703SN/A if self.TBEType != None: 11865703SN/A code(''' 11875703SN/A ${{self.TBEType.c_ident}}*& m_tbe_ptr, 11888983Snate@binkert.org''') 11895703SN/A if self.EntryType != None: 11905703SN/A code(''' 11915703SN/A ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 11929885Sstever@gmail.com''') 11939988Snilay@cs.wisc.edu code(''' 11948464SN/A const Address& addr) 11955703SN/A{ 11969348SAli.Saidi@ARM.com switch(HASH_FUN(state, event)) { 11975703SN/A''') 11985703SN/A 11995703SN/A # This map will allow suppress generating duplicate code 12005703SN/A cases = orderdict() 12015703SN/A 12025703SN/A for trans in self.transitions: 12035703SN/A case_string = "%s_State_%s, %s_Event_%s" % \ 12045703SN/A (self.ident, trans.state.ident, self.ident, trans.event.ident) 12055703SN/A 12068983Snate@binkert.org case = self.symtab.codeFormatter() 12075703SN/A # Only set next_state if it changes 12085703SN/A if trans.state != trans.nextState: 12095703SN/A ns_ident = trans.nextState.ident 12109885Sstever@gmail.com case('next_state = ${ident}_State_${ns_ident};') 12119988Snilay@cs.wisc.edu 12128464SN/A actions = trans.actions 12135703SN/A 12149348SAli.Saidi@ARM.com # Check for resources 12155703SN/A case_sorter = [] 12165703SN/A res = trans.resources 12175703SN/A for key,val in res.iteritems(): 12185703SN/A if key.type.ident != "DNUCAStopTable": 12195703SN/A val = ''' 12205703SN/Aif (!%s.areNSlotsAvailable(%s)) 12215703SN/A return TransitionResult_ResourceStall; 12225703SN/A''' % (key.code, val) 12235703SN/A case_sorter.append(val) 12248983Snate@binkert.org 12255703SN/A 12265703SN/A # Emit the code sequences in a sorted order. This makes the 12275703SN/A # output deterministic (without this the output order can vary 12289885Sstever@gmail.com # since Map's keys() on a vector of pointers is not deterministic 12299988Snilay@cs.wisc.edu for c in sorted(case_sorter): 12308464SN/A case("$c") 12315703SN/A 12329348SAli.Saidi@ARM.com # Figure out if we stall 12335703SN/A stall = False 12345703SN/A for action in actions: 12355703SN/A if action.ident == "z_stall": 12365703SN/A stall = True 12375703SN/A break 12385703SN/A 12395703SN/A if stall: 12405703SN/A case('return TransitionResult_ProtocolStall;') 12415703SN/A else: 12428983Snate@binkert.org if self.TBEType != None and self.EntryType != None: 12435703SN/A for action in actions: 12445703SN/A case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 12455703SN/A elif self.TBEType != None: 12469885Sstever@gmail.com for action in actions: 12479988Snilay@cs.wisc.edu case('${{action.ident}}(m_tbe_ptr, addr);') 12488464SN/A elif self.EntryType != None: 12495703SN/A for action in actions: 12509348SAli.Saidi@ARM.com case('${{action.ident}}(m_cache_entry_ptr, addr);') 12515703SN/A else: 12525703SN/A for action in actions: 12535703SN/A case('${{action.ident}}(addr);') 12545703SN/A case('return TransitionResult_Valid;') 12555703SN/A 12565703SN/A case = str(case) 12575703SN/A 12585703SN/A # Look to see if this transition code is unique. 12595703SN/A if case not in cases: 12608983Snate@binkert.org cases[case] = [] 12615703SN/A 12625703SN/A cases[case].append(case_string) 12635703SN/A 12649885Sstever@gmail.com # Walk through all of the unique code blocks and spit out the 12659988Snilay@cs.wisc.edu # corresponding case statement elements 12668464SN/A for case,transitions in cases.iteritems(): 12675703SN/A # Iterative over all the multiple transitions that share 12689348SAli.Saidi@ARM.com # the same code 12695703SN/A for trans in transitions: 12705703SN/A code(' case HASH_FUN($trans):') 12715703SN/A code(' $case') 12725703SN/A 12735703SN/A code(''' 12745703SN/A default: 12755703SN/A fatal("Invalid transition\\n" 12765703SN/A "%s time: %d addr: %s event: %s state: %s\\n", 12775703SN/A name(), g_eventQueue_ptr->getTime(), addr, event, state); 12788983Snate@binkert.org } 12795703SN/A return TransitionResult_Valid; 12805703SN/A} 12815703SN/A''') 12829885Sstever@gmail.com code.write(path, "%s_Transitions.cc" % self.ident) 12839988Snilay@cs.wisc.edu 12848464SN/A def printProfileDumperHH(self, path): 12855703SN/A code = self.symtab.codeFormatter() 12869348SAli.Saidi@ARM.com ident = self.ident 12875703SN/A 12885703SN/A code(''' 12895703SN/A// Auto generated C++ code started by $__file__:$__line__ 12905703SN/A// ${ident}: ${{self.short}} 12915703SN/A 12925703SN/A#ifndef __${ident}_PROFILE_DUMPER_HH__ 12935703SN/A#define __${ident}_PROFILE_DUMPER_HH__ 12945703SN/A 12955703SN/A#include <cassert> 12968983Snate@binkert.org#include <iostream> 12975703SN/A#include <vector> 12985703SN/A 12995703SN/A#include "${ident}_Event.hh" 13009885Sstever@gmail.com#include "${ident}_Profiler.hh" 13019988Snilay@cs.wisc.edu 13028464SN/Atypedef std::vector<${ident}_Profiler *> ${ident}_profilers; 13035703SN/A 13049348SAli.Saidi@ARM.comclass ${ident}_ProfileDumper 13055703SN/A{ 13065703SN/A public: 13075703SN/A ${ident}_ProfileDumper(); 13085703SN/A void registerProfiler(${ident}_Profiler* profiler); 13095703SN/A void dumpStats(std::ostream& out) const; 13105703SN/A 13115703SN/A private: 13125703SN/A ${ident}_profilers m_profilers; 13135703SN/A}; 13148983Snate@binkert.org 13155703SN/A#endif // __${ident}_PROFILE_DUMPER_HH__ 13165703SN/A''') 13175703SN/A code.write(path, "%s_ProfileDumper.hh" % self.ident) 13189885Sstever@gmail.com 13199988Snilay@cs.wisc.edu def printProfileDumperCC(self, path): 13208464SN/A code = self.symtab.codeFormatter() 13215703SN/A ident = self.ident 13229348SAli.Saidi@ARM.com 13235703SN/A code(''' 13245703SN/A// Auto generated C++ code started by $__file__:$__line__ 13255703SN/A// ${ident}: ${{self.short}} 13265703SN/A 13275703SN/A#include "mem/protocol/${ident}_ProfileDumper.hh" 13285703SN/A 13295703SN/A${ident}_ProfileDumper::${ident}_ProfileDumper() 13305703SN/A{ 13315703SN/A} 13328983Snate@binkert.org 13335703SN/Avoid 13345703SN/A${ident}_ProfileDumper::registerProfiler(${ident}_Profiler* profiler) 13355703SN/A{ 13369885Sstever@gmail.com m_profilers.push_back(profiler); 13375703SN/A} 13389988Snilay@cs.wisc.edu 13395703SN/Avoid 13409348SAli.Saidi@ARM.com${ident}_ProfileDumper::dumpStats(std::ostream& out) const 13415703SN/A{ 13428983Snate@binkert.org out << " --- ${ident} ---\\n"; 13435703SN/A out << " - Event Counts -\\n"; 13445703SN/A for (${ident}_Event event = ${ident}_Event_FIRST; 13455703SN/A event < ${ident}_Event_NUM; 13465703SN/A ++event) { 13475876SN/A out << (${ident}_Event) event << " ["; 13485703SN/A uint64 total = 0; 13495703SN/A for (int i = 0; i < m_profilers.size(); i++) { 13505876SN/A out << m_profilers[i]->getEventCount(event) << " "; 13515703SN/A total += m_profilers[i]->getEventCount(event); 13525703SN/A } 13535876SN/A out << "] " << total << "\\n"; 13545703SN/A } 13555703SN/A out << "\\n"; 13565876SN/A out << " - Transitions -\\n"; 13575703SN/A for (${ident}_State state = ${ident}_State_FIRST; 13585703SN/A state < ${ident}_State_NUM; 13595876SN/A ++state) { 13605703SN/A for (${ident}_Event event = ${ident}_Event_FIRST; 13615703SN/A event < ${ident}_Event_NUM; 13625876SN/A ++event) { 13635703SN/A if (m_profilers[0]->isPossible(state, event)) { 13645703SN/A out << (${ident}_State) state << " " 13655703SN/A << (${ident}_Event) event << " ["; 13669988Snilay@cs.wisc.edu uint64 total = 0; 13675703SN/A for (int i = 0; i < m_profilers.size(); i++) { 13685703SN/A out << m_profilers[i]->getTransitionCount(state, event) << " "; 13695703SN/A total += m_profilers[i]->getTransitionCount(state, event); 13705703SN/A } 13715703SN/A out << "] " << total << "\\n"; 13725703SN/A } 13735703SN/A } 13745703SN/A out << "\\n"; 13755703SN/A } 137610451Snilay@cs.wisc.edu} 13779988Snilay@cs.wisc.edu''') 13789988Snilay@cs.wisc.edu code.write(path, "%s_ProfileDumper.cc" % self.ident) 13799988Snilay@cs.wisc.edu 13809988Snilay@cs.wisc.edu def printProfilerHH(self, path): 13819988Snilay@cs.wisc.edu code = self.symtab.codeFormatter() 13829988Snilay@cs.wisc.edu ident = self.ident 13839988Snilay@cs.wisc.edu 13849988Snilay@cs.wisc.edu code(''' 13859988Snilay@cs.wisc.edu// Auto generated C++ code started by $__file__:$__line__ 13869988Snilay@cs.wisc.edu// ${ident}: ${{self.short}} 13879988Snilay@cs.wisc.edu 13889988Snilay@cs.wisc.edu#ifndef __${ident}_PROFILER_HH__ 13899988Snilay@cs.wisc.edu#define __${ident}_PROFILER_HH__ 13909988Snilay@cs.wisc.edu 13919988Snilay@cs.wisc.edu#include <cassert> 13925703SN/A#include <iostream> 13935703SN/A 13949988Snilay@cs.wisc.edu#include "mem/protocol/${ident}_Event.hh" 13959988Snilay@cs.wisc.edu#include "mem/protocol/${ident}_State.hh" 13969988Snilay@cs.wisc.edu#include "mem/ruby/common/TypeDefines.hh" 13979988Snilay@cs.wisc.edu 13989988Snilay@cs.wisc.educlass ${ident}_Profiler 13999988Snilay@cs.wisc.edu{ 14009988Snilay@cs.wisc.edu public: 14019988Snilay@cs.wisc.edu ${ident}_Profiler(); 14029988Snilay@cs.wisc.edu void setVersion(int version); 14039988Snilay@cs.wisc.edu void countTransition(${ident}_State state, ${ident}_Event event); 14049988Snilay@cs.wisc.edu void possibleTransition(${ident}_State state, ${ident}_Event event); 14059988Snilay@cs.wisc.edu uint64 getEventCount(${ident}_Event event); 14069988Snilay@cs.wisc.edu bool isPossible(${ident}_State state, ${ident}_Event event); 14079988Snilay@cs.wisc.edu uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); 14089988Snilay@cs.wisc.edu void clearStats(); 14099988Snilay@cs.wisc.edu 14109988Snilay@cs.wisc.edu private: 14115703SN/A int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 14125703SN/A int m_event_counters[${ident}_Event_NUM]; 14135703SN/A bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 14145703SN/A int m_version; 14155703SN/A}; 14165703SN/A 14175703SN/A#endif // __${ident}_PROFILER_HH__ 14189885Sstever@gmail.com''') 14195703SN/A code.write(path, "%s_Profiler.hh" % self.ident) 14207761SN/A 14215703SN/A def printProfilerCC(self, path): 14229988Snilay@cs.wisc.edu code = self.symtab.codeFormatter() 14237761SN/A ident = self.ident 14245703SN/A 14255703SN/A code(''' 14265703SN/A// Auto generated C++ code started by $__file__:$__line__ 14279348SAli.Saidi@ARM.com// ${ident}: ${{self.short}} 14285703SN/A 14295703SN/A#include <cassert> 14308983Snate@binkert.org 14318983Snate@binkert.org#include "mem/protocol/${ident}_Profiler.hh" 14328983Snate@binkert.org 14335703SN/A${ident}_Profiler::${ident}_Profiler() 14345703SN/A{ 14355703SN/A for (int state = 0; state < ${ident}_State_NUM; state++) { 14369885Sstever@gmail.com for (int event = 0; event < ${ident}_Event_NUM; event++) { 14379988Snilay@cs.wisc.edu m_possible[state][event] = false; 14385703SN/A m_counters[state][event] = 0; 14395703SN/A } 14409348SAli.Saidi@ARM.com } 14415703SN/A for (int event = 0; event < ${ident}_Event_NUM; event++) { 14425703SN/A m_event_counters[event] = 0; 14435703SN/A } 14445703SN/A} 14458983Snate@binkert.org 14465703SN/Avoid 14475703SN/A${ident}_Profiler::setVersion(int version) 14485703SN/A{ 14499885Sstever@gmail.com m_version = version; 14509988Snilay@cs.wisc.edu} 14515703SN/A 14529348SAli.Saidi@ARM.comvoid 14535703SN/A${ident}_Profiler::clearStats() 14545703SN/A{ 14558983Snate@binkert.org for (int state = 0; state < ${ident}_State_NUM; state++) { 14565703SN/A for (int event = 0; event < ${ident}_Event_NUM; event++) { 14575703SN/A m_counters[state][event] = 0; 14585703SN/A } 14595703SN/A } 14609885Sstever@gmail.com 14619988Snilay@cs.wisc.edu for (int event = 0; event < ${ident}_Event_NUM; event++) { 14629885Sstever@gmail.com m_event_counters[event] = 0; 14639348SAli.Saidi@ARM.com } 14645703SN/A} 14655703SN/Avoid 14665703SN/A${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) 14675703SN/A{ 14685703SN/A assert(m_possible[state][event]); 14695703SN/A m_counters[state][event]++; 14705703SN/A m_event_counters[event]++; 14719885Sstever@gmail.com} 14729988Snilay@cs.wisc.eduvoid 14735703SN/A${ident}_Profiler::possibleTransition(${ident}_State state, 14749348SAli.Saidi@ARM.com ${ident}_Event event) 14755703SN/A{ 14765703SN/A m_possible[state][event] = true; 14775703SN/A} 14788983Snate@binkert.org 14795703SN/Auint64 14809885Sstever@gmail.com${ident}_Profiler::getEventCount(${ident}_Event event) 14819885Sstever@gmail.com{ 14829988Snilay@cs.wisc.edu return m_event_counters[event]; 14839885Sstever@gmail.com} 14849885Sstever@gmail.com 1485bool 1486${ident}_Profiler::isPossible(${ident}_State state, ${ident}_Event event) 1487{ 1488 return m_possible[state][event]; 1489} 1490 1491uint64 1492${ident}_Profiler::getTransitionCount(${ident}_State state, 1493 ${ident}_Event event) 1494{ 1495 return m_counters[state][event]; 1496} 1497 1498''') 1499 code.write(path, "%s_Profiler.cc" % self.ident) 1500 1501 # ************************** 1502 # ******* HTML Files ******* 1503 # ************************** 1504 def frameRef(self, click_href, click_target, over_href, over_num, text): 1505 code = self.symtab.codeFormatter(fix_newlines=False) 1506 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1507 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1508 parent.frames[$over_num].location='$over_href' 1509 }\"> 1510 ${{html.formatShorthand(text)}} 1511 </A>""") 1512 return str(code) 1513 1514 def writeHTMLFiles(self, path): 1515 # Create table with no row hilighted 1516 self.printHTMLTransitions(path, None) 1517 1518 # Generate transition tables 1519 for state in self.states.itervalues(): 1520 self.printHTMLTransitions(path, state) 1521 1522 # Generate action descriptions 1523 for action in self.actions.itervalues(): 1524 name = "%s_action_%s.html" % (self.ident, action.ident) 1525 code = html.createSymbol(action, "Action") 1526 code.write(path, name) 1527 1528 # Generate state descriptions 1529 for state in self.states.itervalues(): 1530 name = "%s_State_%s.html" % (self.ident, state.ident) 1531 code = html.createSymbol(state, "State") 1532 code.write(path, name) 1533 1534 # Generate event descriptions 1535 for event in self.events.itervalues(): 1536 name = "%s_Event_%s.html" % (self.ident, event.ident) 1537 code = html.createSymbol(event, "Event") 1538 code.write(path, name) 1539 1540 def printHTMLTransitions(self, path, active_state): 1541 code = self.symtab.codeFormatter() 1542 1543 code(''' 1544<HTML> 1545<BODY link="blue" vlink="blue"> 1546 1547<H1 align="center">${{html.formatShorthand(self.short)}}: 1548''') 1549 code.indent() 1550 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1551 mid = machine.ident 1552 if i != 0: 1553 extra = " - " 1554 else: 1555 extra = "" 1556 if machine == self: 1557 code('$extra$mid') 1558 else: 1559 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1560 code.dedent() 1561 1562 code(""" 1563</H1> 1564 1565<TABLE border=1> 1566<TR> 1567 <TH> </TH> 1568""") 1569 1570 for event in self.events.itervalues(): 1571 href = "%s_Event_%s.html" % (self.ident, event.ident) 1572 ref = self.frameRef(href, "Status", href, "1", event.short) 1573 code('<TH bgcolor=white>$ref</TH>') 1574 1575 code('</TR>') 1576 # -- Body of table 1577 for state in self.states.itervalues(): 1578 # -- Each row 1579 if state == active_state: 1580 color = "yellow" 1581 else: 1582 color = "white" 1583 1584 click = "%s_table_%s.html" % (self.ident, state.ident) 1585 over = "%s_State_%s.html" % (self.ident, state.ident) 1586 text = html.formatShorthand(state.short) 1587 ref = self.frameRef(click, "Table", over, "1", state.short) 1588 code(''' 1589<TR> 1590 <TH bgcolor=$color>$ref</TH> 1591''') 1592 1593 # -- One column for each event 1594 for event in self.events.itervalues(): 1595 trans = self.table.get((state,event), None) 1596 if trans is None: 1597 # This is the no transition case 1598 if state == active_state: 1599 color = "#C0C000" 1600 else: 1601 color = "lightgrey" 1602 1603 code('<TD bgcolor=$color> </TD>') 1604 continue 1605 1606 next = trans.nextState 1607 stall_action = False 1608 1609 # -- Get the actions 1610 for action in trans.actions: 1611 if action.ident == "z_stall" or \ 1612 action.ident == "zz_recycleMandatoryQueue": 1613 stall_action = True 1614 1615 # -- Print out "actions/next-state" 1616 if stall_action: 1617 if state == active_state: 1618 color = "#C0C000" 1619 else: 1620 color = "lightgrey" 1621 1622 elif active_state and next.ident == active_state.ident: 1623 color = "aqua" 1624 elif state == active_state: 1625 color = "yellow" 1626 else: 1627 color = "white" 1628 1629 code('<TD bgcolor=$color>') 1630 for action in trans.actions: 1631 href = "%s_action_%s.html" % (self.ident, action.ident) 1632 ref = self.frameRef(href, "Status", href, "1", 1633 action.short) 1634 code(' $ref') 1635 if next != state: 1636 if trans.actions: 1637 code('/') 1638 click = "%s_table_%s.html" % (self.ident, next.ident) 1639 over = "%s_State_%s.html" % (self.ident, next.ident) 1640 ref = self.frameRef(click, "Table", over, "1", next.short) 1641 code("$ref") 1642 code("</TD>") 1643 1644 # -- Each row 1645 if state == active_state: 1646 color = "yellow" 1647 else: 1648 color = "white" 1649 1650 click = "%s_table_%s.html" % (self.ident, state.ident) 1651 over = "%s_State_%s.html" % (self.ident, state.ident) 1652 ref = self.frameRef(click, "Table", over, "1", state.short) 1653 code(''' 1654 <TH bgcolor=$color>$ref</TH> 1655</TR> 1656''') 1657 code(''' 1658<!- Column footer-> 1659<TR> 1660 <TH> </TH> 1661''') 1662 1663 for event in self.events.itervalues(): 1664 href = "%s_Event_%s.html" % (self.ident, event.ident) 1665 ref = self.frameRef(href, "Status", href, "1", event.short) 1666 code('<TH bgcolor=white>$ref</TH>') 1667 code(''' 1668</TR> 1669</TABLE> 1670</BODY></HTML> 1671''') 1672 1673 1674 if active_state: 1675 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1676 else: 1677 name = "%s_table.html" % self.ident 1678 code.write(path, name) 1679 1680__all__ = [ "StateMachine" ] 1681