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>&nbsp;</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