StateMachine.py revision 10121
16019Shines@cs.fsu.edu# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 26019Shines@cs.fsu.edu# Copyright (c) 2009 The Hewlett-Packard Development Company 37178Sgblack@eecs.umich.edu# All rights reserved. 47178Sgblack@eecs.umich.edu# 57178Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 67178Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 77178Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 87178Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 97178Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 107178Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 117178Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 127178Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 137178Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 147178Sgblack@eecs.umich.edu# this software without specific prior written permission. 156019Shines@cs.fsu.edu# 166019Shines@cs.fsu.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu 286019Shines@cs.fsu.edufrom m5.util import orderdict 296019Shines@cs.fsu.edu 306019Shines@cs.fsu.edufrom slicc.symbols.Symbol import Symbol 316019Shines@cs.fsu.edufrom slicc.symbols.Var import Var 326019Shines@cs.fsu.eduimport slicc.generate.html as html 336019Shines@cs.fsu.eduimport re 346019Shines@cs.fsu.edu 356019Shines@cs.fsu.edupython_class_map = { 366019Shines@cs.fsu.edu "int": "Int", 376019Shines@cs.fsu.edu "uint32_t" : "UInt32", 386019Shines@cs.fsu.edu "std::string": "String", 396019Shines@cs.fsu.edu "bool": "Bool", 406019Shines@cs.fsu.edu "CacheMemory": "RubyCache", 416019Shines@cs.fsu.edu "WireBuffer": "RubyWireBuffer", 426019Shines@cs.fsu.edu "Sequencer": "RubySequencer", 436019Shines@cs.fsu.edu "DirectoryMemory": "RubyDirectoryMemory", 446019Shines@cs.fsu.edu "MemoryControl": "MemoryControl", 456019Shines@cs.fsu.edu "DMASequencer": "DMASequencer", 466019Shines@cs.fsu.edu "Prefetcher":"Prefetcher", 476019Shines@cs.fsu.edu "Cycles":"Cycles", 486019Shines@cs.fsu.edu } 496019Shines@cs.fsu.edu 506019Shines@cs.fsu.educlass StateMachine(Symbol): 516019Shines@cs.fsu.edu def __init__(self, symtab, ident, location, pairs, config_parameters): 526019Shines@cs.fsu.edu super(StateMachine, self).__init__(symtab, ident, location, pairs) 536019Shines@cs.fsu.edu self.table = None 546019Shines@cs.fsu.edu self.config_parameters = config_parameters 556019Shines@cs.fsu.edu self.prefetchers = [] 566019Shines@cs.fsu.edu 576019Shines@cs.fsu.edu for param in config_parameters: 586243Sgblack@eecs.umich.edu if param.pointer: 596243Sgblack@eecs.umich.edu var = Var(symtab, param.name, location, param.type_ast.type, 606243Sgblack@eecs.umich.edu "(*m_%s_ptr)" % param.name, {}, self) 616243Sgblack@eecs.umich.edu else: 626243Sgblack@eecs.umich.edu var = Var(symtab, param.name, location, param.type_ast.type, 636019Shines@cs.fsu.edu "m_%s" % param.name, {}, self) 646019Shines@cs.fsu.edu self.symtab.registerSym(param.name, var) 656019Shines@cs.fsu.edu if str(param.type_ast.type) == "Prefetcher": 666019Shines@cs.fsu.edu self.prefetchers.append(var) 676019Shines@cs.fsu.edu 686019Shines@cs.fsu.edu self.states = orderdict() 696019Shines@cs.fsu.edu self.events = orderdict() 706019Shines@cs.fsu.edu self.actions = orderdict() 716019Shines@cs.fsu.edu self.request_types = orderdict() 726019Shines@cs.fsu.edu self.transitions = [] 736019Shines@cs.fsu.edu self.in_ports = [] 746019Shines@cs.fsu.edu self.functions = [] 756019Shines@cs.fsu.edu self.objects = [] 766019Shines@cs.fsu.edu self.TBEType = None 776019Shines@cs.fsu.edu self.EntryType = None 786019Shines@cs.fsu.edu 796019Shines@cs.fsu.edu def __repr__(self): 806019Shines@cs.fsu.edu return "[StateMachine: %s]" % self.ident 816019Shines@cs.fsu.edu 826019Shines@cs.fsu.edu def addState(self, state): 836019Shines@cs.fsu.edu assert self.table is None 846019Shines@cs.fsu.edu self.states[state.ident] = state 856019Shines@cs.fsu.edu 866019Shines@cs.fsu.edu def addEvent(self, event): 876019Shines@cs.fsu.edu assert self.table is None 886019Shines@cs.fsu.edu self.events[event.ident] = event 896019Shines@cs.fsu.edu 906019Shines@cs.fsu.edu def addAction(self, action): 916019Shines@cs.fsu.edu assert self.table is None 926019Shines@cs.fsu.edu 936019Shines@cs.fsu.edu # Check for duplicate action 946252Sgblack@eecs.umich.edu for other in self.actions.itervalues(): 956243Sgblack@eecs.umich.edu if action.ident == other.ident: 966243Sgblack@eecs.umich.edu action.warning("Duplicate action definition: %s" % action.ident) 976243Sgblack@eecs.umich.edu action.error("Duplicate action definition: %s" % action.ident) 986019Shines@cs.fsu.edu if action.short == other.short: 996019Shines@cs.fsu.edu other.warning("Duplicate action shorthand: %s" % other.ident) 1006019Shines@cs.fsu.edu other.warning(" shorthand = %s" % other.short) 1016019Shines@cs.fsu.edu action.warning("Duplicate action shorthand: %s" % action.ident) 1026019Shines@cs.fsu.edu action.error(" shorthand = %s" % action.short) 1036252Sgblack@eecs.umich.edu 1046243Sgblack@eecs.umich.edu self.actions[action.ident] = action 1056243Sgblack@eecs.umich.edu 1066243Sgblack@eecs.umich.edu def addRequestType(self, request_type): 1076019Shines@cs.fsu.edu assert self.table is None 1086019Shines@cs.fsu.edu self.request_types[request_type.ident] = request_type 1096019Shines@cs.fsu.edu 1106019Shines@cs.fsu.edu def addTransition(self, trans): 1116019Shines@cs.fsu.edu assert self.table is None 1126019Shines@cs.fsu.edu self.transitions.append(trans) 1136019Shines@cs.fsu.edu 1146252Sgblack@eecs.umich.edu def addInPort(self, var): 1156243Sgblack@eecs.umich.edu self.in_ports.append(var) 1166243Sgblack@eecs.umich.edu 1176243Sgblack@eecs.umich.edu def addFunc(self, func): 1186019Shines@cs.fsu.edu # register func in the symbol table 1196019Shines@cs.fsu.edu self.symtab.registerSym(str(func), func) 1206019Shines@cs.fsu.edu self.functions.append(func) 1216019Shines@cs.fsu.edu 1226019Shines@cs.fsu.edu def addObject(self, obj): 1236019Shines@cs.fsu.edu self.objects.append(obj) 1246019Shines@cs.fsu.edu 1256019Shines@cs.fsu.edu def addType(self, type): 1266019Shines@cs.fsu.edu type_ident = '%s' % type.c_ident 1276019Shines@cs.fsu.edu 1286019Shines@cs.fsu.edu if type_ident == "%s_TBE" %self.ident: 1296019Shines@cs.fsu.edu if self.TBEType != None: 1306019Shines@cs.fsu.edu self.error("Multiple Transaction Buffer types in a " \ 1316019Shines@cs.fsu.edu "single machine."); 1326019Shines@cs.fsu.edu self.TBEType = type 1336019Shines@cs.fsu.edu 1346724Sgblack@eecs.umich.edu elif "interface" in type and "AbstractCacheEntry" == type["interface"]: 1356724Sgblack@eecs.umich.edu if self.EntryType != None: 1366019Shines@cs.fsu.edu self.error("Multiple AbstractCacheEntry types in a " \ 1376019Shines@cs.fsu.edu "single machine."); 1386019Shines@cs.fsu.edu self.EntryType = type 1396019Shines@cs.fsu.edu 1406019Shines@cs.fsu.edu # Needs to be called before accessing the table 1416252Sgblack@eecs.umich.edu def buildTable(self): 1426243Sgblack@eecs.umich.edu assert self.table is None 1436243Sgblack@eecs.umich.edu 1446243Sgblack@eecs.umich.edu table = {} 1456019Shines@cs.fsu.edu 1466019Shines@cs.fsu.edu for trans in self.transitions: 1476019Shines@cs.fsu.edu # Track which actions we touch so we know if we use them 1486019Shines@cs.fsu.edu # all -- really this should be done for all symbols as 1496019Shines@cs.fsu.edu # part of the symbol table, then only trigger it for 1506019Shines@cs.fsu.edu # Actions, States, Events, etc. 1517356Sgblack@eecs.umich.edu 1527356Sgblack@eecs.umich.edu for action in trans.actions: 1537356Sgblack@eecs.umich.edu action.used = True 1547356Sgblack@eecs.umich.edu 1557356Sgblack@eecs.umich.edu index = (trans.state, trans.event) 1567356Sgblack@eecs.umich.edu if index in table: 1577356Sgblack@eecs.umich.edu table[index].warning("Duplicate transition: %s" % table[index]) 1587356Sgblack@eecs.umich.edu trans.error("Duplicate transition: %s" % trans) 1597178Sgblack@eecs.umich.edu table[index] = trans 1607178Sgblack@eecs.umich.edu 1617178Sgblack@eecs.umich.edu # Look at all actions to make sure we used them all 1627337Sgblack@eecs.umich.edu for action in self.actions.itervalues(): 1637178Sgblack@eecs.umich.edu if not action.used: 1647178Sgblack@eecs.umich.edu error_msg = "Unused action: %s" % action.ident 1657178Sgblack@eecs.umich.edu if "desc" in action: 1667178Sgblack@eecs.umich.edu error_msg += ", " + action.desc 1677178Sgblack@eecs.umich.edu action.warning(error_msg) 1687178Sgblack@eecs.umich.edu self.table = table 1697178Sgblack@eecs.umich.edu 1707178Sgblack@eecs.umich.edu def writeCodeFiles(self, path, includes): 1717178Sgblack@eecs.umich.edu self.printControllerPython(path) 1727178Sgblack@eecs.umich.edu self.printControllerHH(path) 1737178Sgblack@eecs.umich.edu self.printControllerCC(path, includes) 1747335Sgblack@eecs.umich.edu self.printCSwitch(path) 1757335Sgblack@eecs.umich.edu self.printCWakeup(path, includes) 1767335Sgblack@eecs.umich.edu 1777335Sgblack@eecs.umich.edu def printControllerPython(self, path): 1787335Sgblack@eecs.umich.edu code = self.symtab.codeFormatter() 1797335Sgblack@eecs.umich.edu ident = self.ident 1807335Sgblack@eecs.umich.edu py_ident = "%s_Controller" % ident 1817335Sgblack@eecs.umich.edu c_ident = "%s_Controller" % self.ident 1827335Sgblack@eecs.umich.edu code(''' 1837335Sgblack@eecs.umich.edufrom m5.params import * 1847335Sgblack@eecs.umich.edufrom m5.SimObject import SimObject 1857335Sgblack@eecs.umich.edufrom Controller import RubyController 1867337Sgblack@eecs.umich.edu 1877335Sgblack@eecs.umich.educlass $py_ident(RubyController): 1887335Sgblack@eecs.umich.edu type = '$py_ident' 1897335Sgblack@eecs.umich.edu cxx_header = 'mem/protocol/${c_ident}.hh' 1907335Sgblack@eecs.umich.edu''') 1917335Sgblack@eecs.umich.edu code.indent() 1927335Sgblack@eecs.umich.edu for param in self.config_parameters: 1937335Sgblack@eecs.umich.edu dflt_str = '' 1947335Sgblack@eecs.umich.edu if param.default is not None: 1957335Sgblack@eecs.umich.edu dflt_str = str(param.default) + ', ' 1967335Sgblack@eecs.umich.edu if python_class_map.has_key(param.type_ast.type.c_ident): 1977335Sgblack@eecs.umich.edu python_type = python_class_map[param.type_ast.type.c_ident] 1987335Sgblack@eecs.umich.edu code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")') 1997178Sgblack@eecs.umich.edu else: 2007178Sgblack@eecs.umich.edu self.error("Unknown c++ to python class conversion for c++ " \ 2017178Sgblack@eecs.umich.edu "type: '%s'. Please update the python_class_map " \ 2027178Sgblack@eecs.umich.edu "in StateMachine.py", param.type_ast.type.c_ident) 2037178Sgblack@eecs.umich.edu code.dedent() 2047178Sgblack@eecs.umich.edu code.write(path, '%s.py' % py_ident) 2057178Sgblack@eecs.umich.edu 2067178Sgblack@eecs.umich.edu 2077178Sgblack@eecs.umich.edu def printControllerHH(self, path): 2087178Sgblack@eecs.umich.edu '''Output the method declarations for the class declaration''' 2097178Sgblack@eecs.umich.edu code = self.symtab.codeFormatter() 2107178Sgblack@eecs.umich.edu ident = self.ident 2117178Sgblack@eecs.umich.edu c_ident = "%s_Controller" % self.ident 2127178Sgblack@eecs.umich.edu 2137178Sgblack@eecs.umich.edu code(''' 2147178Sgblack@eecs.umich.edu/** \\file $c_ident.hh 2157178Sgblack@eecs.umich.edu * 2167178Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__ 2177178Sgblack@eecs.umich.edu * Created by slicc definition of Module "${{self.short}}" 2187178Sgblack@eecs.umich.edu */ 2197178Sgblack@eecs.umich.edu 2207178Sgblack@eecs.umich.edu#ifndef __${ident}_CONTROLLER_HH__ 2217178Sgblack@eecs.umich.edu#define __${ident}_CONTROLLER_HH__ 2227178Sgblack@eecs.umich.edu 2237178Sgblack@eecs.umich.edu#include <iostream> 2247178Sgblack@eecs.umich.edu#include <sstream> 2257178Sgblack@eecs.umich.edu#include <string> 2267178Sgblack@eecs.umich.edu 2277178Sgblack@eecs.umich.edu#include "mem/protocol/TransitionResult.hh" 2287346Sgblack@eecs.umich.edu#include "mem/protocol/Types.hh" 2297346Sgblack@eecs.umich.edu#include "mem/ruby/common/Consumer.hh" 2307346Sgblack@eecs.umich.edu#include "mem/ruby/common/Global.hh" 2317346Sgblack@eecs.umich.edu#include "mem/ruby/slicc_interface/AbstractController.hh" 2327346Sgblack@eecs.umich.edu#include "params/$c_ident.hh" 2337346Sgblack@eecs.umich.edu''') 2347346Sgblack@eecs.umich.edu 2357346Sgblack@eecs.umich.edu seen_types = set() 2367346Sgblack@eecs.umich.edu has_peer = False 2377346Sgblack@eecs.umich.edu for var in self.objects: 2387178Sgblack@eecs.umich.edu if var.type.ident not in seen_types and not var.type.isPrimitive: 2397346Sgblack@eecs.umich.edu code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 2407346Sgblack@eecs.umich.edu if "network" in var and "physical_network" in var: 2417346Sgblack@eecs.umich.edu has_peer = True 2427346Sgblack@eecs.umich.edu seen_types.add(var.type.ident) 2437346Sgblack@eecs.umich.edu 2447346Sgblack@eecs.umich.edu # for adding information to the protocol debug trace 2457346Sgblack@eecs.umich.edu code(''' 2467346Sgblack@eecs.umich.eduextern std::stringstream ${ident}_transitionComment; 2477346Sgblack@eecs.umich.edu 2487346Sgblack@eecs.umich.educlass $c_ident : public AbstractController 2497346Sgblack@eecs.umich.edu{ 2507346Sgblack@eecs.umich.edu public: 2517346Sgblack@eecs.umich.edu typedef ${c_ident}Params Params; 2527346Sgblack@eecs.umich.edu $c_ident(const Params *p); 2537346Sgblack@eecs.umich.edu static int getNumControllers(); 2547178Sgblack@eecs.umich.edu void init(); 2557337Sgblack@eecs.umich.edu MessageBuffer* getMandatoryQueue() const; 2567337Sgblack@eecs.umich.edu const std::string toString() const; 2577337Sgblack@eecs.umich.edu 2587337Sgblack@eecs.umich.edu void print(std::ostream& out) const; 2597337Sgblack@eecs.umich.edu void wakeup(); 2607337Sgblack@eecs.umich.edu void resetStats(); 2617337Sgblack@eecs.umich.edu void regStats(); 2627337Sgblack@eecs.umich.edu void collateStats(); 2637337Sgblack@eecs.umich.edu 2647337Sgblack@eecs.umich.edu void recordCacheTrace(int cntrl, CacheRecorder* tr); 2657337Sgblack@eecs.umich.edu Sequencer* getSequencer() const; 2667337Sgblack@eecs.umich.edu 2677337Sgblack@eecs.umich.edu bool functionalReadBuffers(PacketPtr&); 2687337Sgblack@eecs.umich.edu uint32_t functionalWriteBuffers(PacketPtr&); 2697337Sgblack@eecs.umich.edu 2707178Sgblack@eecs.umich.edu void countTransition(${ident}_State state, ${ident}_Event event); 2717178Sgblack@eecs.umich.edu void possibleTransition(${ident}_State state, ${ident}_Event event); 2727178Sgblack@eecs.umich.edu uint64 getEventCount(${ident}_Event event); 2737178Sgblack@eecs.umich.edu bool isPossible(${ident}_State state, ${ident}_Event event); 2747337Sgblack@eecs.umich.edu uint64 getTransitionCount(${ident}_State state, ${ident}_Event event); 2757337Sgblack@eecs.umich.edu 2767337Sgblack@eecs.umich.eduprivate: 2777337Sgblack@eecs.umich.edu''') 2787346Sgblack@eecs.umich.edu 2797346Sgblack@eecs.umich.edu code.indent() 2807346Sgblack@eecs.umich.edu # added by SS 2817346Sgblack@eecs.umich.edu for param in self.config_parameters: 2827346Sgblack@eecs.umich.edu if param.pointer: 2837337Sgblack@eecs.umich.edu code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;') 2847178Sgblack@eecs.umich.edu else: 2857321Sgblack@eecs.umich.edu code('${{param.type_ast.type}} m_${{param.ident}};') 2867356Sgblack@eecs.umich.edu 2877321Sgblack@eecs.umich.edu code(''' 2887356Sgblack@eecs.umich.eduTransitionResult doTransition(${ident}_Event event, 2897356Sgblack@eecs.umich.edu''') 2907356Sgblack@eecs.umich.edu 2917356Sgblack@eecs.umich.edu if self.EntryType != None: 2927356Sgblack@eecs.umich.edu code(''' 2937356Sgblack@eecs.umich.edu ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 2947356Sgblack@eecs.umich.edu''') 2957356Sgblack@eecs.umich.edu if self.TBEType != None: 2967356Sgblack@eecs.umich.edu code(''' 2977356Sgblack@eecs.umich.edu ${{self.TBEType.c_ident}}* m_tbe_ptr, 2987356Sgblack@eecs.umich.edu''') 2997356Sgblack@eecs.umich.edu 3007321Sgblack@eecs.umich.edu code(''' 3017321Sgblack@eecs.umich.edu const Address addr); 3027321Sgblack@eecs.umich.edu 3037321Sgblack@eecs.umich.eduTransitionResult doTransitionWorker(${ident}_Event event, 3047321Sgblack@eecs.umich.edu ${ident}_State state, 3057321Sgblack@eecs.umich.edu ${ident}_State& next_state, 3067321Sgblack@eecs.umich.edu''') 3077321Sgblack@eecs.umich.edu 3087321Sgblack@eecs.umich.edu if self.TBEType != None: 3097321Sgblack@eecs.umich.edu code(''' 3107321Sgblack@eecs.umich.edu ${{self.TBEType.c_ident}}*& m_tbe_ptr, 3117335Sgblack@eecs.umich.edu''') 3127335Sgblack@eecs.umich.edu if self.EntryType != None: 3137335Sgblack@eecs.umich.edu code(''' 3147335Sgblack@eecs.umich.edu ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 3157335Sgblack@eecs.umich.edu''') 3167335Sgblack@eecs.umich.edu 3177335Sgblack@eecs.umich.edu code(''' 3187335Sgblack@eecs.umich.edu const Address& addr); 3197335Sgblack@eecs.umich.edu 3207321Sgblack@eecs.umich.eduint m_counters[${ident}_State_NUM][${ident}_Event_NUM]; 3217323Sgblack@eecs.umich.eduint m_event_counters[${ident}_Event_NUM]; 3227323Sgblack@eecs.umich.edubool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; 3237323Sgblack@eecs.umich.edu 3247323Sgblack@eecs.umich.edustatic std::vector<Stats::Vector *> eventVec; 3257323Sgblack@eecs.umich.edustatic std::vector<std::vector<Stats::Vector *> > transVec; 3267323Sgblack@eecs.umich.edustatic int m_num_controllers; 3277323Sgblack@eecs.umich.edu 3287323Sgblack@eecs.umich.edu// Internal functions 3297323Sgblack@eecs.umich.edu''') 3307323Sgblack@eecs.umich.edu 3317394Sgblack@eecs.umich.edu for func in self.functions: 3327394Sgblack@eecs.umich.edu proto = func.prototype 3337394Sgblack@eecs.umich.edu if proto: 3347394Sgblack@eecs.umich.edu code('$proto') 3357394Sgblack@eecs.umich.edu 3367394Sgblack@eecs.umich.edu if has_peer: 3377323Sgblack@eecs.umich.edu code('void getQueuesFromPeer(AbstractController *);') 3387323Sgblack@eecs.umich.edu if self.EntryType != None: 3397323Sgblack@eecs.umich.edu code(''' 3407323Sgblack@eecs.umich.edu 3417323Sgblack@eecs.umich.edu// Set and Reset for cache_entry variable 3427323Sgblack@eecs.umich.eduvoid set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); 3437323Sgblack@eecs.umich.eduvoid unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); 3447321Sgblack@eecs.umich.edu''') 3457321Sgblack@eecs.umich.edu 3467321Sgblack@eecs.umich.edu if self.TBEType != None: 3477335Sgblack@eecs.umich.edu code(''' 3487335Sgblack@eecs.umich.edu 3497335Sgblack@eecs.umich.edu// Set and Reset for tbe variable 3507335Sgblack@eecs.umich.eduvoid set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); 3517335Sgblack@eecs.umich.eduvoid unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); 3527335Sgblack@eecs.umich.edu''') 3537335Sgblack@eecs.umich.edu 3547335Sgblack@eecs.umich.edu # Prototype the actions that the controller can take 3557335Sgblack@eecs.umich.edu code(''' 3567335Sgblack@eecs.umich.edu 3577335Sgblack@eecs.umich.edu// Actions 3587335Sgblack@eecs.umich.edu''') 3597335Sgblack@eecs.umich.edu if self.TBEType != None and self.EntryType != None: 3607335Sgblack@eecs.umich.edu for action in self.actions.itervalues(): 3617335Sgblack@eecs.umich.edu code('/** \\brief ${{action.desc}} */') 3627335Sgblack@eecs.umich.edu code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 3637335Sgblack@eecs.umich.edu 'm_tbe_ptr, ${{self.EntryType.c_ident}}*& ' 3647335Sgblack@eecs.umich.edu 'm_cache_entry_ptr, const Address& addr);') 3657335Sgblack@eecs.umich.edu elif self.TBEType != None: 3667335Sgblack@eecs.umich.edu for action in self.actions.itervalues(): 3677335Sgblack@eecs.umich.edu code('/** \\brief ${{action.desc}} */') 3687335Sgblack@eecs.umich.edu code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& ' 3697335Sgblack@eecs.umich.edu 'm_tbe_ptr, const Address& addr);') 3707335Sgblack@eecs.umich.edu elif self.EntryType != None: 3717335Sgblack@eecs.umich.edu for action in self.actions.itervalues(): 3727335Sgblack@eecs.umich.edu code('/** \\brief ${{action.desc}} */') 3737335Sgblack@eecs.umich.edu code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& ' 3747335Sgblack@eecs.umich.edu 'm_cache_entry_ptr, const Address& addr);') 3757335Sgblack@eecs.umich.edu else: 3767335Sgblack@eecs.umich.edu for action in self.actions.itervalues(): 3777335Sgblack@eecs.umich.edu code('/** \\brief ${{action.desc}} */') 3787335Sgblack@eecs.umich.edu code('void ${{action.ident}}(const Address& addr);') 3797335Sgblack@eecs.umich.edu 3807321Sgblack@eecs.umich.edu # the controller internal variables 3817321Sgblack@eecs.umich.edu code(''' 3827321Sgblack@eecs.umich.edu 3837321Sgblack@eecs.umich.edu// Objects 3847321Sgblack@eecs.umich.edu''') 3857321Sgblack@eecs.umich.edu for var in self.objects: 3867335Sgblack@eecs.umich.edu th = var.get("template", "") 3877335Sgblack@eecs.umich.edu code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') 3887335Sgblack@eecs.umich.edu 3897335Sgblack@eecs.umich.edu code.dedent() 3907335Sgblack@eecs.umich.edu code('};') 3917335Sgblack@eecs.umich.edu code('#endif // __${ident}_CONTROLLER_H__') 3927335Sgblack@eecs.umich.edu code.write(path, '%s.hh' % c_ident) 3937335Sgblack@eecs.umich.edu 3947335Sgblack@eecs.umich.edu def printControllerCC(self, path, includes): 3957321Sgblack@eecs.umich.edu '''Output the actions for performing the actions''' 3967326Sgblack@eecs.umich.edu 3977326Sgblack@eecs.umich.edu code = self.symtab.codeFormatter() 3987326Sgblack@eecs.umich.edu ident = self.ident 3997326Sgblack@eecs.umich.edu c_ident = "%s_Controller" % self.ident 4007326Sgblack@eecs.umich.edu has_peer = False 4017326Sgblack@eecs.umich.edu 4027326Sgblack@eecs.umich.edu code(''' 4037326Sgblack@eecs.umich.edu/** \\file $c_ident.cc 4047326Sgblack@eecs.umich.edu * 4057326Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__ 4067326Sgblack@eecs.umich.edu * Created by slicc definition of Module "${{self.short}}" 4077326Sgblack@eecs.umich.edu */ 4087326Sgblack@eecs.umich.edu 4097326Sgblack@eecs.umich.edu#include <sys/types.h> 4107326Sgblack@eecs.umich.edu#include <unistd.h> 4117326Sgblack@eecs.umich.edu 4127326Sgblack@eecs.umich.edu#include <cassert> 4137326Sgblack@eecs.umich.edu#include <sstream> 4147326Sgblack@eecs.umich.edu#include <string> 4157326Sgblack@eecs.umich.edu 4167326Sgblack@eecs.umich.edu#include "base/compiler.hh" 4177326Sgblack@eecs.umich.edu#include "base/cprintf.hh" 4187392Sgblack@eecs.umich.edu#include "debug/RubyGenerated.hh" 4197392Sgblack@eecs.umich.edu#include "debug/RubySlicc.hh" 4207392Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Controller.hh" 4217392Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Event.hh" 4227392Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_State.hh" 4237392Sgblack@eecs.umich.edu#include "mem/protocol/Types.hh" 4247392Sgblack@eecs.umich.edu#include "mem/ruby/common/Global.hh" 4257392Sgblack@eecs.umich.edu#include "mem/ruby/system/System.hh" 4267392Sgblack@eecs.umich.edu''') 4277392Sgblack@eecs.umich.edu for include_path in includes: 4287392Sgblack@eecs.umich.edu code('#include "${{include_path}}"') 4297321Sgblack@eecs.umich.edu 4307321Sgblack@eecs.umich.edu code(''' 4317335Sgblack@eecs.umich.edu 4327335Sgblack@eecs.umich.eduusing namespace std; 4337335Sgblack@eecs.umich.edu''') 4347335Sgblack@eecs.umich.edu 4357335Sgblack@eecs.umich.edu # include object classes 4367335Sgblack@eecs.umich.edu seen_types = set() 4377335Sgblack@eecs.umich.edu for var in self.objects: 4387335Sgblack@eecs.umich.edu if var.type.ident not in seen_types and not var.type.isPrimitive: 4397335Sgblack@eecs.umich.edu code('#include "mem/protocol/${{var.type.c_ident}}.hh"') 4407335Sgblack@eecs.umich.edu seen_types.add(var.type.ident) 4417335Sgblack@eecs.umich.edu 4427335Sgblack@eecs.umich.edu num_in_ports = len(self.in_ports) 4437335Sgblack@eecs.umich.edu 4447335Sgblack@eecs.umich.edu code(''' 4457335Sgblack@eecs.umich.edu$c_ident * 4467335Sgblack@eecs.umich.edu${c_ident}Params::create() 4477335Sgblack@eecs.umich.edu{ 4487335Sgblack@eecs.umich.edu return new $c_ident(this); 4497335Sgblack@eecs.umich.edu} 4507335Sgblack@eecs.umich.edu 4517335Sgblack@eecs.umich.eduint $c_ident::m_num_controllers = 0; 4527335Sgblack@eecs.umich.edustd::vector<Stats::Vector *> $c_ident::eventVec; 4537335Sgblack@eecs.umich.edustd::vector<std::vector<Stats::Vector *> > $c_ident::transVec; 4547335Sgblack@eecs.umich.edu 4557335Sgblack@eecs.umich.edu// for adding information to the protocol debug trace 4567335Sgblack@eecs.umich.edustringstream ${ident}_transitionComment; 4577335Sgblack@eecs.umich.edu 4587335Sgblack@eecs.umich.edu#ifndef NDEBUG 4597335Sgblack@eecs.umich.edu#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) 4607335Sgblack@eecs.umich.edu#else 4617335Sgblack@eecs.umich.edu#define APPEND_TRANSITION_COMMENT(str) do {} while (0) 4627335Sgblack@eecs.umich.edu#endif 4637335Sgblack@eecs.umich.edu 4647335Sgblack@eecs.umich.edu/** \\brief constructor */ 4657335Sgblack@eecs.umich.edu$c_ident::$c_ident(const Params *p) 4667335Sgblack@eecs.umich.edu : AbstractController(p) 4677335Sgblack@eecs.umich.edu{ 4687335Sgblack@eecs.umich.edu m_machineID.type = MachineType_${ident}; 4697335Sgblack@eecs.umich.edu m_machineID.num = m_version; 4707335Sgblack@eecs.umich.edu m_num_controllers++; 4717335Sgblack@eecs.umich.edu 4727335Sgblack@eecs.umich.edu m_in_ports = $num_in_ports; 4737335Sgblack@eecs.umich.edu''') 4747335Sgblack@eecs.umich.edu code.indent() 4757321Sgblack@eecs.umich.edu 4767321Sgblack@eecs.umich.edu # 4777321Sgblack@eecs.umich.edu # After initializing the universal machine parameters, initialize the 4787321Sgblack@eecs.umich.edu # this machines config parameters. Also if these configuration params 4797321Sgblack@eecs.umich.edu # include a sequencer, connect the it to the controller. 4807356Sgblack@eecs.umich.edu # 4817356Sgblack@eecs.umich.edu for param in self.config_parameters: 4827356Sgblack@eecs.umich.edu if param.pointer: 4837356Sgblack@eecs.umich.edu code('m_${{param.name}}_ptr = p->${{param.name}};') 4847356Sgblack@eecs.umich.edu else: 4857356Sgblack@eecs.umich.edu code('m_${{param.name}} = p->${{param.name}};') 4867363Sgblack@eecs.umich.edu if re.compile("sequencer").search(param.name): 4877363Sgblack@eecs.umich.edu code('m_${{param.name}}_ptr->setController(this);') 4887363Sgblack@eecs.umich.edu 4897363Sgblack@eecs.umich.edu for var in self.objects: 4907363Sgblack@eecs.umich.edu if var.ident.find("mandatoryQueue") >= 0: 4917363Sgblack@eecs.umich.edu code(''' 4927363Sgblack@eecs.umich.edum_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}(); 4937363Sgblack@eecs.umich.edum_${{var.c_ident}}_ptr->setReceiver(this); 4947363Sgblack@eecs.umich.edu''') 4957363Sgblack@eecs.umich.edu else: 4967363Sgblack@eecs.umich.edu if "network" in var and "physical_network" in var and \ 4977363Sgblack@eecs.umich.edu var["network"] == "To": 4987363Sgblack@eecs.umich.edu has_peer = True 4997363Sgblack@eecs.umich.edu code(''' 5007372Sgblack@eecs.umich.edum_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}(); 5017389Sgblack@eecs.umich.edupeerQueueMap[${{var["physical_network"]}}] = m_${{var.c_ident}}_ptr; 5027389Sgblack@eecs.umich.edum_${{var.c_ident}}_ptr->setSender(this); 5037372Sgblack@eecs.umich.edu''') 5047372Sgblack@eecs.umich.edu 5057372Sgblack@eecs.umich.edu code(''' 5067372Sgblack@eecs.umich.eduif (p->peer != NULL) 5077372Sgblack@eecs.umich.edu connectWithPeer(p->peer); 5087372Sgblack@eecs.umich.edu 5097372Sgblack@eecs.umich.edufor (int state = 0; state < ${ident}_State_NUM; state++) { 5107372Sgblack@eecs.umich.edu for (int event = 0; event < ${ident}_Event_NUM; event++) { 5117372Sgblack@eecs.umich.edu m_possible[state][event] = false; 5127372Sgblack@eecs.umich.edu m_counters[state][event] = 0; 5137372Sgblack@eecs.umich.edu } 5147372Sgblack@eecs.umich.edu} 5157372Sgblack@eecs.umich.edufor (int event = 0; event < ${ident}_Event_NUM; event++) { 5167372Sgblack@eecs.umich.edu m_event_counters[event] = 0; 5177372Sgblack@eecs.umich.edu} 5187372Sgblack@eecs.umich.edu''') 5197372Sgblack@eecs.umich.edu code.dedent() 5207372Sgblack@eecs.umich.edu code(''' 5217363Sgblack@eecs.umich.edu} 5227363Sgblack@eecs.umich.edu 5237370Sgblack@eecs.umich.eduvoid 5247372Sgblack@eecs.umich.edu$c_ident::init() 5257376Sgblack@eecs.umich.edu{ 5267376Sgblack@eecs.umich.edu MachineType machine_type = string_to_MachineType("${{var.machine.ident}}"); 5277370Sgblack@eecs.umich.edu int base M5_VAR_USED = MachineType_base_number(machine_type); 5287376Sgblack@eecs.umich.edu 5297376Sgblack@eecs.umich.edu // initialize objects 5307370Sgblack@eecs.umich.edu 5317370Sgblack@eecs.umich.edu''') 5327372Sgblack@eecs.umich.edu 5337376Sgblack@eecs.umich.edu code.indent() 5347376Sgblack@eecs.umich.edu for var in self.objects: 5357370Sgblack@eecs.umich.edu vtype = var.type 5367376Sgblack@eecs.umich.edu vid = "m_%s_ptr" % var.c_ident 5377376Sgblack@eecs.umich.edu if "network" not in var: 5387370Sgblack@eecs.umich.edu # Not a network port object 5397370Sgblack@eecs.umich.edu if "primitive" in vtype: 5407371Sgblack@eecs.umich.edu code('$vid = new ${{vtype.c_ident}};') 5417371Sgblack@eecs.umich.edu if "default" in var: 5427372Sgblack@eecs.umich.edu code('(*$vid) = ${{var["default"]}};') 5437376Sgblack@eecs.umich.edu else: 5447376Sgblack@eecs.umich.edu # Normal Object 5457371Sgblack@eecs.umich.edu if var.ident.find("mandatoryQueue") < 0: 5467376Sgblack@eecs.umich.edu th = var.get("template", "") 5477376Sgblack@eecs.umich.edu expr = "%s = new %s%s" % (vid, vtype.c_ident, th) 5487371Sgblack@eecs.umich.edu args = "" 5497371Sgblack@eecs.umich.edu if "non_obj" not in vtype and not vtype.isEnumeration: 5507372Sgblack@eecs.umich.edu args = var.get("constructor", "") 5517376Sgblack@eecs.umich.edu code('$expr($args);') 5527376Sgblack@eecs.umich.edu 5537371Sgblack@eecs.umich.edu code('assert($vid != NULL);') 5547376Sgblack@eecs.umich.edu 5557376Sgblack@eecs.umich.edu if "default" in var: 5567371Sgblack@eecs.umich.edu code('*$vid = ${{var["default"]}}; // Object default') 5577371Sgblack@eecs.umich.edu elif "default" in vtype: 5587363Sgblack@eecs.umich.edu comment = "Type %s default" % vtype.ident 5597363Sgblack@eecs.umich.edu code('*$vid = ${{vtype["default"]}}; // $comment') 5607372Sgblack@eecs.umich.edu 5617376Sgblack@eecs.umich.edu # Set ordering 5627376Sgblack@eecs.umich.edu if "ordered" in var: 5637364Sgblack@eecs.umich.edu # A buffer 5647376Sgblack@eecs.umich.edu code('$vid->setOrdering(${{var["ordered"]}});') 5657376Sgblack@eecs.umich.edu 5667364Sgblack@eecs.umich.edu # Set randomization 5677371Sgblack@eecs.umich.edu if "random" in var: 5687372Sgblack@eecs.umich.edu # A buffer 5697376Sgblack@eecs.umich.edu code('$vid->setRandomization(${{var["random"]}});') 5707376Sgblack@eecs.umich.edu 5717371Sgblack@eecs.umich.edu # Set Priority 5727376Sgblack@eecs.umich.edu if vtype.isBuffer and "rank" in var: 5737376Sgblack@eecs.umich.edu code('$vid->setPriority(${{var["rank"]}});') 5747371Sgblack@eecs.umich.edu 5757363Sgblack@eecs.umich.edu # Set sender and receiver for trigger queue 5767363Sgblack@eecs.umich.edu if var.ident.find("triggerQueue") >= 0: 5777363Sgblack@eecs.umich.edu code('$vid->setSender(this);') 5787372Sgblack@eecs.umich.edu code('$vid->setReceiver(this);') 5797376Sgblack@eecs.umich.edu elif vtype.c_ident == "TimerTable": 5807376Sgblack@eecs.umich.edu code('$vid->setClockObj(this);') 5817367Sgblack@eecs.umich.edu elif var.ident.find("optionalQueue") >= 0: 5827376Sgblack@eecs.umich.edu code('$vid->setSender(this);') 5837376Sgblack@eecs.umich.edu code('$vid->setReceiver(this);') 5847367Sgblack@eecs.umich.edu 5857363Sgblack@eecs.umich.edu else: 5867372Sgblack@eecs.umich.edu # Network port object 5877376Sgblack@eecs.umich.edu network = var["network"] 5887376Sgblack@eecs.umich.edu ordered = var["ordered"] 5897368Sgblack@eecs.umich.edu 5907376Sgblack@eecs.umich.edu if "virtual_network" in var: 5917376Sgblack@eecs.umich.edu vnet = var["virtual_network"] 5927368Sgblack@eecs.umich.edu vnet_type = var["vnet_type"] 5937363Sgblack@eecs.umich.edu 5947363Sgblack@eecs.umich.edu assert var.machine is not None 5957363Sgblack@eecs.umich.edu code(''' 5967372Sgblack@eecs.umich.edu$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type"); 5977376Sgblack@eecs.umich.eduassert($vid != NULL); 5987376Sgblack@eecs.umich.edu''') 5997369Sgblack@eecs.umich.edu 6007376Sgblack@eecs.umich.edu # Set the end 6017376Sgblack@eecs.umich.edu if network == "To": 6027369Sgblack@eecs.umich.edu code('$vid->setSender(this);') 6037363Sgblack@eecs.umich.edu else: 6047363Sgblack@eecs.umich.edu code('$vid->setReceiver(this);') 6057363Sgblack@eecs.umich.edu 6067363Sgblack@eecs.umich.edu # Set ordering 6077363Sgblack@eecs.umich.edu if "ordered" in var: 6087363Sgblack@eecs.umich.edu # A buffer 6097372Sgblack@eecs.umich.edu code('$vid->setOrdering(${{var["ordered"]}});') 6107363Sgblack@eecs.umich.edu 6117376Sgblack@eecs.umich.edu # Set randomization 6127376Sgblack@eecs.umich.edu if "random" in var: 6137363Sgblack@eecs.umich.edu # A buffer 6147363Sgblack@eecs.umich.edu code('$vid->setRandomization(${{var["random"]}});') 6157376Sgblack@eecs.umich.edu 6167376Sgblack@eecs.umich.edu # Set Priority 6177363Sgblack@eecs.umich.edu if "rank" in var: 6187363Sgblack@eecs.umich.edu code('$vid->setPriority(${{var["rank"]}})') 6197363Sgblack@eecs.umich.edu 6207363Sgblack@eecs.umich.edu # Set buffer size 6217363Sgblack@eecs.umich.edu if vtype.isBuffer: 6227372Sgblack@eecs.umich.edu code(''' 6237376Sgblack@eecs.umich.eduif (m_buffer_size > 0) { 6247376Sgblack@eecs.umich.edu $vid->resize(m_buffer_size); 6257363Sgblack@eecs.umich.edu} 6267376Sgblack@eecs.umich.edu''') 6277376Sgblack@eecs.umich.edu 6287363Sgblack@eecs.umich.edu # set description (may be overriden later by port def) 6297363Sgblack@eecs.umich.edu code(''' 6307372Sgblack@eecs.umich.edu$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]"); 6317376Sgblack@eecs.umich.edu 6327376Sgblack@eecs.umich.edu''') 6337366Sgblack@eecs.umich.edu 6347376Sgblack@eecs.umich.edu if vtype.isBuffer: 6357376Sgblack@eecs.umich.edu if "recycle_latency" in var: 6367366Sgblack@eecs.umich.edu code('$vid->setRecycleLatency( ' \ 6377363Sgblack@eecs.umich.edu 'Cycles(${{var["recycle_latency"]}}));') 6387363Sgblack@eecs.umich.edu else: 6397363Sgblack@eecs.umich.edu code('$vid->setRecycleLatency(m_recycle_latency);') 6407372Sgblack@eecs.umich.edu 6417376Sgblack@eecs.umich.edu # Set the prefetchers 6427376Sgblack@eecs.umich.edu code() 6437365Sgblack@eecs.umich.edu for prefetcher in self.prefetchers: 6447376Sgblack@eecs.umich.edu code('${{prefetcher.code}}.setController(this);') 6457376Sgblack@eecs.umich.edu 6467365Sgblack@eecs.umich.edu code() 6477363Sgblack@eecs.umich.edu for port in self.in_ports: 6487372Sgblack@eecs.umich.edu # Set the queue consumers 6497376Sgblack@eecs.umich.edu code('${{port.code}}.setConsumer(this);') 6507376Sgblack@eecs.umich.edu # Set the queue descriptions 6517369Sgblack@eecs.umich.edu code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");') 6527376Sgblack@eecs.umich.edu 6537376Sgblack@eecs.umich.edu # Initialize the transition profiling 6547369Sgblack@eecs.umich.edu code() 6557363Sgblack@eecs.umich.edu for trans in self.transitions: 6567363Sgblack@eecs.umich.edu # Figure out if we stall 6577363Sgblack@eecs.umich.edu stall = False 6587398Sgblack@eecs.umich.edu for action in trans.actions: 6597398Sgblack@eecs.umich.edu if action.ident == "z_stall": 6607398Sgblack@eecs.umich.edu stall = True 6617398Sgblack@eecs.umich.edu 6627398Sgblack@eecs.umich.edu # Only possible if it is not a 'z' case 6637398Sgblack@eecs.umich.edu if not stall: 6647398Sgblack@eecs.umich.edu state = "%s_State_%s" % (self.ident, trans.state.ident) 6657398Sgblack@eecs.umich.edu event = "%s_Event_%s" % (self.ident, trans.event.ident) 6667398Sgblack@eecs.umich.edu code('possibleTransition($state, $event);') 6677398Sgblack@eecs.umich.edu 6687398Sgblack@eecs.umich.edu code.dedent() 6697398Sgblack@eecs.umich.edu code(''' 6707398Sgblack@eecs.umich.edu AbstractController::init(); 6717398Sgblack@eecs.umich.edu resetStats(); 6727398Sgblack@eecs.umich.edu} 6737398Sgblack@eecs.umich.edu''') 6747398Sgblack@eecs.umich.edu 6757363Sgblack@eecs.umich.edu mq_ident = "NULL" 6767377Sgblack@eecs.umich.edu for port in self.in_ports: 6777389Sgblack@eecs.umich.edu if port.code.find("mandatoryQueue_ptr") >= 0: 6787389Sgblack@eecs.umich.edu mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident 6797389Sgblack@eecs.umich.edu 6807389Sgblack@eecs.umich.edu seq_ident = "NULL" 6817389Sgblack@eecs.umich.edu for param in self.config_parameters: 6827377Sgblack@eecs.umich.edu if param.name == "sequencer": 6837389Sgblack@eecs.umich.edu assert(param.pointer) 6847389Sgblack@eecs.umich.edu seq_ident = "m_%s_ptr" % param.name 6857389Sgblack@eecs.umich.edu 6867389Sgblack@eecs.umich.edu code(''' 6877389Sgblack@eecs.umich.edu 6887377Sgblack@eecs.umich.eduvoid 6897363Sgblack@eecs.umich.edu$c_ident::regStats() 6907377Sgblack@eecs.umich.edu{ 6917389Sgblack@eecs.umich.edu AbstractController::regStats(); 6927389Sgblack@eecs.umich.edu 6937389Sgblack@eecs.umich.edu if (m_version == 0) { 6947389Sgblack@eecs.umich.edu for (${ident}_Event event = ${ident}_Event_FIRST; 6957389Sgblack@eecs.umich.edu event < ${ident}_Event_NUM; ++event) { 6967377Sgblack@eecs.umich.edu Stats::Vector *t = new Stats::Vector(); 6977389Sgblack@eecs.umich.edu t->init(m_num_controllers); 6987389Sgblack@eecs.umich.edu t->name(g_system_ptr->name() + ".${c_ident}." + 6997389Sgblack@eecs.umich.edu ${ident}_Event_to_string(event)); 7007389Sgblack@eecs.umich.edu t->flags(Stats::pdf | Stats::total | Stats::oneline | 7017389Sgblack@eecs.umich.edu Stats::nozero); 7027377Sgblack@eecs.umich.edu 7037363Sgblack@eecs.umich.edu eventVec.push_back(t); 7047363Sgblack@eecs.umich.edu } 7057374Sgblack@eecs.umich.edu 7067374Sgblack@eecs.umich.edu for (${ident}_State state = ${ident}_State_FIRST; 7077374Sgblack@eecs.umich.edu state < ${ident}_State_NUM; ++state) { 7087374Sgblack@eecs.umich.edu 7097374Sgblack@eecs.umich.edu transVec.push_back(std::vector<Stats::Vector *>()); 7107374Sgblack@eecs.umich.edu 7117374Sgblack@eecs.umich.edu for (${ident}_Event event = ${ident}_Event_FIRST; 7127374Sgblack@eecs.umich.edu event < ${ident}_Event_NUM; ++event) { 7137374Sgblack@eecs.umich.edu 7147363Sgblack@eecs.umich.edu Stats::Vector *t = new Stats::Vector(); 7157363Sgblack@eecs.umich.edu t->init(m_num_controllers); 7167363Sgblack@eecs.umich.edu t->name(g_system_ptr->name() + ".${c_ident}." + 7177373Sgblack@eecs.umich.edu ${ident}_State_to_string(state) + 7187373Sgblack@eecs.umich.edu "." + ${ident}_Event_to_string(event)); 7197373Sgblack@eecs.umich.edu 7207373Sgblack@eecs.umich.edu t->flags(Stats::pdf | Stats::total | Stats::oneline | 7217373Sgblack@eecs.umich.edu Stats::nozero); 7227373Sgblack@eecs.umich.edu transVec[state].push_back(t); 7237373Sgblack@eecs.umich.edu } 7247373Sgblack@eecs.umich.edu } 7257373Sgblack@eecs.umich.edu } 7267373Sgblack@eecs.umich.edu} 7277373Sgblack@eecs.umich.edu 7287373Sgblack@eecs.umich.eduvoid 7297373Sgblack@eecs.umich.edu$c_ident::collateStats() 7307373Sgblack@eecs.umich.edu{ 7317373Sgblack@eecs.umich.edu for (${ident}_Event event = ${ident}_Event_FIRST; 7327373Sgblack@eecs.umich.edu event < ${ident}_Event_NUM; ++event) { 7337373Sgblack@eecs.umich.edu for (unsigned int i = 0; i < m_num_controllers; ++i) { 7347363Sgblack@eecs.umich.edu std::map<uint32_t, AbstractController *>::iterator it = 7357379Sgblack@eecs.umich.edu g_abs_controls[MachineType_${ident}].find(i); 7367379Sgblack@eecs.umich.edu assert(it != g_abs_controls[MachineType_${ident}].end()); 7377379Sgblack@eecs.umich.edu (*eventVec[event])[i] = 7387379Sgblack@eecs.umich.edu (($c_ident *)(*it).second)->getEventCount(event); 7397379Sgblack@eecs.umich.edu } 7407379Sgblack@eecs.umich.edu } 7417379Sgblack@eecs.umich.edu 7427379Sgblack@eecs.umich.edu for (${ident}_State state = ${ident}_State_FIRST; 7437379Sgblack@eecs.umich.edu state < ${ident}_State_NUM; ++state) { 7447379Sgblack@eecs.umich.edu 7457379Sgblack@eecs.umich.edu for (${ident}_Event event = ${ident}_Event_FIRST; 7467379Sgblack@eecs.umich.edu event < ${ident}_Event_NUM; ++event) { 7477379Sgblack@eecs.umich.edu 7487379Sgblack@eecs.umich.edu for (unsigned int i = 0; i < m_num_controllers; ++i) { 7497379Sgblack@eecs.umich.edu std::map<uint32_t, AbstractController *>::iterator it = 7507379Sgblack@eecs.umich.edu g_abs_controls[MachineType_${ident}].find(i); 7517379Sgblack@eecs.umich.edu assert(it != g_abs_controls[MachineType_${ident}].end()); 7527379Sgblack@eecs.umich.edu (*transVec[state][event])[i] = 7537379Sgblack@eecs.umich.edu (($c_ident *)(*it).second)->getTransitionCount(state, event); 7547379Sgblack@eecs.umich.edu } 7557363Sgblack@eecs.umich.edu } 7567379Sgblack@eecs.umich.edu } 7577379Sgblack@eecs.umich.edu} 7587379Sgblack@eecs.umich.edu 7597379Sgblack@eecs.umich.eduvoid 7607379Sgblack@eecs.umich.edu$c_ident::countTransition(${ident}_State state, ${ident}_Event event) 7617379Sgblack@eecs.umich.edu{ 7627379Sgblack@eecs.umich.edu assert(m_possible[state][event]); 7637379Sgblack@eecs.umich.edu m_counters[state][event]++; 7647379Sgblack@eecs.umich.edu m_event_counters[event]++; 7657379Sgblack@eecs.umich.edu} 7667379Sgblack@eecs.umich.eduvoid 7677379Sgblack@eecs.umich.edu$c_ident::possibleTransition(${ident}_State state, 7687379Sgblack@eecs.umich.edu ${ident}_Event event) 7697379Sgblack@eecs.umich.edu{ 7707379Sgblack@eecs.umich.edu m_possible[state][event] = true; 7717379Sgblack@eecs.umich.edu} 7727379Sgblack@eecs.umich.edu 7737379Sgblack@eecs.umich.eduuint64 7747379Sgblack@eecs.umich.edu$c_ident::getEventCount(${ident}_Event event) 7757379Sgblack@eecs.umich.edu{ 7767363Sgblack@eecs.umich.edu return m_event_counters[event]; 7777380Sgblack@eecs.umich.edu} 7787380Sgblack@eecs.umich.edu 7797380Sgblack@eecs.umich.edubool 7807380Sgblack@eecs.umich.edu$c_ident::isPossible(${ident}_State state, ${ident}_Event event) 7817380Sgblack@eecs.umich.edu{ 7827380Sgblack@eecs.umich.edu return m_possible[state][event]; 7837380Sgblack@eecs.umich.edu} 7847380Sgblack@eecs.umich.edu 7857373Sgblack@eecs.umich.eduuint64 7867380Sgblack@eecs.umich.edu$c_ident::getTransitionCount(${ident}_State state, 7877380Sgblack@eecs.umich.edu ${ident}_Event event) 7887380Sgblack@eecs.umich.edu{ 7897380Sgblack@eecs.umich.edu return m_counters[state][event]; 7907380Sgblack@eecs.umich.edu} 7917380Sgblack@eecs.umich.edu 7927380Sgblack@eecs.umich.eduint 7937373Sgblack@eecs.umich.edu$c_ident::getNumControllers() 7947363Sgblack@eecs.umich.edu{ 7957380Sgblack@eecs.umich.edu return m_num_controllers; 7967380Sgblack@eecs.umich.edu} 7977380Sgblack@eecs.umich.edu 7987380Sgblack@eecs.umich.eduMessageBuffer* 7997380Sgblack@eecs.umich.edu$c_ident::getMandatoryQueue() const 8007380Sgblack@eecs.umich.edu{ 8017380Sgblack@eecs.umich.edu return $mq_ident; 8027380Sgblack@eecs.umich.edu} 8037373Sgblack@eecs.umich.edu 8047380Sgblack@eecs.umich.eduSequencer* 8057380Sgblack@eecs.umich.edu$c_ident::getSequencer() const 8067380Sgblack@eecs.umich.edu{ 8077380Sgblack@eecs.umich.edu return $seq_ident; 8087380Sgblack@eecs.umich.edu} 8097380Sgblack@eecs.umich.edu 8107380Sgblack@eecs.umich.educonst string 8117373Sgblack@eecs.umich.edu$c_ident::toString() const 8127363Sgblack@eecs.umich.edu{ 8137379Sgblack@eecs.umich.edu return "$c_ident"; 8147379Sgblack@eecs.umich.edu} 8157379Sgblack@eecs.umich.edu 8167379Sgblack@eecs.umich.eduvoid 8177379Sgblack@eecs.umich.edu$c_ident::print(ostream& out) const 8187379Sgblack@eecs.umich.edu{ 8197379Sgblack@eecs.umich.edu out << "[$c_ident " << m_version << "]"; 8207379Sgblack@eecs.umich.edu} 8217379Sgblack@eecs.umich.edu 8227379Sgblack@eecs.umich.eduvoid $c_ident::resetStats() 8237379Sgblack@eecs.umich.edu{ 8247379Sgblack@eecs.umich.edu for (int state = 0; state < ${ident}_State_NUM; state++) { 8257379Sgblack@eecs.umich.edu for (int event = 0; event < ${ident}_Event_NUM; event++) { 8267379Sgblack@eecs.umich.edu m_counters[state][event] = 0; 8277379Sgblack@eecs.umich.edu } 8287379Sgblack@eecs.umich.edu } 8297379Sgblack@eecs.umich.edu 8307379Sgblack@eecs.umich.edu for (int event = 0; event < ${ident}_Event_NUM; event++) { 8317379Sgblack@eecs.umich.edu m_event_counters[event] = 0; 8327379Sgblack@eecs.umich.edu } 8337363Sgblack@eecs.umich.edu 8347379Sgblack@eecs.umich.edu AbstractController::resetStats(); 8357379Sgblack@eecs.umich.edu} 8367379Sgblack@eecs.umich.edu''') 8377379Sgblack@eecs.umich.edu 8387379Sgblack@eecs.umich.edu if self.EntryType != None: 8397379Sgblack@eecs.umich.edu code(''' 8407379Sgblack@eecs.umich.edu 8417379Sgblack@eecs.umich.edu// Set and Reset for cache_entry variable 8427379Sgblack@eecs.umich.eduvoid 8437379Sgblack@eecs.umich.edu$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) 8447379Sgblack@eecs.umich.edu{ 8457379Sgblack@eecs.umich.edu m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; 8467379Sgblack@eecs.umich.edu} 8477379Sgblack@eecs.umich.edu 8487379Sgblack@eecs.umich.eduvoid 8497379Sgblack@eecs.umich.edu$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) 8507379Sgblack@eecs.umich.edu{ 8517379Sgblack@eecs.umich.edu m_cache_entry_ptr = 0; 8527379Sgblack@eecs.umich.edu} 8537379Sgblack@eecs.umich.edu''') 8547363Sgblack@eecs.umich.edu 8557363Sgblack@eecs.umich.edu if self.TBEType != None: 8567363Sgblack@eecs.umich.edu code(''' 8577363Sgblack@eecs.umich.edu 8587363Sgblack@eecs.umich.edu// Set and Reset for tbe variable 8597363Sgblack@eecs.umich.eduvoid 8607363Sgblack@eecs.umich.edu$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) 8617363Sgblack@eecs.umich.edu{ 8627363Sgblack@eecs.umich.edu m_tbe_ptr = m_new_tbe; 8637363Sgblack@eecs.umich.edu} 8647363Sgblack@eecs.umich.edu 8657363Sgblack@eecs.umich.eduvoid 8667363Sgblack@eecs.umich.edu$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) 867{ 868 m_tbe_ptr = NULL; 869} 870''') 871 872 code(''' 873 874void 875$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr) 876{ 877''') 878 # 879 # Record cache contents for all associated caches. 880 # 881 code.indent() 882 for param in self.config_parameters: 883 if param.type_ast.type.ident == "CacheMemory": 884 assert(param.pointer) 885 code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);') 886 887 code.dedent() 888 code(''' 889} 890 891// Actions 892''') 893 if self.TBEType != None and self.EntryType != None: 894 for action in self.actions.itervalues(): 895 if "c_code" not in action: 896 continue 897 898 code(''' 899/** \\brief ${{action.desc}} */ 900void 901$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 902{ 903 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 904 ${{action["c_code"]}} 905} 906 907''') 908 elif self.TBEType != None: 909 for action in self.actions.itervalues(): 910 if "c_code" not in action: 911 continue 912 913 code(''' 914/** \\brief ${{action.desc}} */ 915void 916$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr) 917{ 918 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 919 ${{action["c_code"]}} 920} 921 922''') 923 elif self.EntryType != None: 924 for action in self.actions.itervalues(): 925 if "c_code" not in action: 926 continue 927 928 code(''' 929/** \\brief ${{action.desc}} */ 930void 931$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) 932{ 933 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 934 ${{action["c_code"]}} 935} 936 937''') 938 else: 939 for action in self.actions.itervalues(): 940 if "c_code" not in action: 941 continue 942 943 code(''' 944/** \\brief ${{action.desc}} */ 945void 946$c_ident::${{action.ident}}(const Address& addr) 947{ 948 DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n"); 949 ${{action["c_code"]}} 950} 951 952''') 953 for func in self.functions: 954 code(func.generateCode()) 955 956 # Function for functional reads from messages buffered in the controller 957 code(''' 958bool 959$c_ident::functionalReadBuffers(PacketPtr& pkt) 960{ 961''') 962 for var in self.objects: 963 vtype = var.type 964 if vtype.isBuffer: 965 vid = "m_%s_ptr" % var.c_ident 966 code('if ($vid->functionalRead(pkt)) { return true; }') 967 code(''' 968 return false; 969} 970''') 971 972 # Function for functional writes to messages buffered in the controller 973 code(''' 974uint32_t 975$c_ident::functionalWriteBuffers(PacketPtr& pkt) 976{ 977 uint32_t num_functional_writes = 0; 978''') 979 for var in self.objects: 980 vtype = var.type 981 if vtype.isBuffer: 982 vid = "m_%s_ptr" % var.c_ident 983 code('num_functional_writes += $vid->functionalWrite(pkt);') 984 code(''' 985 return num_functional_writes; 986} 987''') 988 989 # Check if this controller has a peer, if yes then write the 990 # function for connecting to the peer. 991 if has_peer: 992 code(''' 993 994void 995$c_ident::getQueuesFromPeer(AbstractController *peer) 996{ 997''') 998 for var in self.objects: 999 if "network" in var and "physical_network" in var and \ 1000 var["network"] == "From": 1001 code(''' 1002m_${{var.c_ident}}_ptr = peer->getPeerQueue(${{var["physical_network"]}}); 1003assert(m_${{var.c_ident}}_ptr != NULL); 1004m_${{var.c_ident}}_ptr->setReceiver(this); 1005 1006''') 1007 code('}') 1008 1009 code.write(path, "%s.cc" % c_ident) 1010 1011 def printCWakeup(self, path, includes): 1012 '''Output the wakeup loop for the events''' 1013 1014 code = self.symtab.codeFormatter() 1015 ident = self.ident 1016 1017 outputRequest_types = True 1018 if len(self.request_types) == 0: 1019 outputRequest_types = False 1020 1021 code(''' 1022// Auto generated C++ code started by $__file__:$__line__ 1023// ${ident}: ${{self.short}} 1024 1025#include <sys/types.h> 1026#include <unistd.h> 1027 1028#include <cassert> 1029 1030#include "base/misc.hh" 1031#include "debug/RubySlicc.hh" 1032#include "mem/protocol/${ident}_Controller.hh" 1033#include "mem/protocol/${ident}_Event.hh" 1034#include "mem/protocol/${ident}_State.hh" 1035''') 1036 1037 if outputRequest_types: 1038 code('''#include "mem/protocol/${ident}_RequestType.hh"''') 1039 1040 code(''' 1041#include "mem/protocol/Types.hh" 1042#include "mem/ruby/common/Global.hh" 1043#include "mem/ruby/system/System.hh" 1044''') 1045 1046 1047 for include_path in includes: 1048 code('#include "${{include_path}}"') 1049 1050 code(''' 1051 1052using namespace std; 1053 1054void 1055${ident}_Controller::wakeup() 1056{ 1057 int counter = 0; 1058 while (true) { 1059 // Some cases will put us into an infinite loop without this limit 1060 assert(counter <= m_transitions_per_cycle); 1061 if (counter == m_transitions_per_cycle) { 1062 // Count how often we are fully utilized 1063 m_fully_busy_cycles++; 1064 1065 // Wakeup in another cycle and try again 1066 scheduleEvent(Cycles(1)); 1067 break; 1068 } 1069''') 1070 1071 code.indent() 1072 code.indent() 1073 1074 # InPorts 1075 # 1076 for port in self.in_ports: 1077 code.indent() 1078 code('// ${ident}InPort $port') 1079 if port.pairs.has_key("rank"): 1080 code('m_cur_in_port = ${{port.pairs["rank"]}};') 1081 else: 1082 code('m_cur_in_port = 0;') 1083 code('${{port["c_code_in_port"]}}') 1084 code.dedent() 1085 1086 code('') 1087 1088 code.dedent() 1089 code.dedent() 1090 code(''' 1091 break; // If we got this far, we have nothing left todo 1092 } 1093} 1094''') 1095 1096 code.write(path, "%s_Wakeup.cc" % self.ident) 1097 1098 def printCSwitch(self, path): 1099 '''Output switch statement for transition table''' 1100 1101 code = self.symtab.codeFormatter() 1102 ident = self.ident 1103 1104 code(''' 1105// Auto generated C++ code started by $__file__:$__line__ 1106// ${ident}: ${{self.short}} 1107 1108#include <cassert> 1109 1110#include "base/misc.hh" 1111#include "base/trace.hh" 1112#include "debug/ProtocolTrace.hh" 1113#include "debug/RubyGenerated.hh" 1114#include "mem/protocol/${ident}_Controller.hh" 1115#include "mem/protocol/${ident}_Event.hh" 1116#include "mem/protocol/${ident}_State.hh" 1117#include "mem/protocol/Types.hh" 1118#include "mem/ruby/common/Global.hh" 1119#include "mem/ruby/system/System.hh" 1120 1121#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) 1122 1123#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) 1124#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) 1125 1126TransitionResult 1127${ident}_Controller::doTransition(${ident}_Event event, 1128''') 1129 if self.EntryType != None: 1130 code(''' 1131 ${{self.EntryType.c_ident}}* m_cache_entry_ptr, 1132''') 1133 if self.TBEType != None: 1134 code(''' 1135 ${{self.TBEType.c_ident}}* m_tbe_ptr, 1136''') 1137 code(''' 1138 const Address addr) 1139{ 1140''') 1141 if self.TBEType != None and self.EntryType != None: 1142 code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);') 1143 elif self.TBEType != None: 1144 code('${ident}_State state = getState(m_tbe_ptr, addr);') 1145 elif self.EntryType != None: 1146 code('${ident}_State state = getState(m_cache_entry_ptr, addr);') 1147 else: 1148 code('${ident}_State state = getState(addr);') 1149 1150 code(''' 1151 ${ident}_State next_state = state; 1152 1153 DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", 1154 *this, curCycle(), ${ident}_State_to_string(state), 1155 ${ident}_Event_to_string(event), addr); 1156 1157 TransitionResult result = 1158''') 1159 if self.TBEType != None and self.EntryType != None: 1160 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') 1161 elif self.TBEType != None: 1162 code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') 1163 elif self.EntryType != None: 1164 code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') 1165 else: 1166 code('doTransitionWorker(event, state, next_state, addr);') 1167 1168 code(''' 1169 if (result == TransitionResult_Valid) { 1170 DPRINTF(RubyGenerated, "next_state: %s\\n", 1171 ${ident}_State_to_string(next_state)); 1172 countTransition(state, event); 1173 DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n", 1174 curTick(), m_version, "${ident}", 1175 ${ident}_Event_to_string(event), 1176 ${ident}_State_to_string(state), 1177 ${ident}_State_to_string(next_state), 1178 addr, GET_TRANSITION_COMMENT()); 1179 1180 CLEAR_TRANSITION_COMMENT(); 1181''') 1182 if self.TBEType != None and self.EntryType != None: 1183 code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') 1184 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1185 elif self.TBEType != None: 1186 code('setState(m_tbe_ptr, addr, next_state);') 1187 code('setAccessPermission(addr, next_state);') 1188 elif self.EntryType != None: 1189 code('setState(m_cache_entry_ptr, addr, next_state);') 1190 code('setAccessPermission(m_cache_entry_ptr, addr, next_state);') 1191 else: 1192 code('setState(addr, next_state);') 1193 code('setAccessPermission(addr, next_state);') 1194 1195 code(''' 1196 } else if (result == TransitionResult_ResourceStall) { 1197 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1198 curTick(), m_version, "${ident}", 1199 ${ident}_Event_to_string(event), 1200 ${ident}_State_to_string(state), 1201 ${ident}_State_to_string(next_state), 1202 addr, "Resource Stall"); 1203 } else if (result == TransitionResult_ProtocolStall) { 1204 DPRINTF(RubyGenerated, "stalling\\n"); 1205 DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n", 1206 curTick(), m_version, "${ident}", 1207 ${ident}_Event_to_string(event), 1208 ${ident}_State_to_string(state), 1209 ${ident}_State_to_string(next_state), 1210 addr, "Protocol Stall"); 1211 } 1212 1213 return result; 1214} 1215 1216TransitionResult 1217${ident}_Controller::doTransitionWorker(${ident}_Event event, 1218 ${ident}_State state, 1219 ${ident}_State& next_state, 1220''') 1221 1222 if self.TBEType != None: 1223 code(''' 1224 ${{self.TBEType.c_ident}}*& m_tbe_ptr, 1225''') 1226 if self.EntryType != None: 1227 code(''' 1228 ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, 1229''') 1230 code(''' 1231 const Address& addr) 1232{ 1233 switch(HASH_FUN(state, event)) { 1234''') 1235 1236 # This map will allow suppress generating duplicate code 1237 cases = orderdict() 1238 1239 for trans in self.transitions: 1240 case_string = "%s_State_%s, %s_Event_%s" % \ 1241 (self.ident, trans.state.ident, self.ident, trans.event.ident) 1242 1243 case = self.symtab.codeFormatter() 1244 # Only set next_state if it changes 1245 if trans.state != trans.nextState: 1246 ns_ident = trans.nextState.ident 1247 case('next_state = ${ident}_State_${ns_ident};') 1248 1249 actions = trans.actions 1250 request_types = trans.request_types 1251 1252 # Check for resources 1253 case_sorter = [] 1254 res = trans.resources 1255 for key,val in res.iteritems(): 1256 if key.type.ident != "DNUCAStopTable": 1257 val = ''' 1258if (!%s.areNSlotsAvailable(%s)) 1259 return TransitionResult_ResourceStall; 1260''' % (key.code, val) 1261 case_sorter.append(val) 1262 1263 # Check all of the request_types for resource constraints 1264 for request_type in request_types: 1265 val = ''' 1266if (!checkResourceAvailable(%s_RequestType_%s, addr)) { 1267 return TransitionResult_ResourceStall; 1268} 1269''' % (self.ident, request_type.ident) 1270 case_sorter.append(val) 1271 1272 # Emit the code sequences in a sorted order. This makes the 1273 # output deterministic (without this the output order can vary 1274 # since Map's keys() on a vector of pointers is not deterministic 1275 for c in sorted(case_sorter): 1276 case("$c") 1277 1278 # Record access types for this transition 1279 for request_type in request_types: 1280 case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);') 1281 1282 # Figure out if we stall 1283 stall = False 1284 for action in actions: 1285 if action.ident == "z_stall": 1286 stall = True 1287 break 1288 1289 if stall: 1290 case('return TransitionResult_ProtocolStall;') 1291 else: 1292 if self.TBEType != None and self.EntryType != None: 1293 for action in actions: 1294 case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') 1295 elif self.TBEType != None: 1296 for action in actions: 1297 case('${{action.ident}}(m_tbe_ptr, addr);') 1298 elif self.EntryType != None: 1299 for action in actions: 1300 case('${{action.ident}}(m_cache_entry_ptr, addr);') 1301 else: 1302 for action in actions: 1303 case('${{action.ident}}(addr);') 1304 case('return TransitionResult_Valid;') 1305 1306 case = str(case) 1307 1308 # Look to see if this transition code is unique. 1309 if case not in cases: 1310 cases[case] = [] 1311 1312 cases[case].append(case_string) 1313 1314 # Walk through all of the unique code blocks and spit out the 1315 # corresponding case statement elements 1316 for case,transitions in cases.iteritems(): 1317 # Iterative over all the multiple transitions that share 1318 # the same code 1319 for trans in transitions: 1320 code(' case HASH_FUN($trans):') 1321 code(' $case') 1322 1323 code(''' 1324 default: 1325 fatal("Invalid transition\\n" 1326 "%s time: %d addr: %s event: %s state: %s\\n", 1327 name(), curCycle(), addr, event, state); 1328 } 1329 return TransitionResult_Valid; 1330} 1331''') 1332 code.write(path, "%s_Transitions.cc" % self.ident) 1333 1334 1335 # ************************** 1336 # ******* HTML Files ******* 1337 # ************************** 1338 def frameRef(self, click_href, click_target, over_href, over_num, text): 1339 code = self.symtab.codeFormatter(fix_newlines=False) 1340 code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\" 1341 if (parent.frames[$over_num].location != parent.location + '$over_href') { 1342 parent.frames[$over_num].location='$over_href' 1343 }\"> 1344 ${{html.formatShorthand(text)}} 1345 </A>""") 1346 return str(code) 1347 1348 def writeHTMLFiles(self, path): 1349 # Create table with no row hilighted 1350 self.printHTMLTransitions(path, None) 1351 1352 # Generate transition tables 1353 for state in self.states.itervalues(): 1354 self.printHTMLTransitions(path, state) 1355 1356 # Generate action descriptions 1357 for action in self.actions.itervalues(): 1358 name = "%s_action_%s.html" % (self.ident, action.ident) 1359 code = html.createSymbol(action, "Action") 1360 code.write(path, name) 1361 1362 # Generate state descriptions 1363 for state in self.states.itervalues(): 1364 name = "%s_State_%s.html" % (self.ident, state.ident) 1365 code = html.createSymbol(state, "State") 1366 code.write(path, name) 1367 1368 # Generate event descriptions 1369 for event in self.events.itervalues(): 1370 name = "%s_Event_%s.html" % (self.ident, event.ident) 1371 code = html.createSymbol(event, "Event") 1372 code.write(path, name) 1373 1374 def printHTMLTransitions(self, path, active_state): 1375 code = self.symtab.codeFormatter() 1376 1377 code(''' 1378<HTML> 1379<BODY link="blue" vlink="blue"> 1380 1381<H1 align="center">${{html.formatShorthand(self.short)}}: 1382''') 1383 code.indent() 1384 for i,machine in enumerate(self.symtab.getAllType(StateMachine)): 1385 mid = machine.ident 1386 if i != 0: 1387 extra = " - " 1388 else: 1389 extra = "" 1390 if machine == self: 1391 code('$extra$mid') 1392 else: 1393 code('$extra<A target="Table" href="${mid}_table.html">$mid</A>') 1394 code.dedent() 1395 1396 code(""" 1397</H1> 1398 1399<TABLE border=1> 1400<TR> 1401 <TH> </TH> 1402""") 1403 1404 for event in self.events.itervalues(): 1405 href = "%s_Event_%s.html" % (self.ident, event.ident) 1406 ref = self.frameRef(href, "Status", href, "1", event.short) 1407 code('<TH bgcolor=white>$ref</TH>') 1408 1409 code('</TR>') 1410 # -- Body of table 1411 for state in self.states.itervalues(): 1412 # -- Each row 1413 if state == active_state: 1414 color = "yellow" 1415 else: 1416 color = "white" 1417 1418 click = "%s_table_%s.html" % (self.ident, state.ident) 1419 over = "%s_State_%s.html" % (self.ident, state.ident) 1420 text = html.formatShorthand(state.short) 1421 ref = self.frameRef(click, "Table", over, "1", state.short) 1422 code(''' 1423<TR> 1424 <TH bgcolor=$color>$ref</TH> 1425''') 1426 1427 # -- One column for each event 1428 for event in self.events.itervalues(): 1429 trans = self.table.get((state,event), None) 1430 if trans is None: 1431 # This is the no transition case 1432 if state == active_state: 1433 color = "#C0C000" 1434 else: 1435 color = "lightgrey" 1436 1437 code('<TD bgcolor=$color> </TD>') 1438 continue 1439 1440 next = trans.nextState 1441 stall_action = False 1442 1443 # -- Get the actions 1444 for action in trans.actions: 1445 if action.ident == "z_stall" or \ 1446 action.ident == "zz_recycleMandatoryQueue": 1447 stall_action = True 1448 1449 # -- Print out "actions/next-state" 1450 if stall_action: 1451 if state == active_state: 1452 color = "#C0C000" 1453 else: 1454 color = "lightgrey" 1455 1456 elif active_state and next.ident == active_state.ident: 1457 color = "aqua" 1458 elif state == active_state: 1459 color = "yellow" 1460 else: 1461 color = "white" 1462 1463 code('<TD bgcolor=$color>') 1464 for action in trans.actions: 1465 href = "%s_action_%s.html" % (self.ident, action.ident) 1466 ref = self.frameRef(href, "Status", href, "1", 1467 action.short) 1468 code(' $ref') 1469 if next != state: 1470 if trans.actions: 1471 code('/') 1472 click = "%s_table_%s.html" % (self.ident, next.ident) 1473 over = "%s_State_%s.html" % (self.ident, next.ident) 1474 ref = self.frameRef(click, "Table", over, "1", next.short) 1475 code("$ref") 1476 code("</TD>") 1477 1478 # -- Each row 1479 if state == active_state: 1480 color = "yellow" 1481 else: 1482 color = "white" 1483 1484 click = "%s_table_%s.html" % (self.ident, state.ident) 1485 over = "%s_State_%s.html" % (self.ident, state.ident) 1486 ref = self.frameRef(click, "Table", over, "1", state.short) 1487 code(''' 1488 <TH bgcolor=$color>$ref</TH> 1489</TR> 1490''') 1491 code(''' 1492<!- Column footer-> 1493<TR> 1494 <TH> </TH> 1495''') 1496 1497 for event in self.events.itervalues(): 1498 href = "%s_Event_%s.html" % (self.ident, event.ident) 1499 ref = self.frameRef(href, "Status", href, "1", event.short) 1500 code('<TH bgcolor=white>$ref</TH>') 1501 code(''' 1502</TR> 1503</TABLE> 1504</BODY></HTML> 1505''') 1506 1507 1508 if active_state: 1509 name = "%s_table_%s.html" % (self.ident, active_state.ident) 1510 else: 1511 name = "%s_table.html" % self.ident 1512 code.write(path, name) 1513 1514__all__ = [ "StateMachine" ] 1515