StateMachine.py revision 6881
12292SN/A# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
27597Sminkyu.jeong@arm.com# Copyright (c) 2009 The Hewlett-Packard Development Company
37597Sminkyu.jeong@arm.com# All rights reserved.
47597Sminkyu.jeong@arm.com#
57597Sminkyu.jeong@arm.com# Redistribution and use in source and binary forms, with or without
67597Sminkyu.jeong@arm.com# modification, are permitted provided that the following conditions are
77597Sminkyu.jeong@arm.com# met: redistributions of source code must retain the above copyright
87597Sminkyu.jeong@arm.com# notice, this list of conditions and the following disclaimer;
97597Sminkyu.jeong@arm.com# redistributions in binary form must reproduce the above copyright
107597Sminkyu.jeong@arm.com# notice, this list of conditions and the following disclaimer in the
117597Sminkyu.jeong@arm.com# documentation and/or other materials provided with the distribution;
127597Sminkyu.jeong@arm.com# neither the name of the copyright holders nor the names of its
137597Sminkyu.jeong@arm.com# contributors may be used to endorse or promote products derived from
142292SN/A# this software without specific prior written permission.
152292SN/A#
162292SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172292SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182292SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192292SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202292SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212292SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222292SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232292SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242292SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252292SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262292SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272292SN/A
282292SN/Afrom m5.util import code_formatter, orderdict
292292SN/A
302292SN/Afrom slicc.symbols.Symbol import Symbol
312292SN/Afrom slicc.symbols.Var import Var
322292SN/Aimport slicc.generate.html as html
332292SN/A
342292SN/Aclass StateMachine(Symbol):
352292SN/A    def __init__(self, symtab, ident, location, pairs, config_parameters):
362292SN/A        super(StateMachine, self).__init__(symtab, ident, location, pairs)
372292SN/A        self.table = None
382292SN/A        self.config_parameters = config_parameters
392689Sktlim@umich.edu        for param in config_parameters:
402689Sktlim@umich.edu            var = Var(symtab, param.name, location, param.type_ast.type,
412689Sktlim@umich.edu                      "m_%s" % param.name, {}, self)
422292SN/A            self.symtab.registerSym(param.name, var)
432292SN/A
443326Sktlim@umich.edu        self.states = orderdict()
458229Snate@binkert.org        self.events = orderdict()
466658Snate@binkert.org        self.actions = orderdict()
472733Sktlim@umich.edu        self.transitions = []
482907Sktlim@umich.edu        self.in_ports = []
492292SN/A        self.functions = []
508232Snate@binkert.org        self.objects = []
518232Snate@binkert.org
528232Snate@binkert.org        self.message_buffer_names = []
532722Sktlim@umich.edu
542669Sktlim@umich.edu    def __repr__(self):
552292SN/A        return "[StateMachine: %s]" % self.ident
562790Sktlim@umich.edu
572790Sktlim@umich.edu    def addState(self, state):
582790Sktlim@umich.edu        assert self.table is None
592790Sktlim@umich.edu        self.states[state.ident] = state
602669Sktlim@umich.edu
612678Sktlim@umich.edu    def addEvent(self, event):
622678Sktlim@umich.edu        assert self.table is None
638581Ssteve.reinhardt@amd.com        self.events[event.ident] = event
648581Ssteve.reinhardt@amd.com
652292SN/A    def addAction(self, action):
662292SN/A        assert self.table is None
672292SN/A
682669Sktlim@umich.edu        # Check for duplicate action
692292SN/A        for other in self.actions.itervalues():
702678Sktlim@umich.edu            if action.ident == other.ident:
712292SN/A                action.warning("Duplicate action definition: %s" % action.ident)
722678Sktlim@umich.edu                action.error("Duplicate action definition: %s" % action.ident)
732678Sktlim@umich.edu            if action.short == other.short:
742678Sktlim@umich.edu                other.warning("Duplicate action shorthand: %s" % other.ident)
754319Sktlim@umich.edu                other.warning("    shorthand = %s" % other.short)
764319Sktlim@umich.edu                action.warning("Duplicate action shorthand: %s" % action.ident)
774319Sktlim@umich.edu                action.error("    shorthand = %s" % action.short)
784319Sktlim@umich.edu
794319Sktlim@umich.edu        self.actions[action.ident] = action
802678Sktlim@umich.edu
812678Sktlim@umich.edu    def addTransition(self, trans):
822292SN/A        assert self.table is None
832678Sktlim@umich.edu        self.transitions.append(trans)
842678Sktlim@umich.edu
855336Shines@cs.fsu.edu    def addInPort(self, var):
862678Sktlim@umich.edu        self.in_ports.append(var)
874873Sstever@eecs.umich.edu
882678Sktlim@umich.edu    def addFunc(self, func):
892292SN/A        # register func in the symbol table
902678Sktlim@umich.edu        self.symtab.registerSym(str(func), func)
912678Sktlim@umich.edu        self.functions.append(func)
922678Sktlim@umich.edu
932678Sktlim@umich.edu    def addObject(self, obj):
942678Sktlim@umich.edu        self.objects.append(obj)
952678Sktlim@umich.edu
967852SMatt.Horsnell@arm.com    # Needs to be called before accessing the table
977852SMatt.Horsnell@arm.com    def buildTable(self):
982344SN/A        assert self.table is None
992678Sktlim@umich.edu
1002678Sktlim@umich.edu        table = {}
1014986Ssaidi@eecs.umich.edu
1024986Ssaidi@eecs.umich.edu        for trans in self.transitions:
1036974Stjones1@inf.ed.ac.uk            # Track which actions we touch so we know if we use them
1046974Stjones1@inf.ed.ac.uk            # all -- really this should be done for all symbols as
1056974Stjones1@inf.ed.ac.uk            # part of the symbol table, then only trigger it for
1066974Stjones1@inf.ed.ac.uk            # Actions, States, Events, etc.
1076974Stjones1@inf.ed.ac.uk
1086974Stjones1@inf.ed.ac.uk            for action in trans.actions:
1096974Stjones1@inf.ed.ac.uk                action.used = True
1102678Sktlim@umich.edu
1112820Sktlim@umich.edu            index = (trans.state, trans.event)
1122678Sktlim@umich.edu            if index in table:
1132678Sktlim@umich.edu                table[index].warning("Duplicate transition: %s" % table[index])
1146974Stjones1@inf.ed.ac.uk                trans.error("Duplicate transition: %s" % trans)
1156974Stjones1@inf.ed.ac.uk            table[index] = trans
1166974Stjones1@inf.ed.ac.uk
1176974Stjones1@inf.ed.ac.uk        # Look at all actions to make sure we used them all
1186974Stjones1@inf.ed.ac.uk        for action in self.actions.itervalues():
1196974Stjones1@inf.ed.ac.uk            if not action.used:
1202678Sktlim@umich.edu                error_msg = "Unused action: %s" % action.ident
1212678Sktlim@umich.edu                if "desc" in action:
1222678Sktlim@umich.edu                    error_msg += ", "  + action.desc
1232678Sktlim@umich.edu                action.warning(error_msg)
1242678Sktlim@umich.edu        self.table = table
1252344SN/A
1262307SN/A    def writeCodeFiles(self, path):
1276974Stjones1@inf.ed.ac.uk        self.printControllerPython(path)
1286974Stjones1@inf.ed.ac.uk        self.printControllerHH(path)
1296974Stjones1@inf.ed.ac.uk        self.printControllerCC(path)
1306974Stjones1@inf.ed.ac.uk        self.printCSwitch(path)
1312678Sktlim@umich.edu        self.printCWakeup(path)
1324032Sktlim@umich.edu        self.printProfilerCC(path)
1332678Sktlim@umich.edu        self.printProfilerHH(path)
1342292SN/A
1352292SN/A        for func in self.functions:
1362292SN/A            func.writeCodeFiles(path)
1372292SN/A
1388545Ssaidi@eecs.umich.edu    def printControllerPython(self, path):
1392678Sktlim@umich.edu        code = code_formatter()
1406974Stjones1@inf.ed.ac.uk        ident = self.ident
1412292SN/A        py_ident = "%s_Controller" % ident
1422292SN/A        c_ident = "%s_Controller" % self.ident
1432292SN/A        code('''
1442292SN/Afrom m5.params import *
1452292SN/Afrom m5.SimObject import SimObject
1465529Snate@binkert.orgfrom Controller import RubyController
1475529Snate@binkert.org
1485529Snate@binkert.orgclass $py_ident(RubyController):
1492292SN/A    type = '$py_ident'
1504329Sktlim@umich.edu''')
1514329Sktlim@umich.edu        code.indent()
1524329Sktlim@umich.edu        for param in self.config_parameters:
1534329Sktlim@umich.edu            dflt_str = ''
1542292SN/A            if param.default is not None:
1552307SN/A                dflt_str = str(param.default) + ', '
1562307SN/A            code('${{param.name}} = Param.Int(${dflt_str}"")')
1578545Ssaidi@eecs.umich.edu        code.dedent()
1588545Ssaidi@eecs.umich.edu        code.write(path, '%s.py' % py_ident)
1592907Sktlim@umich.edu
1602907Sktlim@umich.edu
1612292SN/A    def printControllerHH(self, path):
1622292SN/A        '''Output the method declarations for the class declaration'''
1632329SN/A        code = code_formatter()
1642329SN/A        ident = self.ident
1652329SN/A        c_ident = "%s_Controller" % self.ident
1662292SN/A
1672292SN/A        self.message_buffer_names = []
1682292SN/A
1692292SN/A        code('''
1708199SAli.Saidi@ARM.com/** \\file $ident.hh
1718199SAli.Saidi@ARM.com *
1728199SAli.Saidi@ARM.com * Auto generated C++ code started by $__file__:$__line__
1732292SN/A * Created by slicc definition of Module "${{self.short}}"
1742292SN/A */
1752292SN/A
1762292SN/A#ifndef ${ident}_CONTROLLER_H
1772292SN/A#define ${ident}_CONTROLLER_H
1782292SN/A
1792292SN/A#include "params/$c_ident.hh"
1803492Sktlim@umich.edu
1812329SN/A#include "mem/ruby/common/Global.hh"
1822292SN/A#include "mem/ruby/common/Consumer.hh"
1832292SN/A#include "mem/ruby/slicc_interface/AbstractController.hh"
1842292SN/A#include "mem/protocol/TransitionResult.hh"
1852292SN/A#include "mem/protocol/Types.hh"
1862292SN/A#include "mem/protocol/${ident}_Profiler.hh"
1872292SN/A''')
1882292SN/A
1892292SN/A        seen_types = set()
1902292SN/A        for var in self.objects:
1912292SN/A            if var.type.ident not in seen_types and not var.type.isPrimitive:
1922292SN/A                code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
1938247Snate@binkert.org            seen_types.add(var.type.ident)
1942292SN/A
1952292SN/A        # for adding information to the protocol debug trace
1962292SN/A        code('''
1972292SN/Aextern stringstream ${ident}_transitionComment;
1982292SN/A
1992727Sktlim@umich.educlass $c_ident : public AbstractController {
2002727Sktlim@umich.edu#ifdef CHECK_COHERENCE
2012727Sktlim@umich.edu#endif /* CHECK_COHERENCE */
2022727Sktlim@umich.edupublic:
2032727Sktlim@umich.edu    typedef ${c_ident}Params Params;
2042727Sktlim@umich.edu    $c_ident(const Params *p);
2052727Sktlim@umich.edu    static int getNumControllers();
2062727Sktlim@umich.edu    void init();
2072727Sktlim@umich.edu    MessageBuffer* getMandatoryQueue() const;
2082727Sktlim@umich.edu    const int & getVersion() const;
2092727Sktlim@umich.edu    const string toString() const;
2102727Sktlim@umich.edu    const string getName() const;
2112727Sktlim@umich.edu    const MachineType getMachineType() const;
2122727Sktlim@umich.edu    void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; }
2132727Sktlim@umich.edu    void print(ostream& out) const;
2142727Sktlim@umich.edu    void printConfig(ostream& out) const;
2152727Sktlim@umich.edu    void wakeup();
2162727Sktlim@umich.edu    void printStats(ostream& out) const { s_profiler.dumpStats(out); }
2172361SN/A    void clearStats() { s_profiler.clearStats(); }
2182361SN/A    void blockOnQueue(Address addr, MessageBuffer* port);
2192361SN/A    void unblock(Address addr);
2202361SN/Aprivate:
2212727Sktlim@umich.edu''')
2222727Sktlim@umich.edu
2232727Sktlim@umich.edu        code.indent()
2242727Sktlim@umich.edu        # added by SS
2252727Sktlim@umich.edu        for param in self.config_parameters:
2262727Sktlim@umich.edu            code('int m_${{param.ident}};')
2272727Sktlim@umich.edu
2282727Sktlim@umich.edu        code('''
2292727Sktlim@umich.eduint m_number_of_TBEs;
2302727Sktlim@umich.edu
2312727Sktlim@umich.eduTransitionResult doTransition(${ident}_Event event, ${ident}_State state, const Address& addr); // in ${ident}_Transitions.cc
2322727Sktlim@umich.eduTransitionResult doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr); // in ${ident}_Transitions.cc
2332727Sktlim@umich.edustring m_name;
2342727Sktlim@umich.eduint m_transitions_per_cycle;
2352727Sktlim@umich.eduint m_buffer_size;
2362727Sktlim@umich.eduint m_recycle_latency;
2372727Sktlim@umich.edumap< string, string > m_cfg;
2382727Sktlim@umich.eduNodeID m_version;
2392727Sktlim@umich.eduNetwork* m_net_ptr;
2402727Sktlim@umich.eduMachineID m_machineID;
2412727Sktlim@umich.edubool m_is_blocking;
2422727Sktlim@umich.edumap< Address, MessageBuffer* > m_block_map;
2432727Sktlim@umich.edu${ident}_Profiler s_profiler;
2444329Sktlim@umich.edustatic int m_num_controllers;
2454329Sktlim@umich.edu// Internal functions
2464329Sktlim@umich.edu''')
2474329Sktlim@umich.edu
2484329Sktlim@umich.edu        for func in self.functions:
2494329Sktlim@umich.edu            proto = func.prototype
2504329Sktlim@umich.edu            if proto:
2514329Sktlim@umich.edu                code('$proto')
2524329Sktlim@umich.edu
2534329Sktlim@umich.edu        code('''
2544329Sktlim@umich.edu
2554329Sktlim@umich.edu// Actions
2564329Sktlim@umich.edu''')
2572292SN/A        for action in self.actions.itervalues():
2582292SN/A            code('/** \\brief ${{action.desc}} */')
2592292SN/A            code('void ${{action.ident}}(const Address& addr);')
2602292SN/A
2612292SN/A        # the controller internal variables
2622292SN/A        code('''
2632292SN/A
2642292SN/A// Object
2652292SN/A''')
2662292SN/A        for var in self.objects:
2672292SN/A            th = var.get("template_hack", "")
2682292SN/A            code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;')
2692292SN/A
2702292SN/A            if var.type.ident == "MessageBuffer":
2712307SN/A                self.message_buffer_names.append("m_%s_ptr" % var.c_ident)
2722307SN/A
2732307SN/A        code.dedent()
2742367SN/A        code('};')
2752367SN/A        code('#endif // ${ident}_CONTROLLER_H')
2762307SN/A        code.write(path, '%s.hh' % c_ident)
2772367SN/A
2782307SN/A    def printControllerCC(self, path):
2792329SN/A        '''Output the actions for performing the actions'''
2802307SN/A
2812307SN/A        code = code_formatter()
2822307SN/A        ident = self.ident
2832307SN/A        c_ident = "%s_Controller" % self.ident
2842307SN/A
2852307SN/A        code('''
2862307SN/A/** \\file $ident.cc
2872307SN/A *
2882307SN/A * Auto generated C++ code started by $__file__:$__line__
2892307SN/A * Created by slicc definition of Module "${{self.short}}"
2902307SN/A */
2912307SN/A
2922307SN/A#include "mem/ruby/common/Global.hh"
2932307SN/A#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
2942307SN/A#include "mem/protocol/${ident}_Controller.hh"
2952329SN/A#include "mem/protocol/${ident}_State.hh"
2962307SN/A#include "mem/protocol/${ident}_Event.hh"
2972307SN/A#include "mem/protocol/Types.hh"
2982307SN/A#include "mem/ruby/system/System.hh"
2992307SN/A''')
3002307SN/A
3012307SN/A        # include object classes
3028545Ssaidi@eecs.umich.edu        seen_types = set()
3038545Ssaidi@eecs.umich.edu        for var in self.objects:
3048545Ssaidi@eecs.umich.edu            if var.type.ident not in seen_types and not var.type.isPrimitive:
3052307SN/A                code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
3062307SN/A            seen_types.add(var.type.ident)
3072307SN/A
3082307SN/A        code('''
3092292SN/A$c_ident *
3102292SN/A${c_ident}Params::create()
3112329SN/A{
3122329SN/A    return new $c_ident(this);
3132292SN/A}
3142329SN/A
3152329SN/A
3162292SN/Aint $c_ident::m_num_controllers = 0;
3172292SN/A
3182292SN/Astringstream ${ident}_transitionComment;
3192292SN/A#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str)
3202292SN/A/** \\brief constructor */
3212329SN/A$c_ident::$c_ident(const Params *p)
3222292SN/A    : AbstractController(p)
3232292SN/A{
3242292SN/A    m_version = p->version;
3252292SN/A    m_transitions_per_cycle = p->transitions_per_cycle;
3262292SN/A    m_buffer_size = p->buffer_size;
3272292SN/A    m_recycle_latency = p->recycle_latency;
3282292SN/A    m_number_of_TBEs = p->number_of_TBEs;
3292292SN/A''')
3302329SN/A        code.indent()
3312329SN/A        for param in self.config_parameters:
3322329SN/A            code('m_${{param.name}} = p->${{param.name}};')
3332292SN/A
3342292SN/A        code('m_num_controllers++;')
3352292SN/A        for var in self.objects:
3362292SN/A            if var.ident.find("mandatoryQueue") >= 0:
3372292SN/A                code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();')
3382329SN/A
3392292SN/A        code.dedent()
3402292SN/A        code('''
3412292SN/A}
3422292SN/A
3432292SN/Avoid $c_ident::init()
3442292SN/A{
3452292SN/A    m_machineID.type = MachineType_${ident};
3462292SN/A    m_machineID.num = m_version;
3472292SN/A
3482292SN/A    // Objects
3492292SN/A    s_profiler.setVersion(m_version);
3502292SN/A''')
3512292SN/A
3522292SN/A        code.indent()
3532292SN/A        for var in self.objects:
3542292SN/A            vtype = var.type
3552292SN/A            vid = "m_%s_ptr" % var.c_ident
3562292SN/A            if "network" not in var:
3572292SN/A                # Not a network port object
3582292SN/A                if "primitive" in vtype:
3592292SN/A                    code('$vid = new ${{vtype.c_ident}};')
3602292SN/A                    if "default" in var:
3612292SN/A                        code('(*$vid) = ${{var["default"]}};')
3622292SN/A                else:
3632329SN/A                    # Normal Object
3642329SN/A                    # added by SS
3652292SN/A                    if "factory" in var:
3667720Sgblack@eecs.umich.edu                        code('$vid = ${{var["factory"]}};')
3677720Sgblack@eecs.umich.edu                    elif var.ident.find("mandatoryQueue") < 0:
3682292SN/A                        th = var.get("template_hack", "")
3692292SN/A                        expr = "%s  = new %s%s" % (vid, vtype.c_ident, th)
3702292SN/A
3712292SN/A                        args = ""
3722292SN/A                        if "non_obj" not in vtype and not vtype.isEnumeration:
3732292SN/A                            if expr.find("TBETable") >= 0:
3742292SN/A                                args = "m_number_of_TBEs"
3752292SN/A                            else:
3762292SN/A                                args = var.get("constructor_hack", "")
3772292SN/A                            args = "(%s)" % args
3782292SN/A
3792292SN/A                        code('$expr$args;')
3802292SN/A                    else:
3812292SN/A                        code(';')
3822292SN/A
3832292SN/A                    code('assert($vid != NULL);')
3842292SN/A
3852292SN/A                    if "default" in var:
3862292SN/A                        code('(*$vid) = ${{var["default"]}}; // Object default')
3872292SN/A                    elif "default" in vtype:
3882292SN/A                        code('(*$vid) = ${{vtype["default"]}}; // Type ${{vtype.ident}} default')
3892292SN/A
3902292SN/A                    # Set ordering
3912292SN/A                    if "ordered" in var and "trigger_queue" not in var:
3927720Sgblack@eecs.umich.edu                        # A buffer
3937720Sgblack@eecs.umich.edu                        code('$vid->setOrdering(${{var["ordered"]}});')
3942292SN/A
3952292SN/A                    # Set randomization
3962292SN/A                    if "random" in var:
3972292SN/A                        # A buffer
3982292SN/A                        code('$vid->setRandomization(${{var["random"]}});')
3992292SN/A
4002292SN/A                    # Set Priority
4012292SN/A                    if vtype.isBuffer and \
4022292SN/A                           "rank" in var and "trigger_queue" not in var:
4032292SN/A                        code('$vid->setPriority(${{var["rank"]}});')
4042292SN/A            else:
4052292SN/A                # Network port object
4062292SN/A                network = var["network"]
4072292SN/A                ordered =  var["ordered"]
4082292SN/A                vnet = var["virtual_network"]
4092292SN/A
4102292SN/A                assert var.machine is not None
4112292SN/A                code('''
4122292SN/A$vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string_to_MachineType("${{var.machine.ident}}")), $ordered, $vnet);
4132292SN/A''')
4142292SN/A
4152292SN/A                code('assert($vid != NULL);')
4162292SN/A
4172292SN/A                # Set ordering
4182292SN/A                if "ordered" in var:
4192292SN/A                    # A buffer
4202292SN/A                    code('$vid->setOrdering(${{var["ordered"]}});')
4212292SN/A
4222292SN/A                # Set randomization
4232292SN/A                if "random" in var:
4242292SN/A                    # A buffer
4252292SN/A                    code('$vid->setRandomization(${{var["random"]}})')
4262292SN/A
4272292SN/A                # Set Priority
4282292SN/A                if "rank" in var:
4292292SN/A                    code('$vid->setPriority(${{var["rank"]}})')
4302292SN/A
4312292SN/A                # Set buffer size
4322292SN/A                if vtype.isBuffer:
4332292SN/A                    code('''
4342292SN/Aif (m_buffer_size > 0) {
4352292SN/A    $vid->setSize(m_buffer_size);
4362292SN/A}
4372292SN/A''')
4382292SN/A
4392292SN/A                # set description (may be overriden later by port def)
4402292SN/A                code('$vid->setDescription("[Version " + int_to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");')
4412292SN/A
4422292SN/A        # Set the queue consumers
4432292SN/A        code.insert_newline()
4442292SN/A        for port in self.in_ports:
4452292SN/A            code('${{port.code}}.setConsumer(this);')
4462292SN/A
4472292SN/A        # Set the queue descriptions
4482292SN/A        code.insert_newline()
4492292SN/A        for port in self.in_ports:
4502292SN/A            code('${{port.code}}.setDescription("[Version " + int_to_string(m_version) + ", $ident, $port]");')
4518545Ssaidi@eecs.umich.edu
4528545Ssaidi@eecs.umich.edu        # Initialize the transition profiling
4538545Ssaidi@eecs.umich.edu        code.insert_newline()
4548545Ssaidi@eecs.umich.edu        for trans in self.transitions:
4558545Ssaidi@eecs.umich.edu            # Figure out if we stall
4568545Ssaidi@eecs.umich.edu            stall = False
4578545Ssaidi@eecs.umich.edu            for action in trans.actions:
4588545Ssaidi@eecs.umich.edu                if action.ident == "z_stall":
4598545Ssaidi@eecs.umich.edu                    stall = True
4608545Ssaidi@eecs.umich.edu
4618545Ssaidi@eecs.umich.edu            # Only possible if it is not a 'z' case
4628545Ssaidi@eecs.umich.edu            if not stall:
4638545Ssaidi@eecs.umich.edu                state = "%s_State_%s" % (self.ident, trans.state.ident)
4648545Ssaidi@eecs.umich.edu                event = "%s_Event_%s" % (self.ident, trans.event.ident)
4658545Ssaidi@eecs.umich.edu                code('s_profiler.possibleTransition($state, $event);')
4668545Ssaidi@eecs.umich.edu
4678545Ssaidi@eecs.umich.edu        # added by SS to initialize recycle_latency of message buffers
4688545Ssaidi@eecs.umich.edu        for buf in self.message_buffer_names:
4698545Ssaidi@eecs.umich.edu            code("$buf->setRecycleLatency(m_recycle_latency);")
4708545Ssaidi@eecs.umich.edu
4718545Ssaidi@eecs.umich.edu        code.dedent()
4728545Ssaidi@eecs.umich.edu        code('}')
4738545Ssaidi@eecs.umich.edu
4748545Ssaidi@eecs.umich.edu        has_mandatory_q = False
4758545Ssaidi@eecs.umich.edu        for port in self.in_ports:
4768545Ssaidi@eecs.umich.edu            if port.code.find("mandatoryQueue_ptr") >= 0:
4778545Ssaidi@eecs.umich.edu                has_mandatory_q = True
4788545Ssaidi@eecs.umich.edu
4798545Ssaidi@eecs.umich.edu        if has_mandatory_q:
4808545Ssaidi@eecs.umich.edu            mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident
4818545Ssaidi@eecs.umich.edu        else:
4828545Ssaidi@eecs.umich.edu            mq_ident = "NULL"
4838545Ssaidi@eecs.umich.edu
4848545Ssaidi@eecs.umich.edu        code('''
4858545Ssaidi@eecs.umich.eduint $c_ident::getNumControllers() {
4868545Ssaidi@eecs.umich.edu    return m_num_controllers;
4878545Ssaidi@eecs.umich.edu}
4888545Ssaidi@eecs.umich.edu
4898545Ssaidi@eecs.umich.eduMessageBuffer* $c_ident::getMandatoryQueue() const {
4908545Ssaidi@eecs.umich.edu    return $mq_ident;
4918545Ssaidi@eecs.umich.edu}
4928545Ssaidi@eecs.umich.edu
4938545Ssaidi@eecs.umich.educonst int & $c_ident::getVersion() const{
4948545Ssaidi@eecs.umich.edu    return m_version;
4958545Ssaidi@eecs.umich.edu}
4968545Ssaidi@eecs.umich.edu
4978545Ssaidi@eecs.umich.educonst string $c_ident::toString() const{
4988545Ssaidi@eecs.umich.edu    return "$c_ident";
4998545Ssaidi@eecs.umich.edu}
5008545Ssaidi@eecs.umich.edu
5018545Ssaidi@eecs.umich.educonst string $c_ident::getName() const{
5028545Ssaidi@eecs.umich.edu    return m_name;
5038545Ssaidi@eecs.umich.edu}
5048545Ssaidi@eecs.umich.educonst MachineType $c_ident::getMachineType() const{
5052292SN/A    return MachineType_${ident};
5068199SAli.Saidi@ARM.com}
5078199SAli.Saidi@ARM.com
5088199SAli.Saidi@ARM.comvoid $c_ident::blockOnQueue(Address addr, MessageBuffer* port) {
5098199SAli.Saidi@ARM.com    m_is_blocking = true;
5108199SAli.Saidi@ARM.com    m_block_map[addr] = port;
5118199SAli.Saidi@ARM.com}
5128199SAli.Saidi@ARM.comvoid $c_ident::unblock(Address addr) {
5138199SAli.Saidi@ARM.com    m_block_map.erase(addr);
5148199SAli.Saidi@ARM.com    if (m_block_map.size() == 0) {
5158199SAli.Saidi@ARM.com       m_is_blocking = false;
5168199SAli.Saidi@ARM.com    }
5178199SAli.Saidi@ARM.com}
5188199SAli.Saidi@ARM.com
5198199SAli.Saidi@ARM.comvoid $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; }
5208199SAli.Saidi@ARM.com
5218199SAli.Saidi@ARM.comvoid $c_ident::printConfig(ostream& out) const {
5228199SAli.Saidi@ARM.com    out << "$c_ident config: " << m_name << endl;
5238199SAli.Saidi@ARM.com    out << "  version: " << m_version << endl;
5248199SAli.Saidi@ARM.com    for (map<string, string>::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) {
5258199SAli.Saidi@ARM.com        out << "  " << (*it).first << ": " << (*it).second << endl;
5268199SAli.Saidi@ARM.com    }
5278272SAli.Saidi@ARM.com}
5288545Ssaidi@eecs.umich.edu
5298545Ssaidi@eecs.umich.edu// Actions
5308545Ssaidi@eecs.umich.edu''')
5318545Ssaidi@eecs.umich.edu
5328545Ssaidi@eecs.umich.edu        for action in self.actions.itervalues():
5338545Ssaidi@eecs.umich.edu            if "c_code" not in action:
5348545Ssaidi@eecs.umich.edu                continue
5358545Ssaidi@eecs.umich.edu
5368545Ssaidi@eecs.umich.edu            code('''
5378545Ssaidi@eecs.umich.edu/** \\brief ${{action.desc}} */
5388545Ssaidi@eecs.umich.eduvoid $c_ident::${{action.ident}}(const Address& addr)
5398199SAli.Saidi@ARM.com{
5408545Ssaidi@eecs.umich.edu    DEBUG_MSG(GENERATED_COMP, HighPrio, "executing");
5418199SAli.Saidi@ARM.com    ${{action["c_code"]}}
5428545Ssaidi@eecs.umich.edu}
5438545Ssaidi@eecs.umich.edu
5448545Ssaidi@eecs.umich.edu''')
5458199SAli.Saidi@ARM.com        code.write(path, "%s.cc" % c_ident)
5468545Ssaidi@eecs.umich.edu
5478545Ssaidi@eecs.umich.edu    def printCWakeup(self, path):
5488545Ssaidi@eecs.umich.edu        '''Output the wakeup loop for the events'''
5498545Ssaidi@eecs.umich.edu
5508545Ssaidi@eecs.umich.edu        code = code_formatter()
5518545Ssaidi@eecs.umich.edu        ident = self.ident
5528545Ssaidi@eecs.umich.edu
5538545Ssaidi@eecs.umich.edu        code('''
5548545Ssaidi@eecs.umich.edu// Auto generated C++ code started by $__file__:$__line__
5558545Ssaidi@eecs.umich.edu// ${ident}: ${{self.short}}
5568545Ssaidi@eecs.umich.edu
5578545Ssaidi@eecs.umich.edu#include "mem/ruby/common/Global.hh"
5588545Ssaidi@eecs.umich.edu#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
5598545Ssaidi@eecs.umich.edu#include "mem/protocol/${ident}_Controller.hh"
5608545Ssaidi@eecs.umich.edu#include "mem/protocol/${ident}_State.hh"
5618545Ssaidi@eecs.umich.edu#include "mem/protocol/${ident}_Event.hh"
5628545Ssaidi@eecs.umich.edu#include "mem/protocol/Types.hh"
5638545Ssaidi@eecs.umich.edu#include "mem/ruby/system/System.hh"
5648545Ssaidi@eecs.umich.edu
5658545Ssaidi@eecs.umich.eduvoid ${ident}_Controller::wakeup()
5668545Ssaidi@eecs.umich.edu{
5678545Ssaidi@eecs.umich.edu
5688199SAli.Saidi@ARM.com    int counter = 0;
5698199SAli.Saidi@ARM.com    while (true) {
5708199SAli.Saidi@ARM.com        // Some cases will put us into an infinite loop without this limit
5718199SAli.Saidi@ARM.com        assert(counter <= m_transitions_per_cycle);
5728199SAli.Saidi@ARM.com        if (counter == m_transitions_per_cycle) {
5738199SAli.Saidi@ARM.com            g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we\'re fully utilized
5748199SAli.Saidi@ARM.com            g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again
5758199SAli.Saidi@ARM.com            break;
5768199SAli.Saidi@ARM.com        }
5778199SAli.Saidi@ARM.com''')
5788199SAli.Saidi@ARM.com
5798199SAli.Saidi@ARM.com        code.indent()
5802292SN/A        code.indent()
5812292SN/A
5824032Sktlim@umich.edu        # InPorts
5832292SN/A        #
5842292SN/A        for port in self.in_ports:
5852292SN/A            code.indent()
5867720Sgblack@eecs.umich.edu            code('// ${ident}InPort $port')
5877944SGiacomo.Gabrielli@arm.com            code('${{port["c_code_in_port"]}}')
5882292SN/A            code.dedent()
5894032Sktlim@umich.edu
5904032Sktlim@umich.edu            code('')
5912669Sktlim@umich.edu
5922292SN/A        code.dedent()
5937944SGiacomo.Gabrielli@arm.com        code.dedent()
5947944SGiacomo.Gabrielli@arm.com        code('''
5957944SGiacomo.Gabrielli@arm.com        break;  // If we got this far, we have nothing left todo
5967944SGiacomo.Gabrielli@arm.com    }
5977597Sminkyu.jeong@arm.com}
5987597Sminkyu.jeong@arm.com''')
5997597Sminkyu.jeong@arm.com
6002329SN/A        code.write(path, "%s_Wakeup.cc" % self.ident)
6012329SN/A
6022367SN/A    def printCSwitch(self, path):
6032367SN/A        '''Output switch statement for transition table'''
6047848SAli.Saidi@ARM.com
6057848SAli.Saidi@ARM.com        code = code_formatter()
6067600Sminkyu.jeong@arm.com        ident = self.ident
6077600Sminkyu.jeong@arm.com
6087600Sminkyu.jeong@arm.com        code('''
6094032Sktlim@umich.edu// Auto generated C++ code started by $__file__:$__line__
6103731Sktlim@umich.edu// ${ident}: ${{self.short}}
6112367SN/A
6122367SN/A#include "mem/ruby/common/Global.hh"
6132292SN/A#include "mem/protocol/${ident}_Controller.hh"
6142292SN/A#include "mem/protocol/${ident}_State.hh"
6154032Sktlim@umich.edu#include "mem/protocol/${ident}_Event.hh"
6164032Sktlim@umich.edu#include "mem/protocol/Types.hh"
6174032Sktlim@umich.edu#include "mem/ruby/system/System.hh"
6184032Sktlim@umich.edu
6194032Sktlim@umich.edu#define HASH_FUN(state, event)  ((int(state)*${ident}_Event_NUM)+int(event))
6208199SAli.Saidi@ARM.com
6218199SAli.Saidi@ARM.com#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str())
6222292SN/A#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str(""))
6232292SN/A
6242292SN/ATransitionResult ${ident}_Controller::doTransition(${ident}_Event event, ${ident}_State state, const Address& addr
6252292SN/A)
6262292SN/A{
6272292SN/A    ${ident}_State next_state = state;
6282292SN/A
6292292SN/A    DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
6302292SN/A    DEBUG_MSG(GENERATED_COMP, MedPrio, *this);
6312292SN/A    DEBUG_EXPR(GENERATED_COMP, MedPrio, g_eventQueue_ptr->getTime());
6322292SN/A    DEBUG_EXPR(GENERATED_COMP, MedPrio,state);
6332292SN/A    DEBUG_EXPR(GENERATED_COMP, MedPrio,event);
6342292SN/A    DEBUG_EXPR(GENERATED_COMP, MedPrio,addr);
6352292SN/A
6362292SN/A    TransitionResult result = doTransitionWorker(event, state, next_state, addr);
6377720Sgblack@eecs.umich.edu
6387720Sgblack@eecs.umich.edu    if (result == TransitionResult_Valid) {
6392292SN/A        DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state);
6404032Sktlim@umich.edu        DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
6414032Sktlim@umich.edu        s_profiler.countTransition(state, event);
6422292SN/A        if (Debug::getProtocolTrace()) {
6432292SN/A            g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
6442292SN/A                    ${ident}_State_to_string(state),
6452292SN/A                    ${ident}_Event_to_string(event),
6462292SN/A                    ${ident}_State_to_string(next_state), GET_TRANSITION_COMMENT());
6472292SN/A        }
6487944SGiacomo.Gabrielli@arm.com    CLEAR_TRANSITION_COMMENT();
6497944SGiacomo.Gabrielli@arm.com    ${ident}_setState(addr, next_state);
6507944SGiacomo.Gabrielli@arm.com
6517944SGiacomo.Gabrielli@arm.com    } else if (result == TransitionResult_ResourceStall) {
6527848SAli.Saidi@ARM.com        if (Debug::getProtocolTrace()) {
6537848SAli.Saidi@ARM.com            g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
6547848SAli.Saidi@ARM.com                   ${ident}_State_to_string(state),
6552329SN/A                   ${ident}_Event_to_string(event),
6567782Sminkyu.jeong@arm.com                   ${ident}_State_to_string(next_state),
6577720Sgblack@eecs.umich.edu                   "Resource Stall");
6582292SN/A        }
6592292SN/A    } else if (result == TransitionResult_ProtocolStall) {
6607782Sminkyu.jeong@arm.com        DEBUG_MSG(GENERATED_COMP, HighPrio, "stalling");
6617782Sminkyu.jeong@arm.com        DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
6627782Sminkyu.jeong@arm.com        if (Debug::getProtocolTrace()) {
6637782Sminkyu.jeong@arm.com            g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
6642292SN/A                   ${ident}_State_to_string(state),
6652292SN/A                   ${ident}_Event_to_string(event),
6662292SN/A                   ${ident}_State_to_string(next_state),
6672292SN/A                   "Protocol Stall");
6682336SN/A        }
6692336SN/A    }
6702336SN/A
6712329SN/A    return result;
6722292SN/A}
6732329SN/A
6742292SN/ATransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr
6752292SN/A)
6768199SAli.Saidi@ARM.com{
6772292SN/A    switch(HASH_FUN(state, event)) {
6782292SN/A''')
6792292SN/A
6802292SN/A        # This map will allow suppress generating duplicate code
6812292SN/A        cases = orderdict()
6822292SN/A
6832292SN/A        for trans in self.transitions:
6842292SN/A            case_string = "%s_State_%s, %s_Event_%s" % \
6852292SN/A                (self.ident, trans.state.ident, self.ident, trans.event.ident)
6867720Sgblack@eecs.umich.edu
6877720Sgblack@eecs.umich.edu            case = code_formatter()
6882292SN/A            # Only set next_state if it changes
6892292SN/A            if trans.state != trans.nextState:
6902292SN/A                ns_ident = trans.nextState.ident
6912292SN/A                case('next_state = ${ident}_State_${ns_ident};')
6922292SN/A
6932292SN/A            actions = trans.actions
6942292SN/A
6952292SN/A            # Check for resources
6962292SN/A            case_sorter = []
6972292SN/A            res = trans.resources
6982292SN/A            for key,val in res.iteritems():
6992292SN/A                if key.type.ident != "DNUCAStopTable":
7002292SN/A                    val = '''
7012292SN/Aif (!%s.areNSlotsAvailable(%s)) {
7022292SN/A    return TransitionResult_ResourceStall;
7032292SN/A}
7042292SN/A''' % (key.code, val)
7052292SN/A                case_sorter.append(val)
7062292SN/A
7072292SN/A
7082292SN/A            # Emit the code sequences in a sorted order.  This makes the
7092292SN/A            # output deterministic (without this the output order can vary
7102292SN/A            # since Map's keys() on a vector of pointers is not deterministic
7112292SN/A            for c in sorted(case_sorter):
7122292SN/A                case("$c")
7132292SN/A
7142292SN/A            # Figure out if we stall
7152292SN/A            stall = False
7162292SN/A            for action in actions:
7172329SN/A                if action.ident == "z_stall":
7182329SN/A                    stall = True
7192292SN/A                    break
7202292SN/A
7212292SN/A            if stall:
7222292SN/A                case('return TransitionResult_ProtocolStall;')
7232292SN/A            else:
7247720Sgblack@eecs.umich.edu                for action in actions:
7257720Sgblack@eecs.umich.edu                    case('${{action.ident}}(addr);')
7262292SN/A                case('return TransitionResult_Valid;')
7272292SN/A
7282292SN/A            case = str(case)
7292292SN/A
7302292SN/A            # Look to see if this transition code is unique.
7312292SN/A            if case not in cases:
7322292SN/A                cases[case] = []
7332292SN/A
7342292SN/A            cases[case].append(case_string)
7352292SN/A
7362292SN/A        # Walk through all of the unique code blocks and spit out the
7372292SN/A        # corresponding case statement elements
7382292SN/A        for case,transitions in cases.iteritems():
7396974Stjones1@inf.ed.ac.uk            # Iterative over all the multiple transitions that share
7406974Stjones1@inf.ed.ac.uk            # the same code
7416974Stjones1@inf.ed.ac.uk            for trans in transitions:
7426974Stjones1@inf.ed.ac.uk                code('  case HASH_FUN($trans):')
7436974Stjones1@inf.ed.ac.uk            code('  {')
7446974Stjones1@inf.ed.ac.uk            code('    $case')
7456974Stjones1@inf.ed.ac.uk            code('  }')
7466974Stjones1@inf.ed.ac.uk
7476974Stjones1@inf.ed.ac.uk        code('''
7486974Stjones1@inf.ed.ac.uk      default:
7496974Stjones1@inf.ed.ac.uk        WARN_EXPR(m_version);
7506974Stjones1@inf.ed.ac.uk        WARN_EXPR(g_eventQueue_ptr->getTime());
7516974Stjones1@inf.ed.ac.uk        WARN_EXPR(addr);
7526974Stjones1@inf.ed.ac.uk        WARN_EXPR(event);
7536974Stjones1@inf.ed.ac.uk        WARN_EXPR(state);
7546974Stjones1@inf.ed.ac.uk        ERROR_MSG(\"Invalid transition\");
7552292SN/A    }
7562292SN/A    return TransitionResult_Valid;
7576974Stjones1@inf.ed.ac.uk}
7586974Stjones1@inf.ed.ac.uk''')
7596974Stjones1@inf.ed.ac.uk        code.write(path, "%s_Transitions.cc" % self.ident)
7606974Stjones1@inf.ed.ac.uk
7616974Stjones1@inf.ed.ac.uk    def printProfilerHH(self, path):
7626974Stjones1@inf.ed.ac.uk        code = code_formatter()
7632292SN/A        ident = self.ident
7642292SN/A
7652292SN/A        code('''
7662292SN/A// Auto generated C++ code started by $__file__:$__line__
7672292SN/A// ${ident}: ${{self.short}}
7682292SN/A
7692907Sktlim@umich.edu#ifndef ${ident}_PROFILER_H
7702678Sktlim@umich.edu#define ${ident}_PROFILER_H
7712678Sktlim@umich.edu
7722678Sktlim@umich.edu#include "mem/ruby/common/Global.hh"
7732678Sktlim@umich.edu#include "mem/protocol/${ident}_State.hh"
7742678Sktlim@umich.edu#include "mem/protocol/${ident}_Event.hh"
7752329SN/A
7762329SN/Aclass ${ident}_Profiler {
7772292SN/A  public:
7782292SN/A    ${ident}_Profiler();
7792292SN/A    void setVersion(int version);
7802292SN/A    void countTransition(${ident}_State state, ${ident}_Event event);
7812292SN/A    void possibleTransition(${ident}_State state, ${ident}_Event event);
7822292SN/A    void dumpStats(ostream& out) const;
7832292SN/A    void clearStats();
7842678Sktlim@umich.edu
7852292SN/A  private:
7862292SN/A    int m_counters[${ident}_State_NUM][${ident}_Event_NUM];
7872292SN/A    int m_event_counters[${ident}_Event_NUM];
7882292SN/A    bool m_possible[${ident}_State_NUM][${ident}_Event_NUM];
7892292SN/A    int m_version;
7902292SN/A};
7912292SN/A
7922292SN/A#endif // ${ident}_PROFILER_H
7932292SN/A''')
7942292SN/A        code.write(path, "%s_Profiler.hh" % self.ident)
7952292SN/A
7966974Stjones1@inf.ed.ac.uk    def printProfilerCC(self, path):
7976974Stjones1@inf.ed.ac.uk        code = code_formatter()
7986974Stjones1@inf.ed.ac.uk        ident = self.ident
7996974Stjones1@inf.ed.ac.uk
8006974Stjones1@inf.ed.ac.uk        code('''
8012669Sktlim@umich.edu// Auto generated C++ code started by $__file__:$__line__
8022669Sktlim@umich.edu// ${ident}: ${{self.short}}
8032669Sktlim@umich.edu
8048481Sgblack@eecs.umich.edu#include "mem/protocol/${ident}_Profiler.hh"
8058481Sgblack@eecs.umich.edu
8068481Sgblack@eecs.umich.edu${ident}_Profiler::${ident}_Profiler()
8072292SN/A{
8082292SN/A    for (int state = 0; state < ${ident}_State_NUM; state++) {
8092669Sktlim@umich.edu        for (int event = 0; event < ${ident}_Event_NUM; event++) {
8102669Sktlim@umich.edu            m_possible[state][event] = false;
8113772Sgblack@eecs.umich.edu            m_counters[state][event] = 0;
8124326Sgblack@eecs.umich.edu        }
8132669Sktlim@umich.edu    }
8144878Sstever@eecs.umich.edu    for (int event = 0; event < ${ident}_Event_NUM; event++) {
8154878Sstever@eecs.umich.edu        m_event_counters[event] = 0;
8166102Sgblack@eecs.umich.edu    }
8176974Stjones1@inf.ed.ac.uk}
8186974Stjones1@inf.ed.ac.ukvoid ${ident}_Profiler::setVersion(int version)
8192292SN/A{
8202678Sktlim@umich.edu    m_version = version;
8212678Sktlim@umich.edu}
8222678Sktlim@umich.eduvoid ${ident}_Profiler::clearStats()
8232678Sktlim@umich.edu{
8246974Stjones1@inf.ed.ac.uk    for (int state = 0; state < ${ident}_State_NUM; state++) {
8256974Stjones1@inf.ed.ac.uk        for (int event = 0; event < ${ident}_Event_NUM; event++) {
8266974Stjones1@inf.ed.ac.uk            m_counters[state][event] = 0;
8276974Stjones1@inf.ed.ac.uk        }
8286974Stjones1@inf.ed.ac.uk    }
8296974Stjones1@inf.ed.ac.uk
8306974Stjones1@inf.ed.ac.uk    for (int event = 0; event < ${ident}_Event_NUM; event++) {
8316974Stjones1@inf.ed.ac.uk        m_event_counters[event] = 0;
8326974Stjones1@inf.ed.ac.uk    }
8336974Stjones1@inf.ed.ac.uk}
8346974Stjones1@inf.ed.ac.ukvoid ${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event)
8356974Stjones1@inf.ed.ac.uk{
8366974Stjones1@inf.ed.ac.uk    assert(m_possible[state][event]);
8376974Stjones1@inf.ed.ac.uk    m_counters[state][event]++;
8386974Stjones1@inf.ed.ac.uk    m_event_counters[event]++;
8396974Stjones1@inf.ed.ac.uk}
8406974Stjones1@inf.ed.ac.ukvoid ${ident}_Profiler::possibleTransition(${ident}_State state, ${ident}_Event event)
8416974Stjones1@inf.ed.ac.uk{
8426974Stjones1@inf.ed.ac.uk    m_possible[state][event] = true;
8436974Stjones1@inf.ed.ac.uk}
8446974Stjones1@inf.ed.ac.ukvoid ${ident}_Profiler::dumpStats(ostream& out) const
8456974Stjones1@inf.ed.ac.uk{
8466974Stjones1@inf.ed.ac.uk    out << " --- ${ident} " << m_version << " ---" << endl;
8476974Stjones1@inf.ed.ac.uk    out << " - Event Counts -" << endl;
8486974Stjones1@inf.ed.ac.uk    for (int event = 0; event < ${ident}_Event_NUM; event++) {
8492678Sktlim@umich.edu        int count = m_event_counters[event];
8507720Sgblack@eecs.umich.edu        out << (${ident}_Event) event << "  " << count << endl;
8512292SN/A    }
8527720Sgblack@eecs.umich.edu    out << endl;
8533797Sgblack@eecs.umich.edu    out << " - Transitions -" << endl;
8543221Sktlim@umich.edu    for (int state = 0; state < ${ident}_State_NUM; state++) {
8552292SN/A        for (int event = 0; event < ${ident}_Event_NUM; event++) {
8562693Sktlim@umich.edu            if (m_possible[state][event]) {
8574350Sgblack@eecs.umich.edu                int count = m_counters[state][event];
8586974Stjones1@inf.ed.ac.uk                out << (${ident}_State) state << "  " << (${ident}_Event) event << "  " << count;
8593326Sktlim@umich.edu                if (count == 0) {
8603326Sktlim@umich.edu                    out << " <-- ";
8613326Sktlim@umich.edu                }
8623326Sktlim@umich.edu                out << endl;
8633326Sktlim@umich.edu            }
8643326Sktlim@umich.edu        }
8653326Sktlim@umich.edu        out << endl;
8663326Sktlim@umich.edu    }
8673326Sktlim@umich.edu}
8683326Sktlim@umich.edu''')
8693326Sktlim@umich.edu        code.write(path, "%s_Profiler.cc" % self.ident)
8703326Sktlim@umich.edu
8713326Sktlim@umich.edu    # **************************
8727823Ssteve.reinhardt@amd.com    # ******* HTML Files *******
8733326Sktlim@umich.edu    # **************************
8743326Sktlim@umich.edu    def frameRef(self, click_href, click_target, over_href, over_target_num,
8753326Sktlim@umich.edu                 text):
8762693Sktlim@umich.edu        code = code_formatter(fix_newlines=False)
8772693Sktlim@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>""")
8782693Sktlim@umich.edu        return str(code)
8792693Sktlim@umich.edu
8802693Sktlim@umich.edu    def writeHTMLFiles(self, path):
8812693Sktlim@umich.edu        # Create table with no row hilighted
8828481Sgblack@eecs.umich.edu        self.printHTMLTransitions(path, None)
8838481Sgblack@eecs.umich.edu
8848481Sgblack@eecs.umich.edu        # Generate transition tables
8858481Sgblack@eecs.umich.edu        for state in self.states.itervalues():
8868481Sgblack@eecs.umich.edu            self.printHTMLTransitions(path, state)
8878481Sgblack@eecs.umich.edu
8888481Sgblack@eecs.umich.edu        # Generate action descriptions
8898481Sgblack@eecs.umich.edu        for action in self.actions.itervalues():
8908481Sgblack@eecs.umich.edu            name = "%s_action_%s.html" % (self.ident, action.ident)
8918481Sgblack@eecs.umich.edu            code = html.createSymbol(action, "Action")
8928481Sgblack@eecs.umich.edu            code.write(path, name)
8938481Sgblack@eecs.umich.edu
8948481Sgblack@eecs.umich.edu        # Generate state descriptions
8958481Sgblack@eecs.umich.edu        for state in self.states.itervalues():
8968481Sgblack@eecs.umich.edu            name = "%s_State_%s.html" % (self.ident, state.ident)
8978481Sgblack@eecs.umich.edu            code = html.createSymbol(state, "State")
8988481Sgblack@eecs.umich.edu            code.write(path, name)
8998481Sgblack@eecs.umich.edu
9008481Sgblack@eecs.umich.edu        # Generate event descriptions
9018481Sgblack@eecs.umich.edu        for event in self.events.itervalues():
9028481Sgblack@eecs.umich.edu            name = "%s_Event_%s.html" % (self.ident, event.ident)
9034032Sktlim@umich.edu            code = html.createSymbol(event, "Event")
9043221Sktlim@umich.edu            code.write(path, name)
9053221Sktlim@umich.edu
9066974Stjones1@inf.ed.ac.uk    def printHTMLTransitions(self, path, active_state):
9076974Stjones1@inf.ed.ac.uk        code = code_formatter()
9088481Sgblack@eecs.umich.edu
9096974Stjones1@inf.ed.ac.uk        code('''
9106974Stjones1@inf.ed.ac.uk<HTML><BODY link="blue" vlink="blue">
9116974Stjones1@inf.ed.ac.uk
9122669Sktlim@umich.edu<H1 align="center">${{html.formatShorthand(self.short)}}:
9136974Stjones1@inf.ed.ac.uk''')
9146974Stjones1@inf.ed.ac.uk        code.indent()
9158481Sgblack@eecs.umich.edu        for i,machine in enumerate(self.symtab.getAllType(StateMachine)):
9166974Stjones1@inf.ed.ac.uk            mid = machine.ident
9176974Stjones1@inf.ed.ac.uk            if i != 0:
9186974Stjones1@inf.ed.ac.uk                extra = " - "
9196974Stjones1@inf.ed.ac.uk            else:
9206974Stjones1@inf.ed.ac.uk                extra = ""
9216974Stjones1@inf.ed.ac.uk            if machine == self:
9226974Stjones1@inf.ed.ac.uk                code('$extra$mid')
9236974Stjones1@inf.ed.ac.uk            else:
9246974Stjones1@inf.ed.ac.uk                code('$extra<A target="Table" href="${mid}_table.html">$mid</A>')
9256974Stjones1@inf.ed.ac.uk        code.dedent()
9266974Stjones1@inf.ed.ac.uk
9276974Stjones1@inf.ed.ac.uk        code("""
9286974Stjones1@inf.ed.ac.uk</H1>
9296974Stjones1@inf.ed.ac.uk
9306974Stjones1@inf.ed.ac.uk<TABLE border=1>
9316974Stjones1@inf.ed.ac.uk<TR>
9326974Stjones1@inf.ed.ac.uk  <TH> </TH>
9336974Stjones1@inf.ed.ac.uk""")
9346974Stjones1@inf.ed.ac.uk
9356974Stjones1@inf.ed.ac.uk        for event in self.events.itervalues():
9366974Stjones1@inf.ed.ac.uk            href = "%s_Event_%s.html" % (self.ident, event.ident)
9376974Stjones1@inf.ed.ac.uk            ref = self.frameRef(href, "Status", href, "1", event.short)
9386974Stjones1@inf.ed.ac.uk            code('<TH bgcolor=white>$ref</TH>')
9396974Stjones1@inf.ed.ac.uk
9402292SN/A        code('</TR>')
9412292SN/A        # -- Body of table
9422292SN/A        for state in self.states.itervalues():
9432292SN/A            # -- Each row
9442292SN/A            if state == active_state:
9452292SN/A                color = "yellow"
9462292SN/A            else:
9472292SN/A                color = "white"
9482292SN/A
9492292SN/A            click = "%s_table_%s.html" % (self.ident, state.ident)
9502292SN/A            over = "%s_State_%s.html" % (self.ident, state.ident)
9512292SN/A            text = html.formatShorthand(state.short)
9522292SN/A            ref = self.frameRef(click, "Table", over, "1", state.short)
9532292SN/A            code('''
9542292SN/A<TR>
9552292SN/A  <TH bgcolor=$color>$ref</TH>
9562292SN/A''')
9572292SN/A
9582292SN/A            # -- One column for each event
9592292SN/A            for event in self.events.itervalues():
9602292SN/A                trans = self.table.get((state,event), None)
9612292SN/A                if trans is None:
9622292SN/A                    # This is the no transition case
9632292SN/A                    if state == active_state:
9642292SN/A                        color = "#C0C000"
9652292SN/A                    else:
9662292SN/A                        color = "lightgrey"
9672292SN/A
9682329SN/A                    code('<TD bgcolor=$color>&nbsp;</TD>')
9692292SN/A                    continue
9702292SN/A
9712292SN/A                next = trans.nextState
9722292SN/A                stall_action = False
9732292SN/A
9747720Sgblack@eecs.umich.edu                # -- Get the actions
9752292SN/A                for action in trans.actions:
9767720Sgblack@eecs.umich.edu                    if action.ident == "z_stall" or \
9772292SN/A                       action.ident == "zz_recycleMandatoryQueue":
9782292SN/A                        stall_action = True
9792292SN/A
9802292SN/A                # -- Print out "actions/next-state"
9812292SN/A                if stall_action:
9822292SN/A                    if state == active_state:
9832292SN/A                        color = "#C0C000"
9842292SN/A                    else:
9852329SN/A                        color = "lightgrey"
9862731Sktlim@umich.edu
9872292SN/A                elif active_state and next.ident == active_state.ident:
9882292SN/A                    color = "aqua"
9892292SN/A                elif state == active_state:
9902292SN/A                    color = "yellow"
9912292SN/A                else:
9922292SN/A                    color = "white"
9932292SN/A
9942727Sktlim@umich.edu                fix = code.nofix()
9952292SN/A                code('<TD bgcolor=$color>')
9962292SN/A                for action in trans.actions:
9972292SN/A                    href = "%s_action_%s.html" % (self.ident, action.ident)
9982292SN/A                    ref = self.frameRef(href, "Status", href, "1",
9992292SN/A                                        action.short)
10002292SN/A                    code('  $ref\n')
10012292SN/A                if next != state:
10022292SN/A                    if trans.actions:
10032292SN/A                        code('/')
10042292SN/A                    click = "%s_table_%s.html" % (self.ident, next.ident)
10054032Sktlim@umich.edu                    over = "%s_State_%s.html" % (self.ident, next.ident)
10064032Sktlim@umich.edu                    ref = self.frameRef(click, "Table", over, "1", next.short)
10074032Sktlim@umich.edu                    code("$ref")
10084032Sktlim@umich.edu                code("</TD>\n")
10092292SN/A                code.fix(fix)
10102292SN/A
10112292SN/A            # -- Each row
10122292SN/A            if state == active_state:
10132292SN/A                color = "yellow"
10142329SN/A            else:
10152292SN/A                color = "white"
10162292SN/A
10172292SN/A            click = "%s_table_%s.html" % (self.ident, state.ident)
10182292SN/A            over = "%s_State_%s.html" % (self.ident, state.ident)
10197720Sgblack@eecs.umich.edu            ref = self.frameRef(click, "Table", over, "1", state.short)
10202292SN/A            code('''
10217720Sgblack@eecs.umich.edu  <TH bgcolor=$color>$ref</TH>
10222292SN/A</TR>
10232292SN/A''')
10242329SN/A        code('''
10252329SN/A<TR>
10262292SN/A  <TH> </TH>
10272292SN/A''')
10282292SN/A
10292292SN/A        for event in self.events.itervalues():
10302292SN/A            href = "%s_Event_%s.html" % (self.ident, event.ident)
10312292SN/A            ref = self.frameRef(href, "Status", href, "1", event.short)
10322292SN/A            code('<TH bgcolor=white>$ref</TH>')
10332329SN/A        code('''
10342731Sktlim@umich.edu</TR>
10352292SN/A</TABLE>
10362292SN/A</BODY></HTML>
10372292SN/A''')
10384032Sktlim@umich.edu
10394032Sktlim@umich.edu
10404032Sktlim@umich.edu        if active_state:
10414032Sktlim@umich.edu            name = "%s_table_%s.html" % (self.ident, active_state.ident)
10426974Stjones1@inf.ed.ac.uk        else:
10436974Stjones1@inf.ed.ac.uk            name = "%s_table.html" % self.ident
10446974Stjones1@inf.ed.ac.uk        code.write(path, name)
10456974Stjones1@inf.ed.ac.uk
10466974Stjones1@inf.ed.ac.uk__all__ = [ "StateMachine" ]
10476974Stjones1@inf.ed.ac.uk