StateMachine.py revision 6888
15331Sgblack@eecs.umich.edu# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
25331Sgblack@eecs.umich.edu# Copyright (c) 2009 The Hewlett-Packard Development Company
35331Sgblack@eecs.umich.edu# All rights reserved.
45331Sgblack@eecs.umich.edu#
55331Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
65331Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are
75331Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright
85331Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
95331Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
105331Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
115331Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution;
125331Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its
135331Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from
145331Sgblack@eecs.umich.edu# this software without specific prior written permission.
155331Sgblack@eecs.umich.edu#
165331Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175331Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185331Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195331Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205331Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215331Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225331Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235331Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245331Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255331Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265331Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275331Sgblack@eecs.umich.edu
285331Sgblack@eecs.umich.edufrom m5.util import code_formatter, orderdict
295331Sgblack@eecs.umich.edu
304276Sgblack@eecs.umich.edufrom slicc.symbols.Symbol import Symbol
314276Sgblack@eecs.umich.edufrom slicc.symbols.Var import Var
324276Sgblack@eecs.umich.eduimport slicc.generate.html as html
334276Sgblack@eecs.umich.edu
344276Sgblack@eecs.umich.edupython_class_map = {"int": "Int",
354276Sgblack@eecs.umich.edu                    "string": "String",
364276Sgblack@eecs.umich.edu                    "bool": "Bool",
374276Sgblack@eecs.umich.edu                    "CacheMemory": "RubyCache",
384276Sgblack@eecs.umich.edu                    "Sequencer": "RubySequencer",
394276Sgblack@eecs.umich.edu                    "DirectoryMemory": "RubyDirectoryMemory",
404276Sgblack@eecs.umich.edu                    "MemoryControl": "RubyMemoryControl",
414276Sgblack@eecs.umich.edu                    "DMASequencer": "DMASequencer"
424276Sgblack@eecs.umich.edu                    }
434276Sgblack@eecs.umich.edu
444276Sgblack@eecs.umich.educlass StateMachine(Symbol):
454276Sgblack@eecs.umich.edu    def __init__(self, symtab, ident, location, pairs, config_parameters):
464276Sgblack@eecs.umich.edu        super(StateMachine, self).__init__(symtab, ident, location, pairs)
474276Sgblack@eecs.umich.edu        self.table = None
484276Sgblack@eecs.umich.edu        self.config_parameters = config_parameters
494276Sgblack@eecs.umich.edu        for param in config_parameters:
504276Sgblack@eecs.umich.edu            if param.pointer:
514276Sgblack@eecs.umich.edu                var = Var(symtab, param.name, location, param.type_ast.type,
524276Sgblack@eecs.umich.edu                          "(*m_%s_ptr)" % param.name, {}, self)
534276Sgblack@eecs.umich.edu            else:
544276Sgblack@eecs.umich.edu                var = Var(symtab, param.name, location, param.type_ast.type,
554276Sgblack@eecs.umich.edu                          "m_%s" % param.name, {}, self)
564276Sgblack@eecs.umich.edu            self.symtab.registerSym(param.name, var)
574276Sgblack@eecs.umich.edu
584276Sgblack@eecs.umich.edu        self.states = orderdict()
594276Sgblack@eecs.umich.edu        self.events = orderdict()
604276Sgblack@eecs.umich.edu        self.actions = orderdict()
614276Sgblack@eecs.umich.edu        self.transitions = []
624276Sgblack@eecs.umich.edu        self.in_ports = []
634276Sgblack@eecs.umich.edu        self.functions = []
644276Sgblack@eecs.umich.edu        self.objects = []
654276Sgblack@eecs.umich.edu
664276Sgblack@eecs.umich.edu        self.message_buffer_names = []
674276Sgblack@eecs.umich.edu
684276Sgblack@eecs.umich.edu    def __repr__(self):
694276Sgblack@eecs.umich.edu        return "[StateMachine: %s]" % self.ident
704276Sgblack@eecs.umich.edu
714276Sgblack@eecs.umich.edu    def addState(self, state):
724276Sgblack@eecs.umich.edu        assert self.table is None
734276Sgblack@eecs.umich.edu        self.states[state.ident] = state
744276Sgblack@eecs.umich.edu
754276Sgblack@eecs.umich.edu    def addEvent(self, event):
764276Sgblack@eecs.umich.edu        assert self.table is None
774276Sgblack@eecs.umich.edu        self.events[event.ident] = event
784276Sgblack@eecs.umich.edu
794276Sgblack@eecs.umich.edu    def addAction(self, action):
804276Sgblack@eecs.umich.edu        assert self.table is None
814276Sgblack@eecs.umich.edu
824276Sgblack@eecs.umich.edu        # Check for duplicate action
834276Sgblack@eecs.umich.edu        for other in self.actions.itervalues():
844276Sgblack@eecs.umich.edu            if action.ident == other.ident:
854276Sgblack@eecs.umich.edu                action.warning("Duplicate action definition: %s" % action.ident)
864276Sgblack@eecs.umich.edu                action.error("Duplicate action definition: %s" % action.ident)
874276Sgblack@eecs.umich.edu            if action.short == other.short:
884276Sgblack@eecs.umich.edu                other.warning("Duplicate action shorthand: %s" % other.ident)
894711Sgblack@eecs.umich.edu                other.warning("    shorthand = %s" % other.short)
904276Sgblack@eecs.umich.edu                action.warning("Duplicate action shorthand: %s" % action.ident)
914276Sgblack@eecs.umich.edu                action.error("    shorthand = %s" % action.short)
925238Sgblack@eecs.umich.edu
935238Sgblack@eecs.umich.edu        self.actions[action.ident] = action
945238Sgblack@eecs.umich.edu
955238Sgblack@eecs.umich.edu    def addTransition(self, trans):
965238Sgblack@eecs.umich.edu        assert self.table is None
975238Sgblack@eecs.umich.edu        self.transitions.append(trans)
985238Sgblack@eecs.umich.edu
995238Sgblack@eecs.umich.edu    def addInPort(self, var):
1005238Sgblack@eecs.umich.edu        self.in_ports.append(var)
1015238Sgblack@eecs.umich.edu
1025238Sgblack@eecs.umich.edu    def addFunc(self, func):
1035238Sgblack@eecs.umich.edu        # register func in the symbol table
1045238Sgblack@eecs.umich.edu        self.symtab.registerSym(str(func), func)
1055238Sgblack@eecs.umich.edu        self.functions.append(func)
1065238Sgblack@eecs.umich.edu
1075238Sgblack@eecs.umich.edu    def addObject(self, obj):
1085238Sgblack@eecs.umich.edu        self.objects.append(obj)
1095238Sgblack@eecs.umich.edu
1105238Sgblack@eecs.umich.edu    # Needs to be called before accessing the table
1115238Sgblack@eecs.umich.edu    def buildTable(self):
1125238Sgblack@eecs.umich.edu        assert self.table is None
1135238Sgblack@eecs.umich.edu
1145238Sgblack@eecs.umich.edu        table = {}
1155238Sgblack@eecs.umich.edu
1165238Sgblack@eecs.umich.edu        for trans in self.transitions:
1175238Sgblack@eecs.umich.edu            # Track which actions we touch so we know if we use them
1185238Sgblack@eecs.umich.edu            # all -- really this should be done for all symbols as
1195238Sgblack@eecs.umich.edu            # part of the symbol table, then only trigger it for
1205238Sgblack@eecs.umich.edu            # Actions, States, Events, etc.
1215238Sgblack@eecs.umich.edu
1225238Sgblack@eecs.umich.edu            for action in trans.actions:
1235238Sgblack@eecs.umich.edu                action.used = True
1245238Sgblack@eecs.umich.edu
1255238Sgblack@eecs.umich.edu            index = (trans.state, trans.event)
1265238Sgblack@eecs.umich.edu            if index in table:
1275238Sgblack@eecs.umich.edu                table[index].warning("Duplicate transition: %s" % table[index])
1285238Sgblack@eecs.umich.edu                trans.error("Duplicate transition: %s" % trans)
1295238Sgblack@eecs.umich.edu            table[index] = trans
1305238Sgblack@eecs.umich.edu
1315683Sgblack@eecs.umich.edu        # Look at all actions to make sure we used them all
1325238Sgblack@eecs.umich.edu        for action in self.actions.itervalues():
1335238Sgblack@eecs.umich.edu            if not action.used:
1345238Sgblack@eecs.umich.edu                error_msg = "Unused action: %s" % action.ident
1355238Sgblack@eecs.umich.edu                if "desc" in action:
1365238Sgblack@eecs.umich.edu                    error_msg += ", "  + action.desc
1375238Sgblack@eecs.umich.edu                action.warning(error_msg)
1385238Sgblack@eecs.umich.edu        self.table = table
1395238Sgblack@eecs.umich.edu
1405291Sgblack@eecs.umich.edu    def writeCodeFiles(self, path):
1415291Sgblack@eecs.umich.edu        self.printControllerPython(path)
1425291Sgblack@eecs.umich.edu        self.printControllerHH(path)
1435291Sgblack@eecs.umich.edu        self.printControllerCC(path)
1445291Sgblack@eecs.umich.edu        self.printCSwitch(path)
1455291Sgblack@eecs.umich.edu        self.printCWakeup(path)
1465291Sgblack@eecs.umich.edu        self.printProfilerCC(path)
1475291Sgblack@eecs.umich.edu        self.printProfilerHH(path)
1485291Sgblack@eecs.umich.edu
1495292Sgblack@eecs.umich.edu        for func in self.functions:
1505292Sgblack@eecs.umich.edu            func.writeCodeFiles(path)
1515292Sgblack@eecs.umich.edu
1525292Sgblack@eecs.umich.edu    def printControllerPython(self, path):
1535292Sgblack@eecs.umich.edu        code = code_formatter()
1545292Sgblack@eecs.umich.edu        ident = self.ident
1555292Sgblack@eecs.umich.edu        py_ident = "%s_Controller" % ident
1565292Sgblack@eecs.umich.edu        c_ident = "%s_Controller" % self.ident
1575292Sgblack@eecs.umich.edu        code('''
1585238Sgblack@eecs.umich.edufrom m5.params import *
1595238Sgblack@eecs.umich.edufrom m5.SimObject import SimObject
1605359Sgblack@eecs.umich.edufrom Controller import RubyController
1615238Sgblack@eecs.umich.edu
1625238Sgblack@eecs.umich.educlass $py_ident(RubyController):
1635238Sgblack@eecs.umich.edu    type = '$py_ident'
1644276Sgblack@eecs.umich.edu''')
1654276Sgblack@eecs.umich.edu        code.indent()
1665789Sgblack@eecs.umich.edu        for param in self.config_parameters:
1675789Sgblack@eecs.umich.edu            dflt_str = ''
1685789Sgblack@eecs.umich.edu            if param.default is not None:
1695789Sgblack@eecs.umich.edu                dflt_str = str(param.default) + ', '
1705789Sgblack@eecs.umich.edu            if python_class_map.has_key(param.type_ast.type.c_ident):
1715789Sgblack@eecs.umich.edu                python_type = python_class_map[param.type_ast.type.c_ident]
1725789Sgblack@eecs.umich.edu                code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")')
1735789Sgblack@eecs.umich.edu            else:
1745789Sgblack@eecs.umich.edu                self.error("Unknown c++ to python class conversion for c++ " \
1755789Sgblack@eecs.umich.edu                           "type: '%s'. Please update the python_class_map " \
1765789Sgblack@eecs.umich.edu                           "in StateMachine.py", param.type_ast.type.c_ident)
1775789Sgblack@eecs.umich.edu        code.dedent()
1785789Sgblack@eecs.umich.edu        code.write(path, '%s.py' % py_ident)
1795789Sgblack@eecs.umich.edu
1805789Sgblack@eecs.umich.edu
1815789Sgblack@eecs.umich.edu    def printControllerHH(self, path):
1825789Sgblack@eecs.umich.edu        '''Output the method declarations for the class declaration'''
1835789Sgblack@eecs.umich.edu        code = code_formatter()
1845789Sgblack@eecs.umich.edu        ident = self.ident
1855789Sgblack@eecs.umich.edu        c_ident = "%s_Controller" % self.ident
1865789Sgblack@eecs.umich.edu
1875789Sgblack@eecs.umich.edu        self.message_buffer_names = []
1885789Sgblack@eecs.umich.edu
1895789Sgblack@eecs.umich.edu        code('''
1905789Sgblack@eecs.umich.edu/** \\file $ident.hh
1915789Sgblack@eecs.umich.edu *
1925789Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__
1935789Sgblack@eecs.umich.edu * Created by slicc definition of Module "${{self.short}}"
1945789Sgblack@eecs.umich.edu */
1955789Sgblack@eecs.umich.edu
1965789Sgblack@eecs.umich.edu#ifndef ${ident}_CONTROLLER_H
1975789Sgblack@eecs.umich.edu#define ${ident}_CONTROLLER_H
1985789Sgblack@eecs.umich.edu
1995789Sgblack@eecs.umich.edu#include "params/$c_ident.hh"
2005789Sgblack@eecs.umich.edu
2015789Sgblack@eecs.umich.edu#include "mem/ruby/common/Global.hh"
2025789Sgblack@eecs.umich.edu#include "mem/ruby/common/Consumer.hh"
2035789Sgblack@eecs.umich.edu#include "mem/ruby/slicc_interface/AbstractController.hh"
2045789Sgblack@eecs.umich.edu#include "mem/protocol/TransitionResult.hh"
2055789Sgblack@eecs.umich.edu#include "mem/protocol/Types.hh"
2065789Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Profiler.hh"
2075789Sgblack@eecs.umich.edu''')
2085789Sgblack@eecs.umich.edu
2095789Sgblack@eecs.umich.edu        seen_types = set()
2105789Sgblack@eecs.umich.edu        for var in self.objects:
2115789Sgblack@eecs.umich.edu            if var.type.ident not in seen_types and not var.type.isPrimitive:
2125789Sgblack@eecs.umich.edu                code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
2135789Sgblack@eecs.umich.edu            seen_types.add(var.type.ident)
2145789Sgblack@eecs.umich.edu
2155789Sgblack@eecs.umich.edu        # for adding information to the protocol debug trace
2165789Sgblack@eecs.umich.edu        code('''
2175789Sgblack@eecs.umich.eduextern stringstream ${ident}_transitionComment;
2185789Sgblack@eecs.umich.edu
2195789Sgblack@eecs.umich.educlass $c_ident : public AbstractController {
2205789Sgblack@eecs.umich.edu#ifdef CHECK_COHERENCE
2215789Sgblack@eecs.umich.edu#endif /* CHECK_COHERENCE */
2225789Sgblack@eecs.umich.edupublic:
2235789Sgblack@eecs.umich.edu    typedef ${c_ident}Params Params;
2245789Sgblack@eecs.umich.edu    $c_ident(const Params *p);
2255789Sgblack@eecs.umich.edu    static int getNumControllers();
2265789Sgblack@eecs.umich.edu    void init();
2275789Sgblack@eecs.umich.edu    MessageBuffer* getMandatoryQueue() const;
2285789Sgblack@eecs.umich.edu    const int & getVersion() const;
2295789Sgblack@eecs.umich.edu    const string toString() const;
2305789Sgblack@eecs.umich.edu    const string getName() const;
2315789Sgblack@eecs.umich.edu    const MachineType getMachineType() const;
2325789Sgblack@eecs.umich.edu    void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; }
2335789Sgblack@eecs.umich.edu    void print(ostream& out) const;
2345789Sgblack@eecs.umich.edu    void printConfig(ostream& out) const;
2355789Sgblack@eecs.umich.edu    void wakeup();
2365789Sgblack@eecs.umich.edu    void printStats(ostream& out) const { s_profiler.dumpStats(out); }
2375789Sgblack@eecs.umich.edu    void clearStats() { s_profiler.clearStats(); }
2385789Sgblack@eecs.umich.edu    void blockOnQueue(Address addr, MessageBuffer* port);
2395789Sgblack@eecs.umich.edu    void unblock(Address addr);
2405789Sgblack@eecs.umich.eduprivate:
2415789Sgblack@eecs.umich.edu''')
2425789Sgblack@eecs.umich.edu
2435789Sgblack@eecs.umich.edu        code.indent()
2445789Sgblack@eecs.umich.edu        # added by SS
2455789Sgblack@eecs.umich.edu        for param in self.config_parameters:
2465789Sgblack@eecs.umich.edu            if param.pointer:
2475789Sgblack@eecs.umich.edu                code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;')
2485789Sgblack@eecs.umich.edu            else:
2495789Sgblack@eecs.umich.edu                code('${{param.type_ast.type}} m_${{param.ident}};')
2505789Sgblack@eecs.umich.edu
2515789Sgblack@eecs.umich.edu        code('''
2525789Sgblack@eecs.umich.eduint m_number_of_TBEs;
2535789Sgblack@eecs.umich.edu
2545789Sgblack@eecs.umich.eduTransitionResult doTransition(${ident}_Event event, ${ident}_State state, const Address& addr); // in ${ident}_Transitions.cc
2555789Sgblack@eecs.umich.eduTransitionResult doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr); // in ${ident}_Transitions.cc
2564712Sgblack@eecs.umich.edustring m_name;
2574711Sgblack@eecs.umich.eduint m_transitions_per_cycle;
2584712Sgblack@eecs.umich.eduint m_buffer_size;
2595659Sgblack@eecs.umich.eduint m_recycle_latency;
2604712Sgblack@eecs.umich.edumap< string, string > m_cfg;
2614276Sgblack@eecs.umich.eduNodeID m_version;
2624276Sgblack@eecs.umich.eduNetwork* m_net_ptr;
2634276Sgblack@eecs.umich.eduMachineID m_machineID;
2644276Sgblack@eecs.umich.edubool m_is_blocking;
2654276Sgblack@eecs.umich.edumap< Address, MessageBuffer* > m_block_map;
2664276Sgblack@eecs.umich.edu${ident}_Profiler s_profiler;
2674712Sgblack@eecs.umich.edustatic int m_num_controllers;
2684712Sgblack@eecs.umich.edu// Internal functions
2694730Sgblack@eecs.umich.edu''')
2704760Sgblack@eecs.umich.edu
2714730Sgblack@eecs.umich.edu        for func in self.functions:
2725422Sgblack@eecs.umich.edu            proto = func.prototype
2735422Sgblack@eecs.umich.edu            if proto:
2745422Sgblack@eecs.umich.edu                code('$proto')
2754276Sgblack@eecs.umich.edu
2764760Sgblack@eecs.umich.edu        code('''
2774760Sgblack@eecs.umich.edu
2784760Sgblack@eecs.umich.edu// Actions
2795020Sgblack@eecs.umich.edu''')
2805020Sgblack@eecs.umich.edu        for action in self.actions.itervalues():
2815020Sgblack@eecs.umich.edu            code('/** \\brief ${{action.desc}} */')
2825020Sgblack@eecs.umich.edu            code('void ${{action.ident}}(const Address& addr);')
2835020Sgblack@eecs.umich.edu
2845020Sgblack@eecs.umich.edu        # the controller internal variables
2855020Sgblack@eecs.umich.edu        code('''
2865020Sgblack@eecs.umich.edu
2875020Sgblack@eecs.umich.edu// Object
2885020Sgblack@eecs.umich.edu''')
2895020Sgblack@eecs.umich.edu        for var in self.objects:
2905020Sgblack@eecs.umich.edu            th = var.get("template_hack", "")
2915020Sgblack@eecs.umich.edu            code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;')
2925020Sgblack@eecs.umich.edu
2934760Sgblack@eecs.umich.edu            if var.type.ident == "MessageBuffer":
2944760Sgblack@eecs.umich.edu                self.message_buffer_names.append("m_%s_ptr" % var.c_ident)
2954760Sgblack@eecs.umich.edu
2965020Sgblack@eecs.umich.edu        code.dedent()
2975020Sgblack@eecs.umich.edu        code('};')
2985020Sgblack@eecs.umich.edu        code('#endif // ${ident}_CONTROLLER_H')
2995020Sgblack@eecs.umich.edu        code.write(path, '%s.hh' % c_ident)
3005020Sgblack@eecs.umich.edu
3014760Sgblack@eecs.umich.edu    def printControllerCC(self, path):
3024760Sgblack@eecs.umich.edu        '''Output the actions for performing the actions'''
3034760Sgblack@eecs.umich.edu
3045020Sgblack@eecs.umich.edu        code = code_formatter()
3055020Sgblack@eecs.umich.edu        ident = self.ident
3065029Sgblack@eecs.umich.edu        c_ident = "%s_Controller" % self.ident
3075029Sgblack@eecs.umich.edu
3085020Sgblack@eecs.umich.edu        code('''
3095020Sgblack@eecs.umich.edu/** \\file $ident.cc
3105020Sgblack@eecs.umich.edu *
3115020Sgblack@eecs.umich.edu * Auto generated C++ code started by $__file__:$__line__
3124760Sgblack@eecs.umich.edu * Created by slicc definition of Module "${{self.short}}"
3134760Sgblack@eecs.umich.edu */
3144760Sgblack@eecs.umich.edu
3155030Sgblack@eecs.umich.edu#include "mem/ruby/common/Global.hh"
3165030Sgblack@eecs.umich.edu#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
3175020Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Controller.hh"
3185020Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_State.hh"
3194760Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Event.hh"
3204760Sgblack@eecs.umich.edu#include "mem/protocol/Types.hh"
3214276Sgblack@eecs.umich.edu#include "mem/ruby/system/System.hh"
3224276Sgblack@eecs.umich.edu''')
3235331Sgblack@eecs.umich.edu
3245331Sgblack@eecs.umich.edu        # include object classes
3255331Sgblack@eecs.umich.edu        seen_types = set()
3265331Sgblack@eecs.umich.edu        for var in self.objects:
3275331Sgblack@eecs.umich.edu            if var.type.ident not in seen_types and not var.type.isPrimitive:
3285331Sgblack@eecs.umich.edu                code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
3295331Sgblack@eecs.umich.edu            seen_types.add(var.type.ident)
3305331Sgblack@eecs.umich.edu
3315331Sgblack@eecs.umich.edu        code('''
3325331Sgblack@eecs.umich.edu$c_ident *
3335331Sgblack@eecs.umich.edu${c_ident}Params::create()
3345331Sgblack@eecs.umich.edu{
3355331Sgblack@eecs.umich.edu    return new $c_ident(this);
3365331Sgblack@eecs.umich.edu}
3375331Sgblack@eecs.umich.edu
3384276Sgblack@eecs.umich.edu
3395020Sgblack@eecs.umich.eduint $c_ident::m_num_controllers = 0;
3405020Sgblack@eecs.umich.edu
3415020Sgblack@eecs.umich.edustringstream ${ident}_transitionComment;
3425296Sgblack@eecs.umich.edu#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str)
3435020Sgblack@eecs.umich.edu/** \\brief constructor */
3445241Sgblack@eecs.umich.edu$c_ident::$c_ident(const Params *p)
3455020Sgblack@eecs.umich.edu    : AbstractController(p)
3465020Sgblack@eecs.umich.edu{
3475020Sgblack@eecs.umich.edu    m_version = p->version;
3485020Sgblack@eecs.umich.edu    m_transitions_per_cycle = p->transitions_per_cycle;
3495020Sgblack@eecs.umich.edu    m_buffer_size = p->buffer_size;
3505020Sgblack@eecs.umich.edu    m_recycle_latency = p->recycle_latency;
3515020Sgblack@eecs.umich.edu    m_number_of_TBEs = p->number_of_TBEs;
3525020Sgblack@eecs.umich.edu''')
3535020Sgblack@eecs.umich.edu        code.indent()
3545020Sgblack@eecs.umich.edu
3555020Sgblack@eecs.umich.edu        #
3564276Sgblack@eecs.umich.edu        # After initializing the universal machine parameters, initialize the
3575020Sgblack@eecs.umich.edu        # this machines config parameters.  Also detemine if these configuration
3585020Sgblack@eecs.umich.edu        # params include a sequencer.  This information will be used later for
3595020Sgblack@eecs.umich.edu        # contecting the sequencer back to the L1 cache controller.
3605031Sgblack@eecs.umich.edu        #
3615031Sgblack@eecs.umich.edu        contains_sequencer = False
3625031Sgblack@eecs.umich.edu        for param in self.config_parameters:
3635031Sgblack@eecs.umich.edu            if param.name == "sequencer" or param.name == "dma_sequencer":
3645020Sgblack@eecs.umich.edu                contains_sequencer = True
3655020Sgblack@eecs.umich.edu            if param.pointer:
3665020Sgblack@eecs.umich.edu                code('m_${{param.name}}_ptr = p->${{param.name}};')
3675020Sgblack@eecs.umich.edu            else:
3685020Sgblack@eecs.umich.edu                code('m_${{param.name}} = p->${{param.name}};')
3695020Sgblack@eecs.umich.edu
3705020Sgblack@eecs.umich.edu        #
3715020Sgblack@eecs.umich.edu        # For the l1 cache controller, add the special atomic support which
3725020Sgblack@eecs.umich.edu        # includes passing the sequencer a pointer to the controller.
3735020Sgblack@eecs.umich.edu        #
3745020Sgblack@eecs.umich.edu        if self.ident == "L1Cache":
3755020Sgblack@eecs.umich.edu            if not contains_sequencer:
3765020Sgblack@eecs.umich.edu                self.error("The L1Cache controller must include the sequencer " \
3775020Sgblack@eecs.umich.edu                           "configuration parameter")
3785020Sgblack@eecs.umich.edu
3795020Sgblack@eecs.umich.edu            code('''
3805020Sgblack@eecs.umich.edum_sequencer_ptr->setController(this);
3815020Sgblack@eecs.umich.edu''')
3825020Sgblack@eecs.umich.edu        #
3835020Sgblack@eecs.umich.edu        # For the DMA controller, pass the sequencer a pointer to the
3845020Sgblack@eecs.umich.edu        # controller.
3855020Sgblack@eecs.umich.edu        #
3865020Sgblack@eecs.umich.edu        if self.ident == "DMA":
3875020Sgblack@eecs.umich.edu            if not contains_sequencer:
3885020Sgblack@eecs.umich.edu                self.error("The DMA controller must include the sequencer " \
3895020Sgblack@eecs.umich.edu                           "configuration parameter")
3905020Sgblack@eecs.umich.edu
3915020Sgblack@eecs.umich.edu            code('''
3925058Sgblack@eecs.umich.edum_dma_sequencer_ptr->setController(this);
3935020Sgblack@eecs.umich.edu''')
3945020Sgblack@eecs.umich.edu
3955020Sgblack@eecs.umich.edu        code('m_num_controllers++;')
3965020Sgblack@eecs.umich.edu        for var in self.objects:
3975046Sgblack@eecs.umich.edu            if var.ident.find("mandatoryQueue") >= 0:
3985046Sgblack@eecs.umich.edu                code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();')
3995046Sgblack@eecs.umich.edu
4005046Sgblack@eecs.umich.edu        code.dedent()
4015020Sgblack@eecs.umich.edu        code('''
4025020Sgblack@eecs.umich.edu}
4035020Sgblack@eecs.umich.edu
4045020Sgblack@eecs.umich.eduvoid $c_ident::init()
4054276Sgblack@eecs.umich.edu{
4064276Sgblack@eecs.umich.edu    m_machineID.type = MachineType_${ident};
4075149Sgblack@eecs.umich.edu    m_machineID.num = m_version;
4085409Sgblack@eecs.umich.edu
4095149Sgblack@eecs.umich.edu    // Objects
4104712Sgblack@eecs.umich.edu    s_profiler.setVersion(m_version);
4114712Sgblack@eecs.umich.edu''')
4124712Sgblack@eecs.umich.edu
4134730Sgblack@eecs.umich.edu        code.indent()
4144712Sgblack@eecs.umich.edu        for var in self.objects:
4154276Sgblack@eecs.umich.edu            vtype = var.type
4164276Sgblack@eecs.umich.edu            vid = "m_%s_ptr" % var.c_ident
4174712Sgblack@eecs.umich.edu            if "network" not in var:
4184712Sgblack@eecs.umich.edu                # Not a network port object
4194712Sgblack@eecs.umich.edu                if "primitive" in vtype:
4204712Sgblack@eecs.umich.edu                    code('$vid = new ${{vtype.c_ident}};')
4214712Sgblack@eecs.umich.edu                    if "default" in var:
4224712Sgblack@eecs.umich.edu                        code('(*$vid) = ${{var["default"]}};')
4234712Sgblack@eecs.umich.edu                else:
4244712Sgblack@eecs.umich.edu                    # Normal Object
4254276Sgblack@eecs.umich.edu                    # added by SS
4264760Sgblack@eecs.umich.edu                    if "factory" in var:
4274760Sgblack@eecs.umich.edu                        code('$vid = ${{var["factory"]}};')
4284760Sgblack@eecs.umich.edu                    elif var.ident.find("mandatoryQueue") < 0:
4294760Sgblack@eecs.umich.edu                        th = var.get("template_hack", "")
4304760Sgblack@eecs.umich.edu                        expr = "%s  = new %s%s" % (vid, vtype.c_ident, th)
4314760Sgblack@eecs.umich.edu
4324760Sgblack@eecs.umich.edu                        args = ""
4334760Sgblack@eecs.umich.edu                        if "non_obj" not in vtype and not vtype.isEnumeration:
4344760Sgblack@eecs.umich.edu                            if expr.find("TBETable") >= 0:
4354760Sgblack@eecs.umich.edu                                args = "m_number_of_TBEs"
4364760Sgblack@eecs.umich.edu                            else:
4374760Sgblack@eecs.umich.edu                                args = var.get("constructor_hack", "")
4384760Sgblack@eecs.umich.edu                            args = "(%s)" % args
4394760Sgblack@eecs.umich.edu
4404760Sgblack@eecs.umich.edu                        code('$expr$args;')
4414760Sgblack@eecs.umich.edu                    else:
4424760Sgblack@eecs.umich.edu                        code(';')
4434760Sgblack@eecs.umich.edu
4444760Sgblack@eecs.umich.edu                    code('assert($vid != NULL);')
4454760Sgblack@eecs.umich.edu
4464760Sgblack@eecs.umich.edu                    if "default" in var:
4474276Sgblack@eecs.umich.edu                        code('(*$vid) = ${{var["default"]}}; // Object default')
4485020Sgblack@eecs.umich.edu                    elif "default" in vtype:
4495020Sgblack@eecs.umich.edu                        code('(*$vid) = ${{vtype["default"]}}; // Type ${{vtype.ident}} default')
4505020Sgblack@eecs.umich.edu
4515020Sgblack@eecs.umich.edu                    # Set ordering
4525020Sgblack@eecs.umich.edu                    if "ordered" in var and "trigger_queue" not in var:
4535020Sgblack@eecs.umich.edu                        # A buffer
4545020Sgblack@eecs.umich.edu                        code('$vid->setOrdering(${{var["ordered"]}});')
4555020Sgblack@eecs.umich.edu
4565020Sgblack@eecs.umich.edu                    # Set randomization
4575020Sgblack@eecs.umich.edu                    if "random" in var:
4585020Sgblack@eecs.umich.edu                        # A buffer
4595020Sgblack@eecs.umich.edu                        code('$vid->setRandomization(${{var["random"]}});')
4605020Sgblack@eecs.umich.edu
4615020Sgblack@eecs.umich.edu                    # Set Priority
4625020Sgblack@eecs.umich.edu                    if vtype.isBuffer and \
4635020Sgblack@eecs.umich.edu                           "rank" in var and "trigger_queue" not in var:
4645020Sgblack@eecs.umich.edu                        code('$vid->setPriority(${{var["rank"]}});')
4655020Sgblack@eecs.umich.edu            else:
4665020Sgblack@eecs.umich.edu                # Network port object
4675020Sgblack@eecs.umich.edu                network = var["network"]
4685020Sgblack@eecs.umich.edu                ordered =  var["ordered"]
4695020Sgblack@eecs.umich.edu                vnet = var["virtual_network"]
4705020Sgblack@eecs.umich.edu
4715020Sgblack@eecs.umich.edu                assert var.machine is not None
4725020Sgblack@eecs.umich.edu                code('''
4735020Sgblack@eecs.umich.edu$vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string_to_MachineType("${{var.machine.ident}}")), $ordered, $vnet);
4745052Sgblack@eecs.umich.edu''')
4755052Sgblack@eecs.umich.edu
4765052Sgblack@eecs.umich.edu                code('assert($vid != NULL);')
4775020Sgblack@eecs.umich.edu
4785020Sgblack@eecs.umich.edu                # Set ordering
4795059Sgblack@eecs.umich.edu                if "ordered" in var:
4805059Sgblack@eecs.umich.edu                    # A buffer
4815059Sgblack@eecs.umich.edu                    code('$vid->setOrdering(${{var["ordered"]}});')
4825059Sgblack@eecs.umich.edu
4835059Sgblack@eecs.umich.edu                # Set randomization
4845059Sgblack@eecs.umich.edu                if "random" in var:
4855059Sgblack@eecs.umich.edu                    # A buffer
4865020Sgblack@eecs.umich.edu                    code('$vid->setRandomization(${{var["random"]}})')
4874276Sgblack@eecs.umich.edu
4885020Sgblack@eecs.umich.edu                # Set Priority
4895020Sgblack@eecs.umich.edu                if "rank" in var:
4905020Sgblack@eecs.umich.edu                    code('$vid->setPriority(${{var["rank"]}})')
4915020Sgblack@eecs.umich.edu
4925020Sgblack@eecs.umich.edu                # Set buffer size
4935020Sgblack@eecs.umich.edu                if vtype.isBuffer:
4945020Sgblack@eecs.umich.edu                    code('''
4955020Sgblack@eecs.umich.eduif (m_buffer_size > 0) {
4965020Sgblack@eecs.umich.edu    $vid->setSize(m_buffer_size);
4975020Sgblack@eecs.umich.edu}
4985020Sgblack@eecs.umich.edu''')
4995020Sgblack@eecs.umich.edu
5005020Sgblack@eecs.umich.edu                # set description (may be overriden later by port def)
5015020Sgblack@eecs.umich.edu                code('$vid->setDescription("[Version " + int_to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");')
5025020Sgblack@eecs.umich.edu
5035020Sgblack@eecs.umich.edu        # Set the queue consumers
5045020Sgblack@eecs.umich.edu        code.insert_newline()
5055020Sgblack@eecs.umich.edu        for port in self.in_ports:
5065020Sgblack@eecs.umich.edu            code('${{port.code}}.setConsumer(this);')
5075020Sgblack@eecs.umich.edu
5085020Sgblack@eecs.umich.edu        # Set the queue descriptions
5095020Sgblack@eecs.umich.edu        code.insert_newline()
5105020Sgblack@eecs.umich.edu        for port in self.in_ports:
5115020Sgblack@eecs.umich.edu            code('${{port.code}}.setDescription("[Version " + int_to_string(m_version) + ", $ident, $port]");')
5125020Sgblack@eecs.umich.edu
5135020Sgblack@eecs.umich.edu        # Initialize the transition profiling
5145020Sgblack@eecs.umich.edu        code.insert_newline()
5155020Sgblack@eecs.umich.edu        for trans in self.transitions:
5165020Sgblack@eecs.umich.edu            # Figure out if we stall
5175020Sgblack@eecs.umich.edu            stall = False
5185020Sgblack@eecs.umich.edu            for action in trans.actions:
5195020Sgblack@eecs.umich.edu                if action.ident == "z_stall":
5205020Sgblack@eecs.umich.edu                    stall = True
5215020Sgblack@eecs.umich.edu
5225020Sgblack@eecs.umich.edu            # Only possible if it is not a 'z' case
5235020Sgblack@eecs.umich.edu            if not stall:
5245047Sgblack@eecs.umich.edu                state = "%s_State_%s" % (self.ident, trans.state.ident)
5255047Sgblack@eecs.umich.edu                event = "%s_Event_%s" % (self.ident, trans.event.ident)
5265020Sgblack@eecs.umich.edu                code('s_profiler.possibleTransition($state, $event);')
5275047Sgblack@eecs.umich.edu
5285020Sgblack@eecs.umich.edu        # added by SS to initialize recycle_latency of message buffers
5295047Sgblack@eecs.umich.edu        for buf in self.message_buffer_names:
5305020Sgblack@eecs.umich.edu            code("$buf->setRecycleLatency(m_recycle_latency);")
5315020Sgblack@eecs.umich.edu
5325020Sgblack@eecs.umich.edu        code.dedent()
5335020Sgblack@eecs.umich.edu        code('}')
5344276Sgblack@eecs.umich.edu
5355020Sgblack@eecs.umich.edu        has_mandatory_q = False
5365020Sgblack@eecs.umich.edu        for port in self.in_ports:
5375020Sgblack@eecs.umich.edu            if port.code.find("mandatoryQueue_ptr") >= 0:
5385020Sgblack@eecs.umich.edu                has_mandatory_q = True
5395020Sgblack@eecs.umich.edu
5405020Sgblack@eecs.umich.edu        if has_mandatory_q:
5415020Sgblack@eecs.umich.edu            mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident
5425020Sgblack@eecs.umich.edu        else:
5435020Sgblack@eecs.umich.edu            mq_ident = "NULL"
5445020Sgblack@eecs.umich.edu
5455020Sgblack@eecs.umich.edu        code('''
5465020Sgblack@eecs.umich.eduint $c_ident::getNumControllers() {
5475020Sgblack@eecs.umich.edu    return m_num_controllers;
5485020Sgblack@eecs.umich.edu}
5495020Sgblack@eecs.umich.edu
5505020Sgblack@eecs.umich.eduMessageBuffer* $c_ident::getMandatoryQueue() const {
5515020Sgblack@eecs.umich.edu    return $mq_ident;
5525020Sgblack@eecs.umich.edu}
5535020Sgblack@eecs.umich.edu
5545020Sgblack@eecs.umich.educonst int & $c_ident::getVersion() const{
5555020Sgblack@eecs.umich.edu    return m_version;
5565020Sgblack@eecs.umich.edu}
5575020Sgblack@eecs.umich.edu
5585020Sgblack@eecs.umich.educonst string $c_ident::toString() const{
5594276Sgblack@eecs.umich.edu    return "$c_ident";
5605020Sgblack@eecs.umich.edu}
5615020Sgblack@eecs.umich.edu
5625020Sgblack@eecs.umich.educonst string $c_ident::getName() const{
5635020Sgblack@eecs.umich.edu    return m_name;
5645020Sgblack@eecs.umich.edu}
5655020Sgblack@eecs.umich.educonst MachineType $c_ident::getMachineType() const{
5665020Sgblack@eecs.umich.edu    return MachineType_${ident};
5675020Sgblack@eecs.umich.edu}
5685020Sgblack@eecs.umich.edu
5695020Sgblack@eecs.umich.eduvoid $c_ident::blockOnQueue(Address addr, MessageBuffer* port) {
5705020Sgblack@eecs.umich.edu    m_is_blocking = true;
5715020Sgblack@eecs.umich.edu    m_block_map[addr] = port;
5725020Sgblack@eecs.umich.edu}
5735020Sgblack@eecs.umich.eduvoid $c_ident::unblock(Address addr) {
5745020Sgblack@eecs.umich.edu    m_block_map.erase(addr);
5755020Sgblack@eecs.umich.edu    if (m_block_map.size() == 0) {
5765020Sgblack@eecs.umich.edu       m_is_blocking = false;
5775020Sgblack@eecs.umich.edu    }
5785020Sgblack@eecs.umich.edu}
5795020Sgblack@eecs.umich.edu
5805020Sgblack@eecs.umich.eduvoid $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; }
5815020Sgblack@eecs.umich.edu
5825020Sgblack@eecs.umich.eduvoid $c_ident::printConfig(ostream& out) const {
5835020Sgblack@eecs.umich.edu    out << "$c_ident config: " << m_name << endl;
5845020Sgblack@eecs.umich.edu    out << "  version: " << m_version << endl;
5855020Sgblack@eecs.umich.edu    for (map<string, string>::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) {
5865020Sgblack@eecs.umich.edu        out << "  " << (*it).first << ": " << (*it).second << endl;
5875020Sgblack@eecs.umich.edu    }
5884276Sgblack@eecs.umich.edu}
5895020Sgblack@eecs.umich.edu
5905020Sgblack@eecs.umich.edu// Actions
5915020Sgblack@eecs.umich.edu''')
5925020Sgblack@eecs.umich.edu
5935238Sgblack@eecs.umich.edu        for action in self.actions.itervalues():
5945238Sgblack@eecs.umich.edu            if "c_code" not in action:
5955238Sgblack@eecs.umich.edu                continue
5965238Sgblack@eecs.umich.edu
5975238Sgblack@eecs.umich.edu            code('''
5985238Sgblack@eecs.umich.edu/** \\brief ${{action.desc}} */
5995238Sgblack@eecs.umich.eduvoid $c_ident::${{action.ident}}(const Address& addr)
6005238Sgblack@eecs.umich.edu{
6015238Sgblack@eecs.umich.edu    DEBUG_MSG(GENERATED_COMP, HighPrio, "executing");
6025238Sgblack@eecs.umich.edu    ${{action["c_code"]}}
6035238Sgblack@eecs.umich.edu}
6045238Sgblack@eecs.umich.edu
6055238Sgblack@eecs.umich.edu''')
6065238Sgblack@eecs.umich.edu        code.write(path, "%s.cc" % c_ident)
6075238Sgblack@eecs.umich.edu
6085238Sgblack@eecs.umich.edu    def printCWakeup(self, path):
6095238Sgblack@eecs.umich.edu        '''Output the wakeup loop for the events'''
6105238Sgblack@eecs.umich.edu
6115238Sgblack@eecs.umich.edu        code = code_formatter()
6125238Sgblack@eecs.umich.edu        ident = self.ident
6135238Sgblack@eecs.umich.edu
6145238Sgblack@eecs.umich.edu        code('''
6155238Sgblack@eecs.umich.edu// Auto generated C++ code started by $__file__:$__line__
6165238Sgblack@eecs.umich.edu// ${ident}: ${{self.short}}
6175238Sgblack@eecs.umich.edu
6185238Sgblack@eecs.umich.edu#include "mem/ruby/common/Global.hh"
6195238Sgblack@eecs.umich.edu#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
6205238Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Controller.hh"
6215238Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_State.hh"
6225238Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Event.hh"
6235238Sgblack@eecs.umich.edu#include "mem/protocol/Types.hh"
6245238Sgblack@eecs.umich.edu#include "mem/ruby/system/System.hh"
6255238Sgblack@eecs.umich.edu
6265238Sgblack@eecs.umich.eduvoid ${ident}_Controller::wakeup()
6275238Sgblack@eecs.umich.edu{
6285238Sgblack@eecs.umich.edu
6295238Sgblack@eecs.umich.edu    int counter = 0;
6305238Sgblack@eecs.umich.edu    while (true) {
6315238Sgblack@eecs.umich.edu        // Some cases will put us into an infinite loop without this limit
6325238Sgblack@eecs.umich.edu        assert(counter <= m_transitions_per_cycle);
6335238Sgblack@eecs.umich.edu        if (counter == m_transitions_per_cycle) {
6345238Sgblack@eecs.umich.edu            g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we\'re fully utilized
6355238Sgblack@eecs.umich.edu            g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again
6365238Sgblack@eecs.umich.edu            break;
6375238Sgblack@eecs.umich.edu        }
6385238Sgblack@eecs.umich.edu''')
6395238Sgblack@eecs.umich.edu
6405238Sgblack@eecs.umich.edu        code.indent()
6415238Sgblack@eecs.umich.edu        code.indent()
6425238Sgblack@eecs.umich.edu
6435238Sgblack@eecs.umich.edu        # InPorts
6445238Sgblack@eecs.umich.edu        #
6455020Sgblack@eecs.umich.edu        for port in self.in_ports:
6465020Sgblack@eecs.umich.edu            code.indent()
6475020Sgblack@eecs.umich.edu            code('// ${ident}InPort $port')
6485020Sgblack@eecs.umich.edu            code('${{port["c_code_in_port"]}}')
6495020Sgblack@eecs.umich.edu            code.dedent()
6505020Sgblack@eecs.umich.edu
6515020Sgblack@eecs.umich.edu            code('')
6525020Sgblack@eecs.umich.edu
6535020Sgblack@eecs.umich.edu        code.dedent()
6545020Sgblack@eecs.umich.edu        code.dedent()
6555020Sgblack@eecs.umich.edu        code('''
6565020Sgblack@eecs.umich.edu        break;  // If we got this far, we have nothing left todo
6575020Sgblack@eecs.umich.edu    }
6585238Sgblack@eecs.umich.edu}
6595238Sgblack@eecs.umich.edu''')
6605238Sgblack@eecs.umich.edu
6615238Sgblack@eecs.umich.edu        code.write(path, "%s_Wakeup.cc" % self.ident)
6625238Sgblack@eecs.umich.edu
6635238Sgblack@eecs.umich.edu    def printCSwitch(self, path):
6645238Sgblack@eecs.umich.edu        '''Output switch statement for transition table'''
6655238Sgblack@eecs.umich.edu
6665238Sgblack@eecs.umich.edu        code = code_formatter()
6675238Sgblack@eecs.umich.edu        ident = self.ident
6685238Sgblack@eecs.umich.edu
6695238Sgblack@eecs.umich.edu        code('''
6705238Sgblack@eecs.umich.edu// Auto generated C++ code started by $__file__:$__line__
6715238Sgblack@eecs.umich.edu// ${ident}: ${{self.short}}
6725238Sgblack@eecs.umich.edu
6735238Sgblack@eecs.umich.edu#include "mem/ruby/common/Global.hh"
6745238Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Controller.hh"
6755238Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_State.hh"
6765238Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Event.hh"
6775238Sgblack@eecs.umich.edu#include "mem/protocol/Types.hh"
6785238Sgblack@eecs.umich.edu#include "mem/ruby/system/System.hh"
6795238Sgblack@eecs.umich.edu
6805238Sgblack@eecs.umich.edu#define HASH_FUN(state, event)  ((int(state)*${ident}_Event_NUM)+int(event))
6815238Sgblack@eecs.umich.edu
6825238Sgblack@eecs.umich.edu#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str())
6835238Sgblack@eecs.umich.edu#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str(""))
6845238Sgblack@eecs.umich.edu
6855238Sgblack@eecs.umich.eduTransitionResult ${ident}_Controller::doTransition(${ident}_Event event, ${ident}_State state, const Address& addr
6865238Sgblack@eecs.umich.edu)
6875238Sgblack@eecs.umich.edu{
6885238Sgblack@eecs.umich.edu    ${ident}_State next_state = state;
6895238Sgblack@eecs.umich.edu
6905238Sgblack@eecs.umich.edu    DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
6915238Sgblack@eecs.umich.edu    DEBUG_MSG(GENERATED_COMP, MedPrio, *this);
6925238Sgblack@eecs.umich.edu    DEBUG_EXPR(GENERATED_COMP, MedPrio, g_eventQueue_ptr->getTime());
6935238Sgblack@eecs.umich.edu    DEBUG_EXPR(GENERATED_COMP, MedPrio,state);
6945238Sgblack@eecs.umich.edu    DEBUG_EXPR(GENERATED_COMP, MedPrio,event);
6955238Sgblack@eecs.umich.edu    DEBUG_EXPR(GENERATED_COMP, MedPrio,addr);
6965238Sgblack@eecs.umich.edu
6975238Sgblack@eecs.umich.edu    TransitionResult result = doTransitionWorker(event, state, next_state, addr);
6985238Sgblack@eecs.umich.edu
6995238Sgblack@eecs.umich.edu    if (result == TransitionResult_Valid) {
7005238Sgblack@eecs.umich.edu        DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state);
7015238Sgblack@eecs.umich.edu        DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
7025238Sgblack@eecs.umich.edu        s_profiler.countTransition(state, event);
7035238Sgblack@eecs.umich.edu        if (Debug::getProtocolTrace()) {
7045238Sgblack@eecs.umich.edu            g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
7055238Sgblack@eecs.umich.edu                    ${ident}_State_to_string(state),
7065238Sgblack@eecs.umich.edu                    ${ident}_Event_to_string(event),
7075238Sgblack@eecs.umich.edu                    ${ident}_State_to_string(next_state), GET_TRANSITION_COMMENT());
7085238Sgblack@eecs.umich.edu        }
7095238Sgblack@eecs.umich.edu    CLEAR_TRANSITION_COMMENT();
7105020Sgblack@eecs.umich.edu    ${ident}_setState(addr, next_state);
7115020Sgblack@eecs.umich.edu
7125020Sgblack@eecs.umich.edu    } else if (result == TransitionResult_ResourceStall) {
7135020Sgblack@eecs.umich.edu        if (Debug::getProtocolTrace()) {
7145020Sgblack@eecs.umich.edu            g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
7155020Sgblack@eecs.umich.edu                   ${ident}_State_to_string(state),
7165020Sgblack@eecs.umich.edu                   ${ident}_Event_to_string(event),
7175020Sgblack@eecs.umich.edu                   ${ident}_State_to_string(next_state),
7185020Sgblack@eecs.umich.edu                   "Resource Stall");
7195020Sgblack@eecs.umich.edu        }
7205020Sgblack@eecs.umich.edu    } else if (result == TransitionResult_ProtocolStall) {
7214276Sgblack@eecs.umich.edu        DEBUG_MSG(GENERATED_COMP, HighPrio, "stalling");
7225020Sgblack@eecs.umich.edu        DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
7235020Sgblack@eecs.umich.edu        if (Debug::getProtocolTrace()) {
7245020Sgblack@eecs.umich.edu            g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
7255020Sgblack@eecs.umich.edu                   ${ident}_State_to_string(state),
7265020Sgblack@eecs.umich.edu                   ${ident}_Event_to_string(event),
7275020Sgblack@eecs.umich.edu                   ${ident}_State_to_string(next_state),
7285020Sgblack@eecs.umich.edu                   "Protocol Stall");
7295020Sgblack@eecs.umich.edu        }
7305020Sgblack@eecs.umich.edu    }
7315020Sgblack@eecs.umich.edu
7325020Sgblack@eecs.umich.edu    return result;
7335020Sgblack@eecs.umich.edu}
7345020Sgblack@eecs.umich.edu
7355020Sgblack@eecs.umich.eduTransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr
7365020Sgblack@eecs.umich.edu)
7375020Sgblack@eecs.umich.edu{
7385020Sgblack@eecs.umich.edu    switch(HASH_FUN(state, event)) {
7395020Sgblack@eecs.umich.edu''')
7405020Sgblack@eecs.umich.edu
7415020Sgblack@eecs.umich.edu        # This map will allow suppress generating duplicate code
7425020Sgblack@eecs.umich.edu        cases = orderdict()
7435020Sgblack@eecs.umich.edu
7445020Sgblack@eecs.umich.edu        for trans in self.transitions:
7455020Sgblack@eecs.umich.edu            case_string = "%s_State_%s, %s_Event_%s" % \
7465020Sgblack@eecs.umich.edu                (self.ident, trans.state.ident, self.ident, trans.event.ident)
7475020Sgblack@eecs.umich.edu
7485020Sgblack@eecs.umich.edu            case = code_formatter()
7495020Sgblack@eecs.umich.edu            # Only set next_state if it changes
7505020Sgblack@eecs.umich.edu            if trans.state != trans.nextState:
7515020Sgblack@eecs.umich.edu                ns_ident = trans.nextState.ident
7524276Sgblack@eecs.umich.edu                case('next_state = ${ident}_State_${ns_ident};')
7534727Sgblack@eecs.umich.edu
7544727Sgblack@eecs.umich.edu            actions = trans.actions
7554727Sgblack@eecs.umich.edu
7564727Sgblack@eecs.umich.edu            # Check for resources
7574727Sgblack@eecs.umich.edu            case_sorter = []
7584727Sgblack@eecs.umich.edu            res = trans.resources
7594727Sgblack@eecs.umich.edu            for key,val in res.iteritems():
7604727Sgblack@eecs.umich.edu                if key.type.ident != "DNUCAStopTable":
7614727Sgblack@eecs.umich.edu                    val = '''
7624727Sgblack@eecs.umich.eduif (!%s.areNSlotsAvailable(%s)) {
7634727Sgblack@eecs.umich.edu    return TransitionResult_ResourceStall;
7644727Sgblack@eecs.umich.edu}
7654727Sgblack@eecs.umich.edu''' % (key.code, val)
7664727Sgblack@eecs.umich.edu                case_sorter.append(val)
7674727Sgblack@eecs.umich.edu
7684727Sgblack@eecs.umich.edu
7694727Sgblack@eecs.umich.edu            # Emit the code sequences in a sorted order.  This makes the
7704727Sgblack@eecs.umich.edu            # output deterministic (without this the output order can vary
7714727Sgblack@eecs.umich.edu            # since Map's keys() on a vector of pointers is not deterministic
7724727Sgblack@eecs.umich.edu            for c in sorted(case_sorter):
7734727Sgblack@eecs.umich.edu                case("$c")
7744760Sgblack@eecs.umich.edu
7754760Sgblack@eecs.umich.edu            # Figure out if we stall
7764760Sgblack@eecs.umich.edu            stall = False
7774760Sgblack@eecs.umich.edu            for action in actions:
7784760Sgblack@eecs.umich.edu                if action.ident == "z_stall":
7794760Sgblack@eecs.umich.edu                    stall = True
7804760Sgblack@eecs.umich.edu                    break
7814760Sgblack@eecs.umich.edu
7824760Sgblack@eecs.umich.edu            if stall:
7834760Sgblack@eecs.umich.edu                case('return TransitionResult_ProtocolStall;')
7844760Sgblack@eecs.umich.edu            else:
7854760Sgblack@eecs.umich.edu                for action in actions:
7864760Sgblack@eecs.umich.edu                    case('${{action.ident}}(addr);')
7874760Sgblack@eecs.umich.edu                case('return TransitionResult_Valid;')
7884760Sgblack@eecs.umich.edu
7894760Sgblack@eecs.umich.edu            case = str(case)
7904760Sgblack@eecs.umich.edu
7914760Sgblack@eecs.umich.edu            # Look to see if this transition code is unique.
7924760Sgblack@eecs.umich.edu            if case not in cases:
7934760Sgblack@eecs.umich.edu                cases[case] = []
7944276Sgblack@eecs.umich.edu
7954276Sgblack@eecs.umich.edu            cases[case].append(case_string)
7964712Sgblack@eecs.umich.edu
7974712Sgblack@eecs.umich.edu        # Walk through all of the unique code blocks and spit out the
7985659Sgblack@eecs.umich.edu        # corresponding case statement elements
7995659Sgblack@eecs.umich.edu        for case,transitions in cases.iteritems():
8005659Sgblack@eecs.umich.edu            # Iterative over all the multiple transitions that share
8015659Sgblack@eecs.umich.edu            # the same code
8025659Sgblack@eecs.umich.edu            for trans in transitions:
8035659Sgblack@eecs.umich.edu                code('  case HASH_FUN($trans):')
8045659Sgblack@eecs.umich.edu            code('  {')
8055659Sgblack@eecs.umich.edu            code('    $case')
8065240Sgblack@eecs.umich.edu            code('  }')
8074712Sgblack@eecs.umich.edu
8084712Sgblack@eecs.umich.edu        code('''
8094712Sgblack@eecs.umich.edu      default:
8104712Sgblack@eecs.umich.edu        WARN_EXPR(m_version);
8114276Sgblack@eecs.umich.edu        WARN_EXPR(g_eventQueue_ptr->getTime());
8124276Sgblack@eecs.umich.edu        WARN_EXPR(addr);
8134712Sgblack@eecs.umich.edu        WARN_EXPR(event);
8144712Sgblack@eecs.umich.edu        WARN_EXPR(state);
8154712Sgblack@eecs.umich.edu        ERROR_MSG(\"Invalid transition\");
8165240Sgblack@eecs.umich.edu    }
8174712Sgblack@eecs.umich.edu    return TransitionResult_Valid;
8184712Sgblack@eecs.umich.edu}
8195238Sgblack@eecs.umich.edu''')
8205238Sgblack@eecs.umich.edu        code.write(path, "%s_Transitions.cc" % self.ident)
8215238Sgblack@eecs.umich.edu
8225238Sgblack@eecs.umich.edu    def printProfilerHH(self, path):
8235238Sgblack@eecs.umich.edu        code = code_formatter()
8245238Sgblack@eecs.umich.edu        ident = self.ident
8255238Sgblack@eecs.umich.edu
8265238Sgblack@eecs.umich.edu        code('''
8275238Sgblack@eecs.umich.edu// Auto generated C++ code started by $__file__:$__line__
8285238Sgblack@eecs.umich.edu// ${ident}: ${{self.short}}
8295238Sgblack@eecs.umich.edu
8305238Sgblack@eecs.umich.edu#ifndef ${ident}_PROFILER_H
8315238Sgblack@eecs.umich.edu#define ${ident}_PROFILER_H
8325238Sgblack@eecs.umich.edu
8335238Sgblack@eecs.umich.edu#include "mem/ruby/common/Global.hh"
8344724Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_State.hh"
8354276Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Event.hh"
8364276Sgblack@eecs.umich.edu
8374864Sgblack@eecs.umich.educlass ${ident}_Profiler {
8384864Sgblack@eecs.umich.edu  public:
8394712Sgblack@eecs.umich.edu    ${ident}_Profiler();
8405240Sgblack@eecs.umich.edu    void setVersion(int version);
8414712Sgblack@eecs.umich.edu    void countTransition(${ident}_State state, ${ident}_Event event);
8424712Sgblack@eecs.umich.edu    void possibleTransition(${ident}_State state, ${ident}_Event event);
8434746Sgblack@eecs.umich.edu    void dumpStats(ostream& out) const;
8444746Sgblack@eecs.umich.edu    void clearStats();
8454746Sgblack@eecs.umich.edu
8464746Sgblack@eecs.umich.edu  private:
8474746Sgblack@eecs.umich.edu    int m_counters[${ident}_State_NUM][${ident}_Event_NUM];
8484276Sgblack@eecs.umich.edu    int m_event_counters[${ident}_Event_NUM];
8494276Sgblack@eecs.umich.edu    bool m_possible[${ident}_State_NUM][${ident}_Event_NUM];
8504712Sgblack@eecs.umich.edu    int m_version;
8515240Sgblack@eecs.umich.edu};
8525240Sgblack@eecs.umich.edu
8535240Sgblack@eecs.umich.edu#endif // ${ident}_PROFILER_H
8545240Sgblack@eecs.umich.edu''')
8555240Sgblack@eecs.umich.edu        code.write(path, "%s_Profiler.hh" % self.ident)
8565240Sgblack@eecs.umich.edu
8575240Sgblack@eecs.umich.edu    def printProfilerCC(self, path):
8585240Sgblack@eecs.umich.edu        code = code_formatter()
8595240Sgblack@eecs.umich.edu        ident = self.ident
8605240Sgblack@eecs.umich.edu
8615240Sgblack@eecs.umich.edu        code('''
8625240Sgblack@eecs.umich.edu// Auto generated C++ code started by $__file__:$__line__
8635238Sgblack@eecs.umich.edu// ${ident}: ${{self.short}}
8645332Sgblack@eecs.umich.edu
8655332Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Profiler.hh"
8664746Sgblack@eecs.umich.edu
8674746Sgblack@eecs.umich.edu${ident}_Profiler::${ident}_Profiler()
8684746Sgblack@eecs.umich.edu{
8694746Sgblack@eecs.umich.edu    for (int state = 0; state < ${ident}_State_NUM; state++) {
8704746Sgblack@eecs.umich.edu        for (int event = 0; event < ${ident}_Event_NUM; event++) {
8714276Sgblack@eecs.umich.edu            m_possible[state][event] = false;
8724276Sgblack@eecs.umich.edu            m_counters[state][event] = 0;
8735815Sgblack@eecs.umich.edu        }
8745815Sgblack@eecs.umich.edu    }
8755238Sgblack@eecs.umich.edu    for (int event = 0; event < ${ident}_Event_NUM; event++) {
8765238Sgblack@eecs.umich.edu        m_event_counters[event] = 0;
8775238Sgblack@eecs.umich.edu    }
8785238Sgblack@eecs.umich.edu}
8795238Sgblack@eecs.umich.eduvoid ${ident}_Profiler::setVersion(int version)
8805238Sgblack@eecs.umich.edu{
8815238Sgblack@eecs.umich.edu    m_version = version;
8825238Sgblack@eecs.umich.edu}
8835238Sgblack@eecs.umich.eduvoid ${ident}_Profiler::clearStats()
8845238Sgblack@eecs.umich.edu{
8855238Sgblack@eecs.umich.edu    for (int state = 0; state < ${ident}_State_NUM; state++) {
8865238Sgblack@eecs.umich.edu        for (int event = 0; event < ${ident}_Event_NUM; event++) {
8875238Sgblack@eecs.umich.edu            m_counters[state][event] = 0;
8885020Sgblack@eecs.umich.edu        }
8895020Sgblack@eecs.umich.edu    }
8905020Sgblack@eecs.umich.edu
8915020Sgblack@eecs.umich.edu    for (int event = 0; event < ${ident}_Event_NUM; event++) {
8925020Sgblack@eecs.umich.edu        m_event_counters[event] = 0;
8935020Sgblack@eecs.umich.edu    }
8945020Sgblack@eecs.umich.edu}
8955020Sgblack@eecs.umich.eduvoid ${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event)
8965020Sgblack@eecs.umich.edu{
8975020Sgblack@eecs.umich.edu    assert(m_possible[state][event]);
8985020Sgblack@eecs.umich.edu    m_counters[state][event]++;
8995020Sgblack@eecs.umich.edu    m_event_counters[event]++;
9005020Sgblack@eecs.umich.edu}
9015020Sgblack@eecs.umich.eduvoid ${ident}_Profiler::possibleTransition(${ident}_State state, ${ident}_Event event)
9025020Sgblack@eecs.umich.edu{
9035020Sgblack@eecs.umich.edu    m_possible[state][event] = true;
9045020Sgblack@eecs.umich.edu}
9055020Sgblack@eecs.umich.eduvoid ${ident}_Profiler::dumpStats(ostream& out) const
9065020Sgblack@eecs.umich.edu{
9075020Sgblack@eecs.umich.edu    out << " --- ${ident} " << m_version << " ---" << endl;
9085020Sgblack@eecs.umich.edu    out << " - Event Counts -" << endl;
9095020Sgblack@eecs.umich.edu    for (int event = 0; event < ${ident}_Event_NUM; event++) {
9105020Sgblack@eecs.umich.edu        int count = m_event_counters[event];
9115020Sgblack@eecs.umich.edu        out << (${ident}_Event) event << "  " << count << endl;
9125020Sgblack@eecs.umich.edu    }
9135020Sgblack@eecs.umich.edu    out << endl;
9145020Sgblack@eecs.umich.edu    out << " - Transitions -" << endl;
9155020Sgblack@eecs.umich.edu    for (int state = 0; state < ${ident}_State_NUM; state++) {
9165020Sgblack@eecs.umich.edu        for (int event = 0; event < ${ident}_Event_NUM; event++) {
9174276Sgblack@eecs.umich.edu            if (m_possible[state][event]) {
9185814Sgblack@eecs.umich.edu                int count = m_counters[state][event];
9195814Sgblack@eecs.umich.edu                out << (${ident}_State) state << "  " << (${ident}_Event) event << "  " << count;
9205814Sgblack@eecs.umich.edu                if (count == 0) {
9215814Sgblack@eecs.umich.edu                    out << " <-- ";
9225814Sgblack@eecs.umich.edu                }
9235020Sgblack@eecs.umich.edu                out << endl;
9245020Sgblack@eecs.umich.edu            }
9255020Sgblack@eecs.umich.edu        }
9265020Sgblack@eecs.umich.edu        out << endl;
9275020Sgblack@eecs.umich.edu    }
9285020Sgblack@eecs.umich.edu}
9295020Sgblack@eecs.umich.edu''')
9305020Sgblack@eecs.umich.edu        code.write(path, "%s_Profiler.cc" % self.ident)
9315020Sgblack@eecs.umich.edu
9325020Sgblack@eecs.umich.edu    # **************************
9335020Sgblack@eecs.umich.edu    # ******* HTML Files *******
9345020Sgblack@eecs.umich.edu    # **************************
9355020Sgblack@eecs.umich.edu    def frameRef(self, click_href, click_target, over_href, over_target_num,
9365020Sgblack@eecs.umich.edu                 text):
9375020Sgblack@eecs.umich.edu        code = code_formatter(fix_newlines=False)
9385020Sgblack@eecs.umich.edu        code("""<A href=\"$click_href\" target=\"$click_target\" onMouseOver=\"if (parent.frames[$over_target_num].location != parent.location + '$over_href') { parent.frames[$over_target_num].location='$over_href' }\" >${{html.formatShorthand(text)}}</A>""")
9395020Sgblack@eecs.umich.edu        return str(code)
9405020Sgblack@eecs.umich.edu
9415020Sgblack@eecs.umich.edu    def writeHTMLFiles(self, path):
9425020Sgblack@eecs.umich.edu        # Create table with no row hilighted
9435020Sgblack@eecs.umich.edu        self.printHTMLTransitions(path, None)
9445020Sgblack@eecs.umich.edu
9455020Sgblack@eecs.umich.edu        # Generate transition tables
9465020Sgblack@eecs.umich.edu        for state in self.states.itervalues():
9475020Sgblack@eecs.umich.edu            self.printHTMLTransitions(path, state)
9485020Sgblack@eecs.umich.edu
9495020Sgblack@eecs.umich.edu        # Generate action descriptions
9505020Sgblack@eecs.umich.edu        for action in self.actions.itervalues():
9515020Sgblack@eecs.umich.edu            name = "%s_action_%s.html" % (self.ident, action.ident)
9525020Sgblack@eecs.umich.edu            code = html.createSymbol(action, "Action")
9535020Sgblack@eecs.umich.edu            code.write(path, name)
9545020Sgblack@eecs.umich.edu
9555020Sgblack@eecs.umich.edu        # Generate state descriptions
9565020Sgblack@eecs.umich.edu        for state in self.states.itervalues():
9575020Sgblack@eecs.umich.edu            name = "%s_State_%s.html" % (self.ident, state.ident)
9585020Sgblack@eecs.umich.edu            code = html.createSymbol(state, "State")
9595020Sgblack@eecs.umich.edu            code.write(path, name)
9604276Sgblack@eecs.umich.edu
9615020Sgblack@eecs.umich.edu        # Generate event descriptions
9625020Sgblack@eecs.umich.edu        for event in self.events.itervalues():
9635020Sgblack@eecs.umich.edu            name = "%s_Event_%s.html" % (self.ident, event.ident)
9645020Sgblack@eecs.umich.edu            code = html.createSymbol(event, "Event")
9655020Sgblack@eecs.umich.edu            code.write(path, name)
9665020Sgblack@eecs.umich.edu
9675020Sgblack@eecs.umich.edu    def printHTMLTransitions(self, path, active_state):
9685020Sgblack@eecs.umich.edu        code = code_formatter()
9695020Sgblack@eecs.umich.edu
9705020Sgblack@eecs.umich.edu        code('''
9715020Sgblack@eecs.umich.edu<HTML><BODY link="blue" vlink="blue">
9725020Sgblack@eecs.umich.edu
9735020Sgblack@eecs.umich.edu<H1 align="center">${{html.formatShorthand(self.short)}}:
9745020Sgblack@eecs.umich.edu''')
9755020Sgblack@eecs.umich.edu        code.indent()
9765020Sgblack@eecs.umich.edu        for i,machine in enumerate(self.symtab.getAllType(StateMachine)):
9775020Sgblack@eecs.umich.edu            mid = machine.ident
9785020Sgblack@eecs.umich.edu            if i != 0:
9795020Sgblack@eecs.umich.edu                extra = " - "
9805020Sgblack@eecs.umich.edu            else:
9815020Sgblack@eecs.umich.edu                extra = ""
9825020Sgblack@eecs.umich.edu            if machine == self:
9835020Sgblack@eecs.umich.edu                code('$extra$mid')
9845020Sgblack@eecs.umich.edu            else:
9854276Sgblack@eecs.umich.edu                code('$extra<A target="Table" href="${mid}_table.html">$mid</A>')
9865022Sgblack@eecs.umich.edu        code.dedent()
9875022Sgblack@eecs.umich.edu
9885022Sgblack@eecs.umich.edu        code("""
9895022Sgblack@eecs.umich.edu</H1>
9905022Sgblack@eecs.umich.edu
9915022Sgblack@eecs.umich.edu<TABLE border=1>
9925022Sgblack@eecs.umich.edu<TR>
9935022Sgblack@eecs.umich.edu  <TH> </TH>
9945022Sgblack@eecs.umich.edu""")
9955022Sgblack@eecs.umich.edu
9965022Sgblack@eecs.umich.edu        for event in self.events.itervalues():
9975022Sgblack@eecs.umich.edu            href = "%s_Event_%s.html" % (self.ident, event.ident)
9985022Sgblack@eecs.umich.edu            ref = self.frameRef(href, "Status", href, "1", event.short)
9995022Sgblack@eecs.umich.edu            code('<TH bgcolor=white>$ref</TH>')
10005022Sgblack@eecs.umich.edu
10015022Sgblack@eecs.umich.edu        code('</TR>')
10025022Sgblack@eecs.umich.edu        # -- Body of table
10035022Sgblack@eecs.umich.edu        for state in self.states.itervalues():
10045022Sgblack@eecs.umich.edu            # -- Each row
10055022Sgblack@eecs.umich.edu            if state == active_state:
10065022Sgblack@eecs.umich.edu                color = "yellow"
10075022Sgblack@eecs.umich.edu            else:
10085022Sgblack@eecs.umich.edu                color = "white"
10095022Sgblack@eecs.umich.edu
10105022Sgblack@eecs.umich.edu            click = "%s_table_%s.html" % (self.ident, state.ident)
10115022Sgblack@eecs.umich.edu            over = "%s_State_%s.html" % (self.ident, state.ident)
10125022Sgblack@eecs.umich.edu            text = html.formatShorthand(state.short)
10135022Sgblack@eecs.umich.edu            ref = self.frameRef(click, "Table", over, "1", state.short)
10145022Sgblack@eecs.umich.edu            code('''
10155022Sgblack@eecs.umich.edu<TR>
10165022Sgblack@eecs.umich.edu  <TH bgcolor=$color>$ref</TH>
10175022Sgblack@eecs.umich.edu''')
10185022Sgblack@eecs.umich.edu
10195022Sgblack@eecs.umich.edu            # -- One column for each event
10204276Sgblack@eecs.umich.edu            for event in self.events.itervalues():
10215020Sgblack@eecs.umich.edu                trans = self.table.get((state,event), None)
10225020Sgblack@eecs.umich.edu                if trans is None:
10235020Sgblack@eecs.umich.edu                    # This is the no transition case
10245020Sgblack@eecs.umich.edu                    if state == active_state:
10255020Sgblack@eecs.umich.edu                        color = "#C0C000"
10265020Sgblack@eecs.umich.edu                    else:
10275020Sgblack@eecs.umich.edu                        color = "lightgrey"
10285020Sgblack@eecs.umich.edu
10295020Sgblack@eecs.umich.edu                    code('<TD bgcolor=$color>&nbsp;</TD>')
10305020Sgblack@eecs.umich.edu                    continue
10315020Sgblack@eecs.umich.edu
10325020Sgblack@eecs.umich.edu                next = trans.nextState
10335020Sgblack@eecs.umich.edu                stall_action = False
10345020Sgblack@eecs.umich.edu
10355020Sgblack@eecs.umich.edu                # -- Get the actions
10365020Sgblack@eecs.umich.edu                for action in trans.actions:
10375020Sgblack@eecs.umich.edu                    if action.ident == "z_stall" or \
10385020Sgblack@eecs.umich.edu                       action.ident == "zz_recycleMandatoryQueue":
10395020Sgblack@eecs.umich.edu                        stall_action = True
10405020Sgblack@eecs.umich.edu
10415020Sgblack@eecs.umich.edu                # -- Print out "actions/next-state"
10425020Sgblack@eecs.umich.edu                if stall_action:
10435020Sgblack@eecs.umich.edu                    if state == active_state:
10445020Sgblack@eecs.umich.edu                        color = "#C0C000"
10454276Sgblack@eecs.umich.edu                    else:
10464276Sgblack@eecs.umich.edu                        color = "lightgrey"
10475022Sgblack@eecs.umich.edu
10485022Sgblack@eecs.umich.edu                elif active_state and next.ident == active_state.ident:
10495022Sgblack@eecs.umich.edu                    color = "aqua"
10505022Sgblack@eecs.umich.edu                elif state == active_state:
10515022Sgblack@eecs.umich.edu                    color = "yellow"
10525022Sgblack@eecs.umich.edu                else:
10535022Sgblack@eecs.umich.edu                    color = "white"
10545022Sgblack@eecs.umich.edu
10555022Sgblack@eecs.umich.edu                fix = code.nofix()
10565022Sgblack@eecs.umich.edu                code('<TD bgcolor=$color>')
10575022Sgblack@eecs.umich.edu                for action in trans.actions:
10585022Sgblack@eecs.umich.edu                    href = "%s_action_%s.html" % (self.ident, action.ident)
10595022Sgblack@eecs.umich.edu                    ref = self.frameRef(href, "Status", href, "1",
10605022Sgblack@eecs.umich.edu                                        action.short)
10615022Sgblack@eecs.umich.edu                    code('  $ref\n')
10625022Sgblack@eecs.umich.edu                if next != state:
10635022Sgblack@eecs.umich.edu                    if trans.actions:
10645022Sgblack@eecs.umich.edu                        code('/')
10655022Sgblack@eecs.umich.edu                    click = "%s_table_%s.html" % (self.ident, next.ident)
10665022Sgblack@eecs.umich.edu                    over = "%s_State_%s.html" % (self.ident, next.ident)
10675022Sgblack@eecs.umich.edu                    ref = self.frameRef(click, "Table", over, "1", next.short)
10685022Sgblack@eecs.umich.edu                    code("$ref")
10695022Sgblack@eecs.umich.edu                code("</TD>\n")
10705022Sgblack@eecs.umich.edu                code.fix(fix)
10715022Sgblack@eecs.umich.edu
10725022Sgblack@eecs.umich.edu            # -- Each row
10735022Sgblack@eecs.umich.edu            if state == active_state:
10745022Sgblack@eecs.umich.edu                color = "yellow"
10754276Sgblack@eecs.umich.edu            else:
10765020Sgblack@eecs.umich.edu                color = "white"
10775020Sgblack@eecs.umich.edu
10785020Sgblack@eecs.umich.edu            click = "%s_table_%s.html" % (self.ident, state.ident)
10795020Sgblack@eecs.umich.edu            over = "%s_State_%s.html" % (self.ident, state.ident)
10805020Sgblack@eecs.umich.edu            ref = self.frameRef(click, "Table", over, "1", state.short)
10815020Sgblack@eecs.umich.edu            code('''
10825020Sgblack@eecs.umich.edu  <TH bgcolor=$color>$ref</TH>
10835020Sgblack@eecs.umich.edu</TR>
10845020Sgblack@eecs.umich.edu''')
10855020Sgblack@eecs.umich.edu        code('''
10865020Sgblack@eecs.umich.edu<TR>
10875020Sgblack@eecs.umich.edu  <TH> </TH>
10885020Sgblack@eecs.umich.edu''')
10895020Sgblack@eecs.umich.edu
10905020Sgblack@eecs.umich.edu        for event in self.events.itervalues():
10915020Sgblack@eecs.umich.edu            href = "%s_Event_%s.html" % (self.ident, event.ident)
10925020Sgblack@eecs.umich.edu            ref = self.frameRef(href, "Status", href, "1", event.short)
10935020Sgblack@eecs.umich.edu            code('<TH bgcolor=white>$ref</TH>')
10945020Sgblack@eecs.umich.edu        code('''
10955020Sgblack@eecs.umich.edu</TR>
10965020Sgblack@eecs.umich.edu</TABLE>
10975020Sgblack@eecs.umich.edu</BODY></HTML>
10985020Sgblack@eecs.umich.edu''')
10995020Sgblack@eecs.umich.edu
11004276Sgblack@eecs.umich.edu
11014276Sgblack@eecs.umich.edu        if active_state:
11024276Sgblack@eecs.umich.edu            name = "%s_table_%s.html" % (self.ident, active_state.ident)
11034276Sgblack@eecs.umich.edu        else:
11044276Sgblack@eecs.umich.edu            name = "%s_table.html" % self.ident
11054276Sgblack@eecs.umich.edu        code.write(path, name)
11064276Sgblack@eecs.umich.edu
1107__all__ = [ "StateMachine" ]
1108