StateMachine.py revision 11111
16657Snate@binkert.org# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 26657Snate@binkert.org# Copyright (c) 2009 The Hewlett-Packard Development Company 36657Snate@binkert.org# Copyright (c) 2013 Advanced Micro Devices, Inc. 46657Snate@binkert.org# All rights reserved. 56657Snate@binkert.org# 66657Snate@binkert.org# Redistribution and use in source and binary forms, with or without 76657Snate@binkert.org# modification, are permitted provided that the following conditions are 86657Snate@binkert.org# met: redistributions of source code must retain the above copyright 96657Snate@binkert.org# notice, this list of conditions and the following disclaimer; 106657Snate@binkert.org# redistributions in binary form must reproduce the above copyright 116657Snate@binkert.org# notice, this list of conditions and the following disclaimer in the 126657Snate@binkert.org# documentation and/or other materials provided with the distribution; 136657Snate@binkert.org# neither the name of the copyright holders nor the names of its 146657Snate@binkert.org# contributors may be used to endorse or promote products derived from 156657Snate@binkert.org# this software without specific prior written permission. 166657Snate@binkert.org# 176657Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186657Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196657Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206657Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216657Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226657Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236657Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246657Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256657Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266657Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276657Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286999Snate@binkert.org 296657Snate@binkert.orgfrom m5.util import orderdict 306657Snate@binkert.org 316657Snate@binkert.orgfrom slicc.symbols.Symbol import Symbol 326657Snate@binkert.orgfrom slicc.symbols.Var import Var 336657Snate@binkert.orgimport slicc.generate.html as html 346882SBrad.Beckmann@amd.comimport re 357055Snate@binkert.org 366882SBrad.Beckmann@amd.compython_class_map = { 376882SBrad.Beckmann@amd.com "int": "Int", 386882SBrad.Beckmann@amd.com "uint32_t" : "UInt32", 396882SBrad.Beckmann@amd.com "std::string": "String", 406882SBrad.Beckmann@amd.com "bool": "Bool", 416888SBrad.Beckmann@amd.com "CacheMemory": "RubyCache", 426882SBrad.Beckmann@amd.com "WireBuffer": "RubyWireBuffer", 436882SBrad.Beckmann@amd.com "Sequencer": "RubySequencer", 446657Snate@binkert.org "DirectoryMemory": "RubyDirectoryMemory", 456657Snate@binkert.org "MemoryControl": "MemoryControl", 466657Snate@binkert.org "MessageBuffer": "MessageBuffer", 476657Snate@binkert.org "DMASequencer": "DMASequencer", 486657Snate@binkert.org "Prefetcher":"Prefetcher", 496657Snate@binkert.org "Cycles":"Cycles", 506882SBrad.Beckmann@amd.com } 516882SBrad.Beckmann@amd.com 526882SBrad.Beckmann@amd.comclass StateMachine(Symbol): 536882SBrad.Beckmann@amd.com def __init__(self, symtab, ident, location, pairs, config_parameters): 546882SBrad.Beckmann@amd.com super(StateMachine, self).__init__(symtab, ident, location, pairs) 556882SBrad.Beckmann@amd.com self.table = None 566657Snate@binkert.org 576657Snate@binkert.org # Data members in the State Machine that have been declared before 586657Snate@binkert.org # the opening brace '{' of the machine. Note that these along with 596657Snate@binkert.org # the members in self.objects form the entire set of data members. 606657Snate@binkert.org self.config_parameters = config_parameters 616657Snate@binkert.org 626657Snate@binkert.org self.prefetchers = [] 636657Snate@binkert.org 646657Snate@binkert.org for param in config_parameters: 656657Snate@binkert.org if param.pointer: 666657Snate@binkert.org var = Var(symtab, param.ident, location, param.type_ast.type, 676657Snate@binkert.org "(*m_%s_ptr)" % param.ident, {}, self) 686657Snate@binkert.org else: 696657Snate@binkert.org var = Var(symtab, param.ident, location, param.type_ast.type, 706657Snate@binkert.org "m_%s" % param.ident, {}, self) 716657Snate@binkert.org 726657Snate@binkert.org self.symtab.registerSym(param.ident, var) 736657Snate@binkert.org 746657Snate@binkert.org if str(param.type_ast.type) == "Prefetcher": 756657Snate@binkert.org self.prefetchers.append(var) 766657Snate@binkert.org 776657Snate@binkert.org self.states = orderdict() 786657Snate@binkert.org self.events = orderdict() 796657Snate@binkert.org self.actions = orderdict() 806657Snate@binkert.org self.request_types = orderdict() 816657Snate@binkert.org self.transitions = [] 826657Snate@binkert.org self.in_ports = [] 836657Snate@binkert.org self.functions = [] 846657Snate@binkert.org 856779SBrad.Beckmann@amd.com # Data members in the State Machine that have been declared inside 866657Snate@binkert.org # the {} machine. Note that these along with the config params 876657Snate@binkert.org # form the entire set of data members of the machine. 886657Snate@binkert.org self.objects = [] 896657Snate@binkert.org self.TBEType = None 906657Snate@binkert.org self.EntryType = None 916657Snate@binkert.org self.debug_flags = set() 926657Snate@binkert.org self.debug_flags.add('RubyGenerated') 936657Snate@binkert.org self.debug_flags.add('RubySlicc') 946657Snate@binkert.org 956657Snate@binkert.org def __repr__(self): 966657Snate@binkert.org return "[StateMachine: %s]" % self.ident 976657Snate@binkert.org 986657Snate@binkert.org def addState(self, state): 996657Snate@binkert.org assert self.table is None 1006657Snate@binkert.org self.states[state.ident] = state 1016657Snate@binkert.org 1026657Snate@binkert.org def addEvent(self, event): 1036657Snate@binkert.org assert self.table is None 1046657Snate@binkert.org self.events[event.ident] = event 1056657Snate@binkert.org 1066657Snate@binkert.org def addAction(self, action): 1076657Snate@binkert.org assert self.table is None 1086657Snate@binkert.org 1096657Snate@binkert.org # Check for duplicate action 1106657Snate@binkert.org for other in self.actions.itervalues(): 1116657Snate@binkert.org if action.ident == other.ident: 1126657Snate@binkert.org action.warning("Duplicate action definition: %s" % action.ident) 1136657Snate@binkert.org action.error("Duplicate action definition: %s" % action.ident) 1146657Snate@binkert.org if action.short == other.short: 1156657Snate@binkert.org other.warning("Duplicate action shorthand: %s" % other.ident) 1166657Snate@binkert.org other.warning(" shorthand = %s" % other.short) 1176657Snate@binkert.org action.warning("Duplicate action shorthand: %s" % action.ident) 1186657Snate@binkert.org action.error(" shorthand = %s" % action.short) 1196657Snate@binkert.org 1206657Snate@binkert.org self.actions[action.ident] = action 1216657Snate@binkert.org 1226657Snate@binkert.org def addDebugFlag(self, flag): 1236657Snate@binkert.org self.debug_flags.add(flag) 1246657Snate@binkert.org 1256657Snate@binkert.org def addRequestType(self, request_type): 1266657Snate@binkert.org assert self.table is None 1276657Snate@binkert.org self.request_types[request_type.ident] = request_type 1286657Snate@binkert.org 1296657Snate@binkert.org def addTransition(self, trans): 1306657Snate@binkert.org assert self.table is None 1316657Snate@binkert.org self.transitions.append(trans) 1326657Snate@binkert.org 1336657Snate@binkert.org def addInPort(self, var): 1346657Snate@binkert.org self.in_ports.append(var) 1356657Snate@binkert.org 1366657Snate@binkert.org def addFunc(self, func): 1376657Snate@binkert.org # register func in the symbol table 1386657Snate@binkert.org self.symtab.registerSym(str(func), func) 1396657Snate@binkert.org self.functions.append(func) 1406657Snate@binkert.org 1416877Ssteve.reinhardt@amd.com def addObject(self, obj): 1426657Snate@binkert.org self.symtab.registerSym(str(obj), obj) 1436657Snate@binkert.org self.objects.append(obj) 1446657Snate@binkert.org 1456657Snate@binkert.org def addType(self, type): 1466657Snate@binkert.org type_ident = '%s' % type.c_ident 1476657Snate@binkert.org 1487542SBrad.Beckmann@amd.com if type_ident == "%s_TBE" %self.ident: 1497542SBrad.Beckmann@amd.com if self.TBEType != None: 1506657Snate@binkert.org self.error("Multiple Transaction Buffer types in a " \ 1516657Snate@binkert.org "single machine."); 1526657Snate@binkert.org self.TBEType = type 1536657Snate@binkert.org 1546877Ssteve.reinhardt@amd.com elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 1556999Snate@binkert.org if "main" in type and "false" == type["main"].lower(): 1566877Ssteve.reinhardt@amd.com pass # this isn't the EntryType 1576877Ssteve.reinhardt@amd.com else: 1586877Ssteve.reinhardt@amd.com if self.EntryType != None: 1596877Ssteve.reinhardt@amd.com self.error("Multiple AbstractCacheEntry types in a " \ 1606877Ssteve.reinhardt@amd.com "single machine."); 1616877Ssteve.reinhardt@amd.com self.EntryType = type 1626877Ssteve.reinhardt@amd.com 1636877Ssteve.reinhardt@amd.com # Needs to be called before accessing the table 1646877Ssteve.reinhardt@amd.com def buildTable(self): 1656877Ssteve.reinhardt@amd.com assert self.table is None 1666877Ssteve.reinhardt@amd.com 1676877Ssteve.reinhardt@amd.com table = {} 1686877Ssteve.reinhardt@amd.com 1696877Ssteve.reinhardt@amd.com for trans in self.transitions: 1706877Ssteve.reinhardt@amd.com # Track which actions we touch so we know if we use them 1716877Ssteve.reinhardt@amd.com # all -- really this should be done for all symbols as 1726882SBrad.Beckmann@amd.com # part of the symbol table, then only trigger it for 1736882SBrad.Beckmann@amd.com # Actions, States, Events, etc. 1746882SBrad.Beckmann@amd.com 1756882SBrad.Beckmann@amd.com for action in trans.actions: 1766882SBrad.Beckmann@amd.com action.used = True 1776882SBrad.Beckmann@amd.com 1786882SBrad.Beckmann@amd.com index = (trans.state, trans.event) 1796877Ssteve.reinhardt@amd.com if index in table: 1806877Ssteve.reinhardt@amd.com table[index].warning("Duplicate transition: %s" % table[index]) 1816877Ssteve.reinhardt@amd.com trans.error("Duplicate transition: %s" % trans) 1826877Ssteve.reinhardt@amd.com table[index] = trans 1836657Snate@binkert.org 1846657Snate@binkert.org # Look at all actions to make sure we used them all 1856999Snate@binkert.org for action in self.actions.itervalues(): 1866657Snate@binkert.org if not action.used: 1876657Snate@binkert.org error_msg = "Unused action: %s" % action.ident 1886657Snate@binkert.org if "desc" in action: 1896657Snate@binkert.org error_msg += ", " + action.desc 1906657Snate@binkert.org action.warning(error_msg) 1916657Snate@binkert.org self.table = table 1927007Snate@binkert.org 1936657Snate@binkert.org # determine the port->msg buffer mappings 1946657Snate@binkert.org def getBufferMaps(self, ident): 1956657Snate@binkert.org msg_bufs = [] 1966657Snate@binkert.org port_to_buf_map = {} 1976657Snate@binkert.org in_msg_bufs = {} 1987007Snate@binkert.org for port in self.in_ports: 1997007Snate@binkert.org buf_name = "m_%s_ptr" % port.pairs["buffer_expr"].name 2006657Snate@binkert.org msg_bufs.append(buf_name) 2017002Snate@binkert.org port_to_buf_map[port] = msg_bufs.index(buf_name) 2027002Snate@binkert.org if buf_name not in in_msg_bufs: 2037002Snate@binkert.org in_msg_bufs[buf_name] = [port] 2047002Snate@binkert.org else: 2056877Ssteve.reinhardt@amd.com in_msg_bufs[buf_name].append(port) 2066877Ssteve.reinhardt@amd.com return port_to_buf_map, in_msg_bufs, msg_bufs 2076657Snate@binkert.org 2086657Snate@binkert.org def writeCodeFiles(self, path, includes): 2096657Snate@binkert.org self.printControllerPython(path) 2106657Snate@binkert.org self.printControllerHH(path) 2116657Snate@binkert.org self.printControllerCC(path, includes) 2126657Snate@binkert.org self.printCSwitch(path) 2137542SBrad.Beckmann@amd.com self.printCWakeup(path, includes) 2146657Snate@binkert.org 2156657Snate@binkert.org def printControllerPython(self, path): 2166657Snate@binkert.org code = self.symtab.codeFormatter() 2176657Snate@binkert.org ident = self.ident 2186793SBrad.Beckmann@amd.com 2196657Snate@binkert.org py_ident = "%s_Controller" % ident 2206657Snate@binkert.org c_ident = "%s_Controller" % self.ident 2216657Snate@binkert.org 2226657Snate@binkert.org code(''' 2236657Snate@binkert.orgfrom m5.params import * 2247002Snate@binkert.orgfrom m5.SimObject import SimObject 2256657Snate@binkert.orgfrom Controller import RubyController 2267007Snate@binkert.org 2277007Snate@binkert.orgclass $py_ident(RubyController): 2287007Snate@binkert.org type = '$py_ident' 2297007Snate@binkert.org cxx_header = 'mem/protocol/${c_ident}.hh' 2307007Snate@binkert.org''') 2316657Snate@binkert.org code.indent() 2326877Ssteve.reinhardt@amd.com for param in self.config_parameters: 2336877Ssteve.reinhardt@amd.com dflt_str = '' 2346657Snate@binkert.org 2356877Ssteve.reinhardt@amd.com if param.rvalue is not None: 2366657Snate@binkert.org dflt_str = str(param.rvalue.inline()) + ', ' 2376657Snate@binkert.org 2387002Snate@binkert.org if python_class_map.has_key(param.type_ast.type.c_ident): 2397002Snate@binkert.org python_type = python_class_map[param.type_ast.type.c_ident] 2406657Snate@binkert.org code('${{param.ident}} = Param.${{python_type}}(${dflt_str}"")') 2416881SBrad.Beckmann@amd.com 2427002Snate@binkert.org else: 2437002Snate@binkert.org self.error("Unknown c++ to python class conversion for c++ " \ 2446657Snate@binkert.org "type: '%s'. Please update the python_class_map " \ 2457002Snate@binkert.org "in StateMachine.py", param.type_ast.type.c_ident) 2466902SBrad.Beckmann@amd.com 2476863Sdrh5@cs.wisc.edu code.dedent() 2486863Sdrh5@cs.wisc.edu code.write(path, '%s.py' % py_ident) 2497007Snate@binkert.org 2506657Snate@binkert.org 2516657Snate@binkert.org def printControllerHH(self, path): 2526657Snate@binkert.org '''Output the method declarations for the class declaration''' 2536657Snate@binkert.org code = self.symtab.codeFormatter() 2546657Snate@binkert.org ident = self.ident 2556657Snate@binkert.org c_ident = "%s_Controller" % self.ident 2566882SBrad.Beckmann@amd.com 2576882SBrad.Beckmann@amd.com code(''' 2586882SBrad.Beckmann@amd.com/** \\file $c_ident.hh 2596882SBrad.Beckmann@amd.com * 2606657Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 2616657Snate@binkert.org * Created by slicc definition of Module "${{self.short}}" 2626657Snate@binkert.org */ 2636657Snate@binkert.org 2647007Snate@binkert.org#ifndef __${ident}_CONTROLLER_HH__ 2657007Snate@binkert.org#define __${ident}_CONTROLLER_HH__ 2667007Snate@binkert.org 2677007Snate@binkert.org#include <iostream> 2687007Snate@binkert.org#include <sstream> 2697007Snate@binkert.org#include <string> 2707007Snate@binkert.org 2717007Snate@binkert.org#include "mem/protocol/TransitionResult.hh" 2727007Snate@binkert.org#include "mem/protocol/Types.hh" 2737002Snate@binkert.org#include "mem/ruby/common/Consumer.hh" 2746657Snate@binkert.org#include "mem/ruby/slicc_interface/AbstractController.hh" 2756657Snate@binkert.org#include "params/$c_ident.hh" 2766657Snate@binkert.org 2777055Snate@binkert.org''') 2786657Snate@binkert.org 2796657Snate@binkert.org seen_types = set() 2806657Snate@binkert.org for var in self.objects: 2816863Sdrh5@cs.wisc.edu if var.type.ident not in seen_types and not var.type.isPrimitive: 2827055Snate@binkert.org code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 2837542SBrad.Beckmann@amd.com seen_types.add(var.type.ident) 2847542SBrad.Beckmann@amd.com 2856657Snate@binkert.org # for adding information to the protocol debug trace 2867007Snate@binkert.org code(''' 2876657Snate@binkert.orgextern std::stringstream ${ident}_transitionComment; 2886657Snate@binkert.org 2896657Snate@binkert.orgclass $c_ident : public AbstractController 2906657Snate@binkert.org{ 2916657Snate@binkert.org public: 2926657Snate@binkert.org typedef ${c_ident}Params Params; 2936657Snate@binkert.org $c_ident(const Params *p); 2946657Snate@binkert.org static int getNumControllers(); 2956657Snate@binkert.org void init(); 2966657Snate@binkert.org 2976657Snate@binkert.org MessageBuffer *getMandatoryQueue() const; 2986657Snate@binkert.org MessageBuffer *getMemoryQueue() const; 2996657Snate@binkert.org void initNetQueues(); 3006657Snate@binkert.org 3016657Snate@binkert.org void print(std::ostream& out) const; 3026657Snate@binkert.org void wakeup(); 3036657Snate@binkert.org void resetStats(); 3046657Snate@binkert.org void regStats(); 3056657Snate@binkert.org void collateStats(); 3067007Snate@binkert.org 3076657Snate@binkert.org void recordCacheTrace(int cntrl, CacheRecorder* tr); 3086657Snate@binkert.org Sequencer* getSequencer() const; 3096657Snate@binkert.org 3106657Snate@binkert.org int functionalWriteBuffers(PacketPtr&); 3116657Snate@binkert.org 3126657Snate@binkert.org void countTransition(${ident}_State state, ${ident}_Event event); 3136657Snate@binkert.org void possibleTransition(${ident}_State state, ${ident}_Event event); 3146657Snate@binkert.org uint64_t getEventCount(${ident}_Event event); 3156657Snate@binkert.org bool isPossible(${ident}_State state, ${ident}_Event event); 3166657Snate@binkert.org uint64_t getTransitionCount(${ident}_State state, ${ident}_Event event); 3177007Snate@binkert.org 3186657Snate@binkert.orgprivate: 3196657Snate@binkert.org''') 3206657Snate@binkert.org 3216657Snate@binkert.org code.indent() 3226657Snate@binkert.org # added by SS 3236999Snate@binkert.org for param in self.config_parameters: 3246657Snate@binkert.org if param.pointer: 3256657Snate@binkert.org code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 3266657Snate@binkert.org else: 3276657Snate@binkert.org code('${{param.type_ast.type}} m_${{param.ident}};') 3287007Snate@binkert.org 3296657Snate@binkert.org code(''' 3306657Snate@binkert.orgTransitionResult doTransition(${ident}_Event event, 3316657Snate@binkert.org''') 3326657Snate@binkert.org 3336657Snate@binkert.org if self.EntryType != None: 3347002Snate@binkert.org code(''' 3357002Snate@binkert.org ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 3367002Snate@binkert.org''') 3377056Snate@binkert.org if self.TBEType != None: 3386657Snate@binkert.org code(''' 3396657Snate@binkert.org ${{self.TBEType.c_ident}}* m_tbe_ptr, 3406657Snate@binkert.org''') 3416657Snate@binkert.org 3427056Snate@binkert.org code(''' 3437056Snate@binkert.org Addr addr); 3446657Snate@binkert.org 3457002Snate@binkert.orgTransitionResult doTransitionWorker(${ident}_Event event, 3467002Snate@binkert.org ${ident}_State state, 3476657Snate@binkert.org ${ident}_State& next_state, 3486657Snate@binkert.org''') 3496657Snate@binkert.org 3506657Snate@binkert.org if self.TBEType != None: 3516657Snate@binkert.org code(''' 3526793SBrad.Beckmann@amd.com ${{self.TBEType.c_ident}}*& m_tbe_ptr, 3536657Snate@binkert.org''') 3546657Snate@binkert.org if self.EntryType != None: 3556657Snate@binkert.org code(''' 3566657Snate@binkert.org ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 3576877Ssteve.reinhardt@amd.com''') 3586877Ssteve.reinhardt@amd.com 3596877Ssteve.reinhardt@amd.com code(''' 3606877Ssteve.reinhardt@amd.com Addr addr); 3616877Ssteve.reinhardt@amd.com 3626877Ssteve.reinhardt@amd.comint m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 3636657Snate@binkert.orgint m_event_counters[${ident}_Event_NUM]; 3647542SBrad.Beckmann@amd.combool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 3656657Snate@binkert.org 3667007Snate@binkert.orgstatic std::vector<Stats::Vector *> eventVec; 3676657Snate@binkert.orgstatic std::vector<std::vector<Stats::Vector *> > transVec; 3686657Snate@binkert.orgstatic int m_num_controllers; 3697007Snate@binkert.org 3706657Snate@binkert.org// Internal functions 3716877Ssteve.reinhardt@amd.com''') 3726877Ssteve.reinhardt@amd.com 3736657Snate@binkert.org for func in self.functions: 3746877Ssteve.reinhardt@amd.com proto = func.prototype 3756877Ssteve.reinhardt@amd.com if proto: 3766877Ssteve.reinhardt@amd.com code('$proto') 3776877Ssteve.reinhardt@amd.com 3786877Ssteve.reinhardt@amd.com if self.EntryType != None: 3796969SBrad.Beckmann@amd.com code(''' 3806657Snate@binkert.org 3816657Snate@binkert.org// Set and Reset for cache_entry variable 3826882SBrad.Beckmann@amd.comvoid set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 3836882SBrad.Beckmann@amd.comvoid unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 3846882SBrad.Beckmann@amd.com''') 3856882SBrad.Beckmann@amd.com 3866882SBrad.Beckmann@amd.com if self.TBEType != None: 3876882SBrad.Beckmann@amd.com code(''' 3886882SBrad.Beckmann@amd.com 3896882SBrad.Beckmann@amd.com// Set and Reset for tbe variable 3906877Ssteve.reinhardt@amd.comvoid set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 3916888SBrad.Beckmann@amd.comvoid unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 3926882SBrad.Beckmann@amd.com''') 3936882SBrad.Beckmann@amd.com 3946882SBrad.Beckmann@amd.com # Prototype the actions that the controller can take 3956882SBrad.Beckmann@amd.com code(''' 3966882SBrad.Beckmann@amd.com 3976882SBrad.Beckmann@amd.com// Actions 3986882SBrad.Beckmann@amd.com''') 3996882SBrad.Beckmann@amd.com if self.TBEType != None and self.EntryType != None: 4006882SBrad.Beckmann@amd.com for action in self.actions.itervalues(): 4016882SBrad.Beckmann@amd.com code('/** \\brief ${{action.desc}} */') 4026882SBrad.Beckmann@amd.com code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 4036882SBrad.Beckmann@amd.com 'm_tbe_ptr, ${{self.EntryType.c_ident}}*& ' 4046882SBrad.Beckmann@amd.com 'm_cache_entry_ptr, Addr addr);') 4056882SBrad.Beckmann@amd.com elif self.TBEType != None: 4066882SBrad.Beckmann@amd.com for action in self.actions.itervalues(): 4076882SBrad.Beckmann@amd.com code('/** \\brief ${{action.desc}} */') 4086882SBrad.Beckmann@amd.com code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 4096882SBrad.Beckmann@amd.com 'm_tbe_ptr, Addr addr);') 4106888SBrad.Beckmann@amd.com elif self.EntryType != None: 4116888SBrad.Beckmann@amd.com for action in self.actions.itervalues(): 4126888SBrad.Beckmann@amd.com code('/** \\brief ${{action.desc}} */') 4136888SBrad.Beckmann@amd.com code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& ' 4146888SBrad.Beckmann@amd.com 'm_cache_entry_ptr, Addr addr);') 4156888SBrad.Beckmann@amd.com else: 4166888SBrad.Beckmann@amd.com for action in self.actions.itervalues(): 4176888SBrad.Beckmann@amd.com code('/** \\brief ${{action.desc}} */') 4186657Snate@binkert.org code('void ${{action.ident}}(Addr addr);') 4196888SBrad.Beckmann@amd.com 4206888SBrad.Beckmann@amd.com # the controller internal variables 4216888SBrad.Beckmann@amd.com code(''' 4226888SBrad.Beckmann@amd.com 4236657Snate@binkert.org// Objects 4246657Snate@binkert.org''') 4256657Snate@binkert.org for var in self.objects: 4266657Snate@binkert.org th = var.get("template", "") 4276657Snate@binkert.org code('${{var.type.c_ident}}$th* m_${{var.ident}}_ptr;') 4286657Snate@binkert.org 4296657Snate@binkert.org code.dedent() 4306657Snate@binkert.org code('};') 4316657Snate@binkert.org code('#endif // __${ident}_CONTROLLER_H__') 4327007Snate@binkert.org code.write(path, '%s.hh' % c_ident) 4337007Snate@binkert.org 4346657Snate@binkert.org def printControllerCC(self, path, includes): 4357007Snate@binkert.org '''Output the actions for performing the actions''' 4367007Snate@binkert.org 4377007Snate@binkert.org code = self.symtab.codeFormatter() 4386657Snate@binkert.org ident = self.ident 4396657Snate@binkert.org c_ident = "%s_Controller" % self.ident 4406657Snate@binkert.org 4417007Snate@binkert.org code(''' 4427542SBrad.Beckmann@amd.com/** \\file $c_ident.cc 4437542SBrad.Beckmann@amd.com * 4447007Snate@binkert.org * Auto generated C++ code started by $__file__:$__line__ 4456657Snate@binkert.org * Created by slicc definition of Module "${{self.short}}" 4466657Snate@binkert.org */ 4476657Snate@binkert.org 4486657Snate@binkert.org#include <sys/types.h> 4496657Snate@binkert.org#include <unistd.h> 4506657Snate@binkert.org 4516657Snate@binkert.org#include <cassert> 4526657Snate@binkert.org#include <sstream> 4536657Snate@binkert.org#include <string> 4546657Snate@binkert.org#include <typeinfo> 4556657Snate@binkert.org 4566657Snate@binkert.org#include "base/compiler.hh" 4576657Snate@binkert.org#include "base/cprintf.hh" 4586657Snate@binkert.org 4596657Snate@binkert.org''') 4606657Snate@binkert.org for f in self.debug_flags: 4616657Snate@binkert.org code('#include "debug/${{f}}.hh"') 4626657Snate@binkert.org code(''' 4636657Snate@binkert.org#include "mem/protocol/${ident}_Controller.hh" 4646657Snate@binkert.org#include "mem/protocol/${ident}_Event.hh" 4656657Snate@binkert.org#include "mem/protocol/${ident}_State.hh" 4666657Snate@binkert.org#include "mem/protocol/Types.hh" 4676657Snate@binkert.org#include "mem/ruby/system/RubySystem.hh" 4686657Snate@binkert.org 4696657Snate@binkert.org''') 4706657Snate@binkert.org for include_path in includes: 4716657Snate@binkert.org code('#include "${{include_path}}"') 4726657Snate@binkert.org 4737007Snate@binkert.org code(''' 4746657Snate@binkert.org 4756657Snate@binkert.orgusing namespace std; 4766657Snate@binkert.org''') 4776657Snate@binkert.org 4787007Snate@binkert.org # include object classes 4796657Snate@binkert.org seen_types = set() 4807007Snate@binkert.org for var in self.objects: 4817007Snate@binkert.org if var.type.ident not in seen_types and not var.type.isPrimitive: 4826657Snate@binkert.org code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 4836657Snate@binkert.org seen_types.add(var.type.ident) 4846657Snate@binkert.org 4856657Snate@binkert.org num_in_ports = len(self.in_ports) 4866657Snate@binkert.org 4876657Snate@binkert.org code(''' 4886657Snate@binkert.org$c_ident * 4896657Snate@binkert.org${c_ident}Params::create() 4906657Snate@binkert.org{ 4916657Snate@binkert.org return new $c_ident(this); 4926657Snate@binkert.org} 4936657Snate@binkert.org 4946657Snate@binkert.orgint $c_ident::m_num_controllers = 0; 4956657Snate@binkert.orgstd::vector<Stats::Vector *> $c_ident::eventVec; 4966657Snate@binkert.orgstd::vector<std::vector<Stats::Vector *> > $c_ident::transVec; 4976657Snate@binkert.org 4986657Snate@binkert.org// for adding information to the protocol debug trace 4996657Snate@binkert.orgstringstream ${ident}_transitionComment; 5006657Snate@binkert.org 5016657Snate@binkert.org#ifndef NDEBUG 5026657Snate@binkert.org#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 5036657Snate@binkert.org#else 5046657Snate@binkert.org#define APPEND_TRANSITION_COMMENT(str) do {} while (0) 5057007Snate@binkert.org#endif 5067007Snate@binkert.org 5077007Snate@binkert.org/** \\brief constructor */ 5086657Snate@binkert.org$c_ident::$c_ident(const Params *p) 5096657Snate@binkert.org : AbstractController(p) 5106657Snate@binkert.org{ 5116657Snate@binkert.org m_machineID.type = MachineType_${ident}; 5126657Snate@binkert.org m_machineID.num = m_version; 5136657Snate@binkert.org m_num_controllers++; 5146657Snate@binkert.org 5156657Snate@binkert.org m_in_ports = $num_in_ports; 5166657Snate@binkert.org''') 5176657Snate@binkert.org code.indent() 5186657Snate@binkert.org 5196657Snate@binkert.org # 5206657Snate@binkert.org # After initializing the universal machine parameters, initialize the 5216657Snate@binkert.org # this machines config parameters. Also if these configuration params 5226657Snate@binkert.org # include a sequencer, connect the it to the controller. 5236657Snate@binkert.org # 5246657Snate@binkert.org for param in self.config_parameters: 5256657Snate@binkert.org if param.pointer: 5266657Snate@binkert.org code('m_${{param.ident}}_ptr = p->${{param.ident}};') 5276657Snate@binkert.org else: 5286657Snate@binkert.org code('m_${{param.ident}} = p->${{param.ident}};') 5296657Snate@binkert.org 5307454Snate@binkert.org if re.compile("sequencer").search(param.ident): 5316657Snate@binkert.org code('m_${{param.ident}}_ptr->setController(this);') 5326657Snate@binkert.org 5336657Snate@binkert.org code(''' 5346657Snate@binkert.org 5357007Snate@binkert.orgfor (int state = 0; state < ${ident}_State_NUM; state++) { 5367056Snate@binkert.org for (int event = 0; event < ${ident}_Event_NUM; event++) { 5377007Snate@binkert.org m_possible[state][event] = false; 5387007Snate@binkert.org m_counters[state][event] = 0; 5396657Snate@binkert.org } 5406657Snate@binkert.org} 5416657Snate@binkert.orgfor (int event = 0; event < ${ident}_Event_NUM; event++) { 5426657Snate@binkert.org m_event_counters[event] = 0; 5436657Snate@binkert.org} 5446657Snate@binkert.org''') 5456657Snate@binkert.org code.dedent() 5466657Snate@binkert.org code(''' 5476657Snate@binkert.org} 5487056Snate@binkert.org 5496657Snate@binkert.orgvoid 5506657Snate@binkert.org$c_ident::initNetQueues() 5516657Snate@binkert.org{ 5526657Snate@binkert.org MachineType machine_type = string_to_MachineType("${{self.ident}}"); 5536657Snate@binkert.org int base M5_VAR_USED = MachineType_base_number(machine_type); 5546657Snate@binkert.org 5556657Snate@binkert.org''') 5566657Snate@binkert.org code.indent() 5576657Snate@binkert.org 5586657Snate@binkert.org # set for maintaining the vnet, direction pairs already seen for this 5596657Snate@binkert.org # machine. This map helps in implementing the check for avoiding 5606657Snate@binkert.org # multiple message buffers being mapped to the same vnet. 5616657Snate@binkert.org vnet_dir_set = set() 5626657Snate@binkert.org 5637542SBrad.Beckmann@amd.com for var in self.config_parameters: 5646657Snate@binkert.org vid = "m_%s_ptr" % var.ident 5656657Snate@binkert.org if "network" in var: 5666657Snate@binkert.org vtype = var.type_ast.type 5676657Snate@binkert.org code('assert($vid != NULL);') 5686657Snate@binkert.org 5696657Snate@binkert.org # Network port object 5706657Snate@binkert.org network = var["network"] 5716657Snate@binkert.org 5726657Snate@binkert.org if "virtual_network" in var: 5736657Snate@binkert.org vnet = var["virtual_network"] 5746657Snate@binkert.org vnet_type = var["vnet_type"] 5756657Snate@binkert.org 5766657Snate@binkert.org assert (vnet, network) not in vnet_dir_set 5776657Snate@binkert.org vnet_dir_set.add((vnet,network)) 5786657Snate@binkert.org 5796657Snate@binkert.org code(''' 5806657Snate@binkert.orgm_net_ptr->set${network}NetQueue(m_version + base, $vid->getOrdered(), $vnet, 5816657Snate@binkert.org "$vnet_type", $vid); 5826657Snate@binkert.org''') 5837007Snate@binkert.org # Set Priority 5847007Snate@binkert.org if "rank" in var: 5857007Snate@binkert.org code('$vid->setPriority(${{var["rank"]}})') 5866657Snate@binkert.org 5876657Snate@binkert.org code.dedent() 5886657Snate@binkert.org code(''' 5897007Snate@binkert.org} 5907007Snate@binkert.org 5917007Snate@binkert.orgvoid 5926657Snate@binkert.org$c_ident::init() 5936657Snate@binkert.org{ 5946657Snate@binkert.org // initialize objects 5957007Snate@binkert.org initNetQueues(); 5967007Snate@binkert.org''') 5977007Snate@binkert.org 5986657Snate@binkert.org code.indent() 5996657Snate@binkert.org 6006657Snate@binkert.org for var in self.objects: 6017007Snate@binkert.org vtype = var.type 6027007Snate@binkert.org vid = "m_%s_ptr" % var.ident 6037007Snate@binkert.org if "network" not in var: 6046657Snate@binkert.org # Not a network port object 6056657Snate@binkert.org if "primitive" in vtype: 6066657Snate@binkert.org code('$vid = new ${{vtype.c_ident}};') 6077007Snate@binkert.org if "default" in var: 6087007Snate@binkert.org code('(*$vid) = ${{var["default"]}};') 6097007Snate@binkert.org else: 6106657Snate@binkert.org # Normal Object 6116657Snate@binkert.org th = var.get("template", "") 6127007Snate@binkert.org expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 6137007Snate@binkert.org args = "" 6147007Snate@binkert.org if "non_obj" not in vtype and not vtype.isEnumeration: 6157007Snate@binkert.org args = var.get("constructor", "") 6166657Snate@binkert.org 6176657Snate@binkert.org code('$expr($args);') 6186657Snate@binkert.org code('assert($vid != NULL);') 6197007Snate@binkert.org 6207007Snate@binkert.org if "default" in var: 6217007Snate@binkert.org code('*$vid = ${{var["default"]}}; // Object default') 6226863Sdrh5@cs.wisc.edu elif "default" in vtype: 6236863Sdrh5@cs.wisc.edu comment = "Type %s default" % vtype.ident 6246863Sdrh5@cs.wisc.edu code('*$vid = ${{vtype["default"]}}; // $comment') 6257007Snate@binkert.org 6267007Snate@binkert.org # Set the prefetchers 6277007Snate@binkert.org code() 6287007Snate@binkert.org for prefetcher in self.prefetchers: 6296863Sdrh5@cs.wisc.edu code('${{prefetcher.code}}.setController(this);') 6306863Sdrh5@cs.wisc.edu 6316863Sdrh5@cs.wisc.edu code() 6326863Sdrh5@cs.wisc.edu for port in self.in_ports: 6336863Sdrh5@cs.wisc.edu # Set the queue consumers 6346863Sdrh5@cs.wisc.edu code('${{port.code}}.setConsumer(this);') 6357007Snate@binkert.org 6367007Snate@binkert.org # Initialize the transition profiling 6377007Snate@binkert.org code() 6387007Snate@binkert.org for trans in self.transitions: 6397007Snate@binkert.org # Figure out if we stall 6406657Snate@binkert.org stall = False 6417007Snate@binkert.org for action in trans.actions: 6427007Snate@binkert.org if action.ident == "z_stall": 6437007Snate@binkert.org stall = True 6446657Snate@binkert.org 6456657Snate@binkert.org # Only possible if it is not a 'z' case 6467007Snate@binkert.org if not stall: 6477007Snate@binkert.org state = "%s_State_%s" % (self.ident, trans.state.ident) 6487007Snate@binkert.org event = "%s_Event_%s" % (self.ident, trans.event.ident) 6496657Snate@binkert.org code('possibleTransition($state, $event);') 6506657Snate@binkert.org 6517007Snate@binkert.org code.dedent() 6527007Snate@binkert.org code(''' 6537007Snate@binkert.org AbstractController::init(); 6546902SBrad.Beckmann@amd.com resetStats(); 6556902SBrad.Beckmann@amd.com} 6566902SBrad.Beckmann@amd.com''') 6576902SBrad.Beckmann@amd.com 6586902SBrad.Beckmann@amd.com mq_ident = "NULL" 6596902SBrad.Beckmann@amd.com for port in self.in_ports: 6606902SBrad.Beckmann@amd.com if port.code.find("mandatoryQueue_ptr") >= 0: 6617025SBrad.Beckmann@amd.com mq_ident = "m_mandatoryQueue_ptr" 6626902SBrad.Beckmann@amd.com 6636902SBrad.Beckmann@amd.com memq_ident = "NULL" 6646902SBrad.Beckmann@amd.com for port in self.in_ports: 6656902SBrad.Beckmann@amd.com if port.code.find("responseFromMemory_ptr") >= 0: 6666902SBrad.Beckmann@amd.com memq_ident = "m_responseFromMemory_ptr" 6677542SBrad.Beckmann@amd.com 6687542SBrad.Beckmann@amd.com seq_ident = "NULL" 6697542SBrad.Beckmann@amd.com for param in self.config_parameters: 6706902SBrad.Beckmann@amd.com if param.ident == "sequencer": 6716902SBrad.Beckmann@amd.com assert(param.pointer) 6726902SBrad.Beckmann@amd.com seq_ident = "m_%s_ptr" % param.ident 6736902SBrad.Beckmann@amd.com 6746902SBrad.Beckmann@amd.com code(''' 6756902SBrad.Beckmann@amd.com 6766902SBrad.Beckmann@amd.comvoid 6776902SBrad.Beckmann@amd.com$c_ident::regStats() 6786902SBrad.Beckmann@amd.com{ 6796902SBrad.Beckmann@amd.com AbstractController::regStats(); 6806902SBrad.Beckmann@amd.com 6816902SBrad.Beckmann@amd.com if (m_version == 0) { 6826902SBrad.Beckmann@amd.com for (${ident}_Event event = ${ident}_Event_FIRST; 6836902SBrad.Beckmann@amd.com event < ${ident}_Event_NUM; ++event) { 6846902SBrad.Beckmann@amd.com Stats::Vector *t = new Stats::Vector(); 6857542SBrad.Beckmann@amd.com t->init(m_num_controllers); 6866902SBrad.Beckmann@amd.com t->name(params()->ruby_system->name() + ".${c_ident}." + 6876902SBrad.Beckmann@amd.com ${ident}_Event_to_string(event)); 6886657Snate@binkert.org t->flags(Stats::pdf | Stats::total | Stats::oneline | 6896657Snate@binkert.org Stats::nozero); 6906657Snate@binkert.org 6916657Snate@binkert.org eventVec.push_back(t); 6926657Snate@binkert.org } 6936657Snate@binkert.org 6946657Snate@binkert.org for (${ident}_State state = ${ident}_State_FIRST; 6956657Snate@binkert.org state < ${ident}_State_NUM; ++state) { 6966657Snate@binkert.org 6977007Snate@binkert.org transVec.push_back(std::vector<Stats::Vector *>()); 6987007Snate@binkert.org 6996657Snate@binkert.org for (${ident}_Event event = ${ident}_Event_FIRST; 7006657Snate@binkert.org event < ${ident}_Event_NUM; ++event) { 7016657Snate@binkert.org 7026657Snate@binkert.org Stats::Vector *t = new Stats::Vector(); 7036657Snate@binkert.org t->init(m_num_controllers); 7046657Snate@binkert.org t->name(params()->ruby_system->name() + ".${c_ident}." + 7056657Snate@binkert.org ${ident}_State_to_string(state) + 7066657Snate@binkert.org "." + ${ident}_Event_to_string(event)); 7076657Snate@binkert.org 7086657Snate@binkert.org t->flags(Stats::pdf | Stats::total | Stats::oneline | 7096657Snate@binkert.org Stats::nozero); 7106999Snate@binkert.org transVec[state].push_back(t); 7116657Snate@binkert.org } 7126657Snate@binkert.org } 7136657Snate@binkert.org } 7146657Snate@binkert.org} 7156657Snate@binkert.org 7166657Snate@binkert.orgvoid 7177007Snate@binkert.org$c_ident::collateStats() 7186657Snate@binkert.org{ 7196657Snate@binkert.org for (${ident}_Event event = ${ident}_Event_FIRST; 7206657Snate@binkert.org event < ${ident}_Event_NUM; ++event) { 7216657Snate@binkert.org for (unsigned int i = 0; i < m_num_controllers; ++i) { 7226657Snate@binkert.org RubySystem *rs = params()->ruby_system; 7236657Snate@binkert.org std::map<uint32_t, AbstractController *>::iterator it = 7246657Snate@binkert.org rs->m_abstract_controls[MachineType_${ident}].find(i); 7256657Snate@binkert.org assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); 7267055Snate@binkert.org (*eventVec[event])[i] = 7277055Snate@binkert.org (($c_ident *)(*it).second)->getEventCount(event); 7287007Snate@binkert.org } 7297007Snate@binkert.org } 7306657Snate@binkert.org 7317007Snate@binkert.org for (${ident}_State state = ${ident}_State_FIRST; 7327007Snate@binkert.org state < ${ident}_State_NUM; ++state) { 7336657Snate@binkert.org 7346657Snate@binkert.org for (${ident}_Event event = ${ident}_Event_FIRST; 7356657Snate@binkert.org event < ${ident}_Event_NUM; ++event) { 7366657Snate@binkert.org 7376657Snate@binkert.org for (unsigned int i = 0; i < m_num_controllers; ++i) { 7386657Snate@binkert.org RubySystem *rs = params()->ruby_system; 7397007Snate@binkert.org std::map<uint32_t, AbstractController *>::iterator it = 7407007Snate@binkert.org rs->m_abstract_controls[MachineType_${ident}].find(i); 7417007Snate@binkert.org assert(it != rs->m_abstract_controls[MachineType_${ident}].end()); 7427007Snate@binkert.org (*transVec[state][event])[i] = 7437007Snate@binkert.org (($c_ident *)(*it).second)->getTransitionCount(state, event); 7446657Snate@binkert.org } 7456657Snate@binkert.org } 7466657Snate@binkert.org } 7476657Snate@binkert.org} 7486657Snate@binkert.org 7496657Snate@binkert.orgvoid 7506657Snate@binkert.org$c_ident::countTransition(${ident}_State state, ${ident}_Event event) 7516657Snate@binkert.org{ 7526657Snate@binkert.org assert(m_possible[state][event]); 7536657Snate@binkert.org m_counters[state][event]++; 7546657Snate@binkert.org m_event_counters[event]++; 7556657Snate@binkert.org} 7566657Snate@binkert.orgvoid 7576657Snate@binkert.org$c_ident::possibleTransition(${ident}_State state, 7586657Snate@binkert.org ${ident}_Event event) 7596657Snate@binkert.org{ 7606657Snate@binkert.org m_possible[state][event] = true; 7616657Snate@binkert.org} 7626657Snate@binkert.org 7636657Snate@binkert.orguint64_t 7646657Snate@binkert.org$c_ident::getEventCount(${ident}_Event event) 7656657Snate@binkert.org{ 7667007Snate@binkert.org return m_event_counters[event]; 7677007Snate@binkert.org} 7686657Snate@binkert.org 7696657Snate@binkert.orgbool 7706657Snate@binkert.org$c_ident::isPossible(${ident}_State state, ${ident}_Event event) 7716657Snate@binkert.org{ 7726657Snate@binkert.org return m_possible[state][event]; 7736657Snate@binkert.org} 7746657Snate@binkert.org 7756657Snate@binkert.orguint64_t 7766999Snate@binkert.org$c_ident::getTransitionCount(${ident}_State state, 7776657Snate@binkert.org ${ident}_Event event) 7786657Snate@binkert.org{ 7796657Snate@binkert.org return m_counters[state][event]; 7806657Snate@binkert.org} 7816657Snate@binkert.org 7826657Snate@binkert.orgint 7836657Snate@binkert.org$c_ident::getNumControllers() 7846657Snate@binkert.org{ 7856657Snate@binkert.org return m_num_controllers; 7866657Snate@binkert.org} 7876657Snate@binkert.org 7886657Snate@binkert.orgMessageBuffer* 7896657Snate@binkert.org$c_ident::getMandatoryQueue() const 7906657Snate@binkert.org{ 7916657Snate@binkert.org return $mq_ident; 7926657Snate@binkert.org} 7936657Snate@binkert.org 7946657Snate@binkert.orgMessageBuffer* 7957007Snate@binkert.org$c_ident::getMemoryQueue() const 7967007Snate@binkert.org{ 7977007Snate@binkert.org return $memq_ident; 7987007Snate@binkert.org} 7996657Snate@binkert.org 8006657Snate@binkert.orgSequencer* 8016657Snate@binkert.org$c_ident::getSequencer() const 8026657Snate@binkert.org{ 8036657Snate@binkert.org return $seq_ident; 8046657Snate@binkert.org} 8056657Snate@binkert.org 8066657Snate@binkert.orgvoid 8076657Snate@binkert.org$c_ident::print(ostream& out) const 8086657Snate@binkert.org{ 8097007Snate@binkert.org out << "[$c_ident " << m_version << "]"; 8107007Snate@binkert.org} 8116657Snate@binkert.org 8126657Snate@binkert.orgvoid $c_ident::resetStats() 8136657Snate@binkert.org{ 8146657Snate@binkert.org for (int state = 0; state < ${ident}_State_NUM; state++) { 8157542SBrad.Beckmann@amd.com for (int event = 0; event < ${ident}_Event_NUM; event++) { 8166657Snate@binkert.org m_counters[state][event] = 0; 8177007Snate@binkert.org } 8187007Snate@binkert.org } 8196657Snate@binkert.org 8206657Snate@binkert.org for (int event = 0; event < ${ident}_Event_NUM; event++) { 8217007Snate@binkert.org m_event_counters[event] = 0; 8227007Snate@binkert.org } 8236657Snate@binkert.org 8246657Snate@binkert.org AbstractController::resetStats(); 8256657Snate@binkert.org} 8266657Snate@binkert.org''') 8276657Snate@binkert.org 8286657Snate@binkert.org if self.EntryType != None: 8297007Snate@binkert.org code(''' 8307007Snate@binkert.org 8316657Snate@binkert.org// Set and Reset for cache_entry variable 8326657Snate@binkert.orgvoid 8336657Snate@binkert.org$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 8346657Snate@binkert.org{ 8356657Snate@binkert.org m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 8366657Snate@binkert.org} 8376657Snate@binkert.org 8386657Snate@binkert.orgvoid 8396657Snate@binkert.org$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 8407007Snate@binkert.org{ 8417007Snate@binkert.org m_cache_entry_ptr = 0; 8426657Snate@binkert.org} 8436657Snate@binkert.org''') 8446657Snate@binkert.org 8456657Snate@binkert.org if self.TBEType != None: 8466657Snate@binkert.org code(''' 8476657Snate@binkert.org 8486657Snate@binkert.org// Set and Reset for tbe variable 8496657Snate@binkert.orgvoid 8506657Snate@binkert.org$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 8516657Snate@binkert.org{ 8527007Snate@binkert.org m_tbe_ptr = m_new_tbe; 8537007Snate@binkert.org} 8547007Snate@binkert.org 8557007Snate@binkert.orgvoid 8567007Snate@binkert.org$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 8576657Snate@binkert.org{ 8586657Snate@binkert.org m_tbe_ptr = NULL; 8596657Snate@binkert.org} 8606657Snate@binkert.org''') 8616657Snate@binkert.org 8626657Snate@binkert.org code(''' 8636657Snate@binkert.org 8646657Snate@binkert.orgvoid 8656657Snate@binkert.org$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr) 8666657Snate@binkert.org{ 8676657Snate@binkert.org''') 8686999Snate@binkert.org # 8696657Snate@binkert.org # Record cache contents for all associated caches. 8706657Snate@binkert.org # 8716657Snate@binkert.org code.indent() 8726657Snate@binkert.org for param in self.config_parameters: 8736657Snate@binkert.org if param.type_ast.type.ident == "CacheMemory": 8746657Snate@binkert.org assert(param.pointer) 8756657Snate@binkert.org code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);') 8766657Snate@binkert.org 8776657Snate@binkert.org code.dedent() 8786657Snate@binkert.org code(''' 8796657Snate@binkert.org} 8806657Snate@binkert.org 8816657Snate@binkert.org// Actions 8827007Snate@binkert.org''') 8836657Snate@binkert.org if self.TBEType != None and self.EntryType != None: 8846657Snate@binkert.org for action in self.actions.itervalues(): 8856657Snate@binkert.org if "c_code" not in action: 8866657Snate@binkert.org continue 8876657Snate@binkert.org 8886657Snate@binkert.org code(''' 8896657Snate@binkert.org/** \\brief ${{action.desc}} */ 8906657Snate@binkert.orgvoid 8916657Snate@binkert.org$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, Addr addr) 8926657Snate@binkert.org{ 8936657Snate@binkert.org DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 8946657Snate@binkert.org try { 8956657Snate@binkert.org ${{action["c_code"]}} 8966657Snate@binkert.org } catch (const RejectException & e) { 8976657Snate@binkert.org fatal("Error in action ${{ident}}:${{action.ident}}: " 8986657Snate@binkert.org "executed a peek statement with the wrong message " 8996657Snate@binkert.org "type specified. "); 9006657Snate@binkert.org } 9016657Snate@binkert.org} 9026657Snate@binkert.org 9036657Snate@binkert.org''') 9046657Snate@binkert.org elif self.TBEType != None: 9056657Snate@binkert.org for action in self.actions.itervalues(): 9066657Snate@binkert.org if "c_code" not in action: 9076657Snate@binkert.org continue 9086657Snate@binkert.org 9096657Snate@binkert.org code(''' 9106657Snate@binkert.org/** \\brief ${{action.desc}} */ 9116657Snate@binkert.orgvoid 9126657Snate@binkert.org$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, Addr addr) 9136657Snate@binkert.org{ 9146657Snate@binkert.org DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9156657Snate@binkert.org ${{action["c_code"]}} 9166657Snate@binkert.org} 9176657Snate@binkert.org 9186657Snate@binkert.org''') 9196657Snate@binkert.org elif self.EntryType != None: 9206657Snate@binkert.org for action in self.actions.itervalues(): 9216657Snate@binkert.org if "c_code" not in action: 9226657Snate@binkert.org continue 9236657Snate@binkert.org 9246657Snate@binkert.org code(''' 9256657Snate@binkert.org/** \\brief ${{action.desc}} */ 9266657Snate@binkert.orgvoid 9276657Snate@binkert.org$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, Addr addr) 9286657Snate@binkert.org{ 9296657Snate@binkert.org DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9306657Snate@binkert.org ${{action["c_code"]}} 9316657Snate@binkert.org} 9326657Snate@binkert.org 9336657Snate@binkert.org''') 9346657Snate@binkert.org else: 9356657Snate@binkert.org for action in self.actions.itervalues(): 9366657Snate@binkert.org if "c_code" not in action: 9376657Snate@binkert.org continue 9386657Snate@binkert.org 9397542SBrad.Beckmann@amd.com code(''' 9407542SBrad.Beckmann@amd.com/** \\brief ${{action.desc}} */ 9417542SBrad.Beckmann@amd.comvoid 9427542SBrad.Beckmann@amd.com$c_ident::${{action.ident}}(Addr addr) 9437542SBrad.Beckmann@amd.com{ 9447542SBrad.Beckmann@amd.com DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 9457542SBrad.Beckmann@amd.com ${{action["c_code"]}} 9467542SBrad.Beckmann@amd.com} 9477542SBrad.Beckmann@amd.com 9487542SBrad.Beckmann@amd.com''') 9497542SBrad.Beckmann@amd.com for func in self.functions: 9507542SBrad.Beckmann@amd.com code(func.generateCode()) 9517542SBrad.Beckmann@amd.com 9527542SBrad.Beckmann@amd.com # Function for functional writes to messages buffered in the controller 9537542SBrad.Beckmann@amd.com code(''' 9547542SBrad.Beckmann@amd.comint 9557542SBrad.Beckmann@amd.com$c_ident::functionalWriteBuffers(PacketPtr& pkt) 9567542SBrad.Beckmann@amd.com{ 9577542SBrad.Beckmann@amd.com int num_functional_writes = 0; 9587542SBrad.Beckmann@amd.com''') 9597542SBrad.Beckmann@amd.com for var in self.objects: 9607542SBrad.Beckmann@amd.com vtype = var.type 9617542SBrad.Beckmann@amd.com if vtype.isBuffer: 9627542SBrad.Beckmann@amd.com vid = "m_%s_ptr" % var.ident 9637542SBrad.Beckmann@amd.com code('num_functional_writes += $vid->functionalWrite(pkt);') 9647542SBrad.Beckmann@amd.com 9657542SBrad.Beckmann@amd.com for var in self.config_parameters: 9667542SBrad.Beckmann@amd.com vtype = var.type_ast.type 9677542SBrad.Beckmann@amd.com if vtype.isBuffer: 9687542SBrad.Beckmann@amd.com vid = "m_%s_ptr" % var.ident 9697542SBrad.Beckmann@amd.com code('num_functional_writes += $vid->functionalWrite(pkt);') 9707542SBrad.Beckmann@amd.com 9717542SBrad.Beckmann@amd.com code(''' 9727542SBrad.Beckmann@amd.com return num_functional_writes; 9737542SBrad.Beckmann@amd.com} 9747542SBrad.Beckmann@amd.com''') 9757542SBrad.Beckmann@amd.com 9767542SBrad.Beckmann@amd.com code.write(path, "%s.cc" % c_ident) 9777542SBrad.Beckmann@amd.com 9787542SBrad.Beckmann@amd.com def printCWakeup(self, path, includes): 9797542SBrad.Beckmann@amd.com '''Output the wakeup loop for the events''' 9807542SBrad.Beckmann@amd.com 9817542SBrad.Beckmann@amd.com code = self.symtab.codeFormatter() 9827542SBrad.Beckmann@amd.com ident = self.ident 9837542SBrad.Beckmann@amd.com 9847542SBrad.Beckmann@amd.com outputRequest_types = True 9857542SBrad.Beckmann@amd.com if len(self.request_types) == 0: 9867542SBrad.Beckmann@amd.com outputRequest_types = False 9877542SBrad.Beckmann@amd.com 9887542SBrad.Beckmann@amd.com code(''' 9897542SBrad.Beckmann@amd.com// Auto generated C++ code started by $__file__:$__line__ 9907542SBrad.Beckmann@amd.com// ${ident}: ${{self.short}} 9917542SBrad.Beckmann@amd.com 9927542SBrad.Beckmann@amd.com#include <sys/types.h> 9937542SBrad.Beckmann@amd.com#include <unistd.h> 9947542SBrad.Beckmann@amd.com 9957542SBrad.Beckmann@amd.com#include <cassert> 9967542SBrad.Beckmann@amd.com#include <typeinfo> 9977542SBrad.Beckmann@amd.com 9987542SBrad.Beckmann@amd.com#include "base/misc.hh" 9997542SBrad.Beckmann@amd.com 10007542SBrad.Beckmann@amd.com''') 10017542SBrad.Beckmann@amd.com for f in self.debug_flags: 10027542SBrad.Beckmann@amd.com code('#include "debug/${{f}}.hh"') 10037542SBrad.Beckmann@amd.com code(''' 10047542SBrad.Beckmann@amd.com#include "mem/protocol/${ident}_Controller.hh" 10057542SBrad.Beckmann@amd.com#include "mem/protocol/${ident}_Event.hh" 10067542SBrad.Beckmann@amd.com#include "mem/protocol/${ident}_State.hh" 10077542SBrad.Beckmann@amd.com 10087542SBrad.Beckmann@amd.com''') 10097542SBrad.Beckmann@amd.com 10107542SBrad.Beckmann@amd.com if outputRequest_types: 10117542SBrad.Beckmann@amd.com code('''#include "mem/protocol/${ident}_RequestType.hh"''') 10127542SBrad.Beckmann@amd.com 10137542SBrad.Beckmann@amd.com code(''' 10147542SBrad.Beckmann@amd.com#include "mem/protocol/Types.hh" 10157542SBrad.Beckmann@amd.com#include "mem/ruby/system/RubySystem.hh" 10167542SBrad.Beckmann@amd.com 10177542SBrad.Beckmann@amd.com''') 10187542SBrad.Beckmann@amd.com 10197542SBrad.Beckmann@amd.com 10207542SBrad.Beckmann@amd.com for include_path in includes: 10217542SBrad.Beckmann@amd.com code('#include "${{include_path}}"') 10227542SBrad.Beckmann@amd.com 10237542SBrad.Beckmann@amd.com port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) 10247542SBrad.Beckmann@amd.com 10257542SBrad.Beckmann@amd.com code(''' 10267542SBrad.Beckmann@amd.com 10277542SBrad.Beckmann@amd.comusing namespace std; 10287542SBrad.Beckmann@amd.com 10297542SBrad.Beckmann@amd.comvoid 10307542SBrad.Beckmann@amd.com${ident}_Controller::wakeup() 10317542SBrad.Beckmann@amd.com{ 10327542SBrad.Beckmann@amd.com int counter = 0; 10337542SBrad.Beckmann@amd.com while (true) { 10346657Snate@binkert.org unsigned char rejected[${{len(msg_bufs)}}]; 10356999Snate@binkert.org memset(rejected, 0, sizeof(unsigned char)*${{len(msg_bufs)}}); 10366657Snate@binkert.org // Some cases will put us into an infinite loop without this limit 10376657Snate@binkert.org assert(counter <= m_transitions_per_cycle); 10386657Snate@binkert.org if (counter == m_transitions_per_cycle) { 10396657Snate@binkert.org // Count how often we are fully utilized 10406657Snate@binkert.org m_fully_busy_cycles++; 10416657Snate@binkert.org 10427542SBrad.Beckmann@amd.com // Wakeup in another cycle and try again 10437542SBrad.Beckmann@amd.com scheduleEvent(Cycles(1)); 10446657Snate@binkert.org break; 10457002Snate@binkert.org } 10467002Snate@binkert.org''') 10476657Snate@binkert.org 10486657Snate@binkert.org code.indent() 10496657Snate@binkert.org code.indent() 10506657Snate@binkert.org 10517007Snate@binkert.org # InPorts 10527007Snate@binkert.org # 10536657Snate@binkert.org for port in self.in_ports: 10546657Snate@binkert.org code.indent() 10556657Snate@binkert.org code('// ${ident}InPort $port') 10566657Snate@binkert.org if port.pairs.has_key("rank"): 10576657Snate@binkert.org code('m_cur_in_port = ${{port.pairs["rank"]}};') 10587542SBrad.Beckmann@amd.com else: 10597542SBrad.Beckmann@amd.com code('m_cur_in_port = 0;') 10607542SBrad.Beckmann@amd.com if port in port_to_buf_map: 10616657Snate@binkert.org code('try {') 10626657Snate@binkert.org code.indent() 10636657Snate@binkert.org code('${{port["c_code_in_port"]}}') 10646657Snate@binkert.org 10656657Snate@binkert.org if port in port_to_buf_map: 10666657Snate@binkert.org code.dedent() 10676657Snate@binkert.org code(''' 10686657Snate@binkert.org } catch (const RejectException & e) { 10696657Snate@binkert.org rejected[${{port_to_buf_map[port]}}]++; 10707007Snate@binkert.org } 10716657Snate@binkert.org''') 10726657Snate@binkert.org code.dedent() 10736657Snate@binkert.org code('') 10746657Snate@binkert.org 10756999Snate@binkert.org code.dedent() 10766657Snate@binkert.org code.dedent() 10776657Snate@binkert.org code(''' 10786657Snate@binkert.org // If we got this far, we have nothing left todo or something went 10796657Snate@binkert.org // wrong''') 10806657Snate@binkert.org for buf_name, ports in in_msg_bufs.items(): 10816657Snate@binkert.org if len(ports) > 1: 10826657Snate@binkert.org # only produce checks when a buffer is shared by multiple ports 10836657Snate@binkert.org code(''' 10846657Snate@binkert.org if (${{buf_name}}->isReady() && rejected[${{port_to_buf_map[ports[0]]}}] == ${{len(ports)}}) 10856657Snate@binkert.org { 10866657Snate@binkert.org // no port claimed the message on the top of this buffer 10876657Snate@binkert.org panic("Runtime Error at Ruby Time: %d. " 10886657Snate@binkert.org "All ports rejected a message. " 10896657Snate@binkert.org "You are probably sending a message type to this controller " 10906657Snate@binkert.org "over a virtual network that do not define an in_port for " 10916657Snate@binkert.org "the incoming message type.\\n", 10926657Snate@binkert.org Cycles(1)); 10936657Snate@binkert.org } 10946657Snate@binkert.org''') 10956657Snate@binkert.org code(''' 10967007Snate@binkert.org break; 10977007Snate@binkert.org } 10987007Snate@binkert.org} 10996657Snate@binkert.org''') 11006657Snate@binkert.org 11016657Snate@binkert.org code.write(path, "%s_Wakeup.cc" % self.ident) 11027007Snate@binkert.org 11037007Snate@binkert.org def printCSwitch(self, path): 11047007Snate@binkert.org '''Output switch statement for transition table''' 11056657Snate@binkert.org 11066657Snate@binkert.org code = self.symtab.codeFormatter() 11076657Snate@binkert.org ident = self.ident 11086657Snate@binkert.org 11096657Snate@binkert.org code(''' 11106657Snate@binkert.org// Auto generated C++ code started by $__file__:$__line__ 11116657Snate@binkert.org// ${ident}: ${{self.short}} 11126657Snate@binkert.org 11136657Snate@binkert.org#include <cassert> 11146657Snate@binkert.org 11156657Snate@binkert.org#include "base/misc.hh" 11167007Snate@binkert.org#include "base/trace.hh" 11177007Snate@binkert.org#include "debug/ProtocolTrace.hh" 11186657Snate@binkert.org#include "debug/RubyGenerated.hh" 11196657Snate@binkert.org#include "mem/protocol/${ident}_Controller.hh" 11206657Snate@binkert.org#include "mem/protocol/${ident}_Event.hh" 11216657Snate@binkert.org#include "mem/protocol/${ident}_State.hh" 11226657Snate@binkert.org#include "mem/protocol/Types.hh" 11237007Snate@binkert.org#include "mem/ruby/system/RubySystem.hh" 11247007Snate@binkert.org 11257007Snate@binkert.org#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 11266657Snate@binkert.org 11276657Snate@binkert.org#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 11286657Snate@binkert.org#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 11297007Snate@binkert.org 11307542SBrad.Beckmann@amd.comTransitionResult 11317542SBrad.Beckmann@amd.com${ident}_Controller::doTransition(${ident}_Event event, 11326657Snate@binkert.org''') 11337542SBrad.Beckmann@amd.com if self.EntryType != None: 11347542SBrad.Beckmann@amd.com code(''' 11357002Snate@binkert.org ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 11367542SBrad.Beckmann@amd.com''') 11377542SBrad.Beckmann@amd.com if self.TBEType != None: 11387542SBrad.Beckmann@amd.com code(''' 11397542SBrad.Beckmann@amd.com ${{self.TBEType.c_ident}}* m_tbe_ptr, 11406657Snate@binkert.org''') 11417542SBrad.Beckmann@amd.com code(''' 11427542SBrad.Beckmann@amd.com Addr addr) 11437542SBrad.Beckmann@amd.com{ 11447542SBrad.Beckmann@amd.com''') 11457542SBrad.Beckmann@amd.com code.indent() 11467542SBrad.Beckmann@amd.com 11477542SBrad.Beckmann@amd.com if self.TBEType != None and self.EntryType != None: 11487542SBrad.Beckmann@amd.com code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 11496657Snate@binkert.org elif self.TBEType != None: 11506657Snate@binkert.org code('${ident}_State state = getState(m_tbe_ptr, addr);') 11516657Snate@binkert.org elif self.EntryType != None: 11526657Snate@binkert.org code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 11536657Snate@binkert.org else: 11546657Snate@binkert.org code('${ident}_State state = getState(addr);') 11557007Snate@binkert.org 11566999Snate@binkert.org code(''' 11577007Snate@binkert.org${ident}_State next_state = state; 11587007Snate@binkert.org 11597007Snate@binkert.orgDPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 11607007Snate@binkert.org *this, curCycle(), ${ident}_State_to_string(state), 11617007Snate@binkert.org ${ident}_Event_to_string(event), addr); 11627007Snate@binkert.org 11636657Snate@binkert.orgTransitionResult result = 11646657Snate@binkert.org''') 11656657Snate@binkert.org if self.TBEType != None and self.EntryType != None: 11666657Snate@binkert.org code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 11676657Snate@binkert.org elif self.TBEType != None: 11686657Snate@binkert.org code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 11696657Snate@binkert.org elif self.EntryType != None: 11706657Snate@binkert.org code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 11716657Snate@binkert.org else: 11726657Snate@binkert.org code('doTransitionWorker(event, state, next_state, addr);') 11736657Snate@binkert.org 11746657Snate@binkert.org port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) 11756657Snate@binkert.org 11766657Snate@binkert.org code(''' 11776657Snate@binkert.org 11786657Snate@binkert.orgif (result == TransitionResult_Valid) { 11796657Snate@binkert.org DPRINTF(RubyGenerated, "next_state: %s\\n", 11806657Snate@binkert.org ${ident}_State_to_string(next_state)); 11816657Snate@binkert.org countTransition(state, event); 11826657Snate@binkert.org 11836657Snate@binkert.org DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %#x %s\\n", 11846657Snate@binkert.org curTick(), m_version, "${ident}", 11856657Snate@binkert.org ${ident}_Event_to_string(event), 11866657Snate@binkert.org ${ident}_State_to_string(state), 11876657Snate@binkert.org ${ident}_State_to_string(next_state), 11886657Snate@binkert.org addr, GET_TRANSITION_COMMENT()); 11896657Snate@binkert.org 11906657Snate@binkert.org CLEAR_TRANSITION_COMMENT(); 11916657Snate@binkert.org''') 11926999Snate@binkert.org if self.TBEType != None and self.EntryType != None: 11936657Snate@binkert.org code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 11946657Snate@binkert.org code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 11957007Snate@binkert.org elif self.TBEType != None: 11967007Snate@binkert.org code('setState(m_tbe_ptr, addr, next_state);') 11976657Snate@binkert.org code('setAccessPermission(addr, next_state);') 11986657Snate@binkert.org elif self.EntryType != None: 11996657Snate@binkert.org code('setState(m_cache_entry_ptr, addr, next_state);') 12006657Snate@binkert.org code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 12016657Snate@binkert.org else: 12026657Snate@binkert.org code('setState(addr, next_state);') 12036657Snate@binkert.org code('setAccessPermission(addr, next_state);') 12046657Snate@binkert.org 12056657Snate@binkert.org code(''' 12066657Snate@binkert.org} else if (result == TransitionResult_ResourceStall) { 12076657Snate@binkert.org DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n", 12086657Snate@binkert.org curTick(), m_version, "${ident}", 12096657Snate@binkert.org ${ident}_Event_to_string(event), 12106657Snate@binkert.org ${ident}_State_to_string(state), 12116657Snate@binkert.org ${ident}_State_to_string(next_state), 12126657Snate@binkert.org addr, "Resource Stall"); 12136657Snate@binkert.org} else if (result == TransitionResult_ProtocolStall) { 12146657Snate@binkert.org DPRINTF(RubyGenerated, "stalling\\n"); 12156657Snate@binkert.org DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n", 12166657Snate@binkert.org curTick(), m_version, "${ident}", 12176657Snate@binkert.org ${ident}_Event_to_string(event), 12186657Snate@binkert.org ${ident}_State_to_string(state), 12196657Snate@binkert.org ${ident}_State_to_string(next_state), 12206657Snate@binkert.org addr, "Protocol Stall"); 12216657Snate@binkert.org} 12226657Snate@binkert.org 12236657Snate@binkert.orgreturn result; 12246657Snate@binkert.org''') 12256657Snate@binkert.org code.dedent() 12266657Snate@binkert.org code(''' 12276657Snate@binkert.org} 12286657Snate@binkert.org 12296657Snate@binkert.orgTransitionResult 12306657Snate@binkert.org${ident}_Controller::doTransitionWorker(${ident}_Event event, 12316657Snate@binkert.org ${ident}_State state, 12326657Snate@binkert.org ${ident}_State& next_state, 12336657Snate@binkert.org''') 12346657Snate@binkert.org 12356657Snate@binkert.org if self.TBEType != None: 12366657Snate@binkert.org code(''' 12376657Snate@binkert.org ${{self.TBEType.c_ident}}*& m_tbe_ptr, 12386657Snate@binkert.org''') 12396657Snate@binkert.org if self.EntryType != None: 12406657Snate@binkert.org code(''' 12416657Snate@binkert.org ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 12426657Snate@binkert.org''') 12436657Snate@binkert.org code(''' 12446657Snate@binkert.org Addr addr) 12456657Snate@binkert.org{ 12466657Snate@binkert.org switch(HASH_FUN(state, event)) { 12476657Snate@binkert.org''') 12486657Snate@binkert.org 12496657Snate@binkert.org # This map will allow suppress generating duplicate code 12506657Snate@binkert.org cases = orderdict() 12516657Snate@binkert.org 12526657Snate@binkert.org for trans in self.transitions: 12536657Snate@binkert.org case_string = "%s_State_%s, %s_Event_%s" % \ 12546657Snate@binkert.org (self.ident, trans.state.ident, self.ident, trans.event.ident) 12556657Snate@binkert.org 12566657Snate@binkert.org case = self.symtab.codeFormatter() 12576657Snate@binkert.org # Only set next_state if it changes 12586657Snate@binkert.org if trans.state != trans.nextState: 12596657Snate@binkert.org if trans.nextState.isWildcard(): 12606657Snate@binkert.org # When * is encountered as an end state of a transition, 12616657Snate@binkert.org # the next state is determined by calling the 12626657Snate@binkert.org # machine-specific getNextState function. The next state 12636657Snate@binkert.org # is determined before any actions of the transition 12646657Snate@binkert.org # execute, and therefore the next state calculation cannot 12656657Snate@binkert.org # depend on any of the transitionactions. 12666657Snate@binkert.org case('next_state = getNextState(addr);') 12676657Snate@binkert.org else: 12686657Snate@binkert.org ns_ident = trans.nextState.ident 12696657Snate@binkert.org case('next_state = ${ident}_State_${ns_ident};') 12706657Snate@binkert.org 12716657Snate@binkert.org actions = trans.actions 12726657Snate@binkert.org request_types = trans.request_types 12736657Snate@binkert.org 12746657Snate@binkert.org # Check for resources 12756657Snate@binkert.org case_sorter = [] 12766657Snate@binkert.org res = trans.resources 12776657Snate@binkert.org for key,val in res.iteritems(): 12786657Snate@binkert.org val = ''' 12796657Snate@binkert.orgif (!%s.areNSlotsAvailable(%s, clockEdge())) 12806657Snate@binkert.org return TransitionResult_ResourceStall; 12816657Snate@binkert.org''' % (key.code, val) 12826657Snate@binkert.org case_sorter.append(val) 12836657Snate@binkert.org 12846657Snate@binkert.org # Check all of the request_types for resource constraints 12857007Snate@binkert.org for request_type in request_types: 12866657Snate@binkert.org val = ''' 12876657Snate@binkert.orgif (!checkResourceAvailable(%s_RequestType_%s, addr)) { 12886657Snate@binkert.org return TransitionResult_ResourceStall; 12896657Snate@binkert.org} 12906657Snate@binkert.org''' % (self.ident, request_type.ident) 12916657Snate@binkert.org case_sorter.append(val) 12926657Snate@binkert.org 12937007Snate@binkert.org # Emit the code sequences in a sorted order. This makes the 12946657Snate@binkert.org # output deterministic (without this the output order can vary 12956657Snate@binkert.org # since Map's keys() on a vector of pointers is not deterministic 12966657Snate@binkert.org for c in sorted(case_sorter): 12976657Snate@binkert.org case("$c") 12986657Snate@binkert.org 12996657Snate@binkert.org # Record access types for this transition 13006657Snate@binkert.org for request_type in request_types: 13016657Snate@binkert.org case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);') 13026657Snate@binkert.org 13036657Snate@binkert.org # Figure out if we stall 13046657Snate@binkert.org stall = False 13056657Snate@binkert.org for action in actions: 13066657Snate@binkert.org if action.ident == "z_stall": 13076657Snate@binkert.org stall = True 13086657Snate@binkert.org break 13097007Snate@binkert.org 13106657Snate@binkert.org if stall: 13116657Snate@binkert.org case('return TransitionResult_ProtocolStall;') 13126657Snate@binkert.org else: 13136657Snate@binkert.org if self.TBEType != None and self.EntryType != None: 13146657Snate@binkert.org for action in actions: 13156657Snate@binkert.org case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 13166657Snate@binkert.org elif self.TBEType != None: 13176657Snate@binkert.org for action in actions: 13186657Snate@binkert.org case('${{action.ident}}(m_tbe_ptr, addr);') 13196657Snate@binkert.org elif self.EntryType != None: 13206657Snate@binkert.org for action in actions: 13216657Snate@binkert.org case('${{action.ident}}(m_cache_entry_ptr, addr);') 13226657Snate@binkert.org else: 13236657Snate@binkert.org for action in actions: 13246657Snate@binkert.org case('${{action.ident}}(addr);') 13256657Snate@binkert.org case('return TransitionResult_Valid;') 13266657Snate@binkert.org 13276657Snate@binkert.org case = str(case) 13286657Snate@binkert.org 13296657Snate@binkert.org # Look to see if this transition code is unique. 13306657Snate@binkert.org if case not in cases: 13316657Snate@binkert.org cases[case] = [] 1332 1333 cases[case].append(case_string) 1334 1335 # Walk through all of the unique code blocks and spit out the 1336 # corresponding case statement elements 1337 for case,transitions in cases.iteritems(): 1338 # Iterative over all the multiple transitions that share 1339 # the same code 1340 for trans in transitions: 1341 code(' case HASH_FUN($trans):') 1342 code(' $case\n') 1343 1344 code(''' 1345 default: 1346 panic("Invalid transition\\n" 1347 "%s time: %d addr: %s event: %s state: %s\\n", 1348 name(), curCycle(), addr, event, state); 1349 } 1350 1351 return TransitionResult_Valid; 1352} 1353''') 1354 code.write(path, "%s_Transitions.cc" % self.ident) 1355 1356 1357 # ************************** 1358 # ******* HTML Files ******* 1359 # ************************** 1360 def frameRef(self, click_href, click_target, over_href, over_num, text): 1361 code = self.symtab.codeFormatter(fix_newlines=False) 1362 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1363 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1364 parent.frames[$over_num].location='$over_href' 1365 }\"> 1366 ${{html.formatShorthand(text)}} 1367 </A>""") 1368 return str(code) 1369 1370 def writeHTMLFiles(self, path): 1371 # Create table with no row hilighted 1372 self.printHTMLTransitions(path, None) 1373 1374 # Generate transition tables 1375 for state in self.states.itervalues(): 1376 self.printHTMLTransitions(path, state) 1377 1378 # Generate action descriptions 1379 for action in self.actions.itervalues(): 1380 name = "%s_action_%s.html" % (self.ident, action.ident) 1381 code = html.createSymbol(action, "Action") 1382 code.write(path, name) 1383 1384 # Generate state descriptions 1385 for state in self.states.itervalues(): 1386 name = "%s_State_%s.html" % (self.ident, state.ident) 1387 code = html.createSymbol(state, "State") 1388 code.write(path, name) 1389 1390 # Generate event descriptions 1391 for event in self.events.itervalues(): 1392 name = "%s_Event_%s.html" % (self.ident, event.ident) 1393 code = html.createSymbol(event, "Event") 1394 code.write(path, name) 1395 1396 def printHTMLTransitions(self, path, active_state): 1397 code = self.symtab.codeFormatter() 1398 1399 code(''' 1400<HTML> 1401<BODY link="blue" vlink="blue"> 1402 1403<H1 align="center">${{html.formatShorthand(self.short)}}: 1404''') 1405 code.indent() 1406 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1407 mid = machine.ident 1408 if i != 0: 1409 extra = " - " 1410 else: 1411 extra = "" 1412 if machine == self: 1413 code('$extra$mid') 1414 else: 1415 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1416 code.dedent() 1417 1418 code(""" 1419</H1> 1420 1421<TABLE border=1> 1422<TR> 1423 <TH> </TH> 1424""") 1425 1426 for event in self.events.itervalues(): 1427 href = "%s_Event_%s.html" % (self.ident, event.ident) 1428 ref = self.frameRef(href, "Status", href, "1", event.short) 1429 code('<TH bgcolor=white>$ref</TH>') 1430 1431 code('</TR>') 1432 # -- Body of table 1433 for state in self.states.itervalues(): 1434 # -- Each row 1435 if state == active_state: 1436 color = "yellow" 1437 else: 1438 color = "white" 1439 1440 click = "%s_table_%s.html" % (self.ident, state.ident) 1441 over = "%s_State_%s.html" % (self.ident, state.ident) 1442 text = html.formatShorthand(state.short) 1443 ref = self.frameRef(click, "Table", over, "1", state.short) 1444 code(''' 1445<TR> 1446 <TH bgcolor=$color>$ref</TH> 1447''') 1448 1449 # -- One column for each event 1450 for event in self.events.itervalues(): 1451 trans = self.table.get((state,event), None) 1452 if trans is None: 1453 # This is the no transition case 1454 if state == active_state: 1455 color = "#C0C000" 1456 else: 1457 color = "lightgrey" 1458 1459 code('<TD bgcolor=$color> </TD>') 1460 continue 1461 1462 next = trans.nextState 1463 stall_action = False 1464 1465 # -- Get the actions 1466 for action in trans.actions: 1467 if action.ident == "z_stall" or \ 1468 action.ident == "zz_recycleMandatoryQueue": 1469 stall_action = True 1470 1471 # -- Print out "actions/next-state" 1472 if stall_action: 1473 if state == active_state: 1474 color = "#C0C000" 1475 else: 1476 color = "lightgrey" 1477 1478 elif active_state and next.ident == active_state.ident: 1479 color = "aqua" 1480 elif state == active_state: 1481 color = "yellow" 1482 else: 1483 color = "white" 1484 1485 code('<TD bgcolor=$color>') 1486 for action in trans.actions: 1487 href = "%s_action_%s.html" % (self.ident, action.ident) 1488 ref = self.frameRef(href, "Status", href, "1", 1489 action.short) 1490 code(' $ref') 1491 if next != state: 1492 if trans.actions: 1493 code('/') 1494 click = "%s_table_%s.html" % (self.ident, next.ident) 1495 over = "%s_State_%s.html" % (self.ident, next.ident) 1496 ref = self.frameRef(click, "Table", over, "1", next.short) 1497 code("$ref") 1498 code("</TD>") 1499 1500 # -- Each row 1501 if state == active_state: 1502 color = "yellow" 1503 else: 1504 color = "white" 1505 1506 click = "%s_table_%s.html" % (self.ident, state.ident) 1507 over = "%s_State_%s.html" % (self.ident, state.ident) 1508 ref = self.frameRef(click, "Table", over, "1", state.short) 1509 code(''' 1510 <TH bgcolor=$color>$ref</TH> 1511</TR> 1512''') 1513 code(''' 1514<!- Column footer-> 1515<TR> 1516 <TH> </TH> 1517''') 1518 1519 for event in self.events.itervalues(): 1520 href = "%s_Event_%s.html" % (self.ident, event.ident) 1521 ref = self.frameRef(href, "Status", href, "1", event.short) 1522 code('<TH bgcolor=white>$ref</TH>') 1523 code(''' 1524</TR> 1525</TABLE> 1526</BODY></HTML> 1527''') 1528 1529 1530 if active_state: 1531 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1532 else: 1533 name = "%s_table.html" % self.ident 1534 code.write(path, name) 1535 1536__all__ = [ "StateMachine" ] 1537