StateMachine.py revision 11113:5a2e1b1b5c43
113531Sjairo.balart@metempsy.com# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
213531Sjairo.balart@metempsy.com# Copyright (c) 2009 The Hewlett-Packard Development Company
313531Sjairo.balart@metempsy.com# Copyright (c) 2013 Advanced Micro Devices, Inc.
413531Sjairo.balart@metempsy.com# All rights reserved.
513531Sjairo.balart@metempsy.com#
613531Sjairo.balart@metempsy.com# Redistribution and use in source and binary forms, with or without
713531Sjairo.balart@metempsy.com# modification, are permitted provided that the following conditions are
813531Sjairo.balart@metempsy.com# met: redistributions of source code must retain the above copyright
913531Sjairo.balart@metempsy.com# notice, this list of conditions and the following disclaimer;
1013531Sjairo.balart@metempsy.com# redistributions in binary form must reproduce the above copyright
1113531Sjairo.balart@metempsy.com# notice, this list of conditions and the following disclaimer in the
1213531Sjairo.balart@metempsy.com# documentation and/or other materials provided with the distribution;
1313531Sjairo.balart@metempsy.com# neither the name of the copyright holders nor the names of its
1413531Sjairo.balart@metempsy.com# contributors may be used to endorse or promote products derived from
1513531Sjairo.balart@metempsy.com# this software without specific prior written permission.
1613531Sjairo.balart@metempsy.com#
1713531Sjairo.balart@metempsy.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1813531Sjairo.balart@metempsy.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1913531Sjairo.balart@metempsy.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2013531Sjairo.balart@metempsy.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2113531Sjairo.balart@metempsy.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2213531Sjairo.balart@metempsy.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2313531Sjairo.balart@metempsy.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2413531Sjairo.balart@metempsy.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2513531Sjairo.balart@metempsy.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2613531Sjairo.balart@metempsy.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2713531Sjairo.balart@metempsy.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2813531Sjairo.balart@metempsy.com
2913531Sjairo.balart@metempsy.comfrom m5.util import orderdict
3013756Sjairo.balart@metempsy.com
3113531Sjairo.balart@metempsy.comfrom slicc.symbols.Symbol import Symbol
3213531Sjairo.balart@metempsy.comfrom slicc.symbols.Var import Var
3313531Sjairo.balart@metempsy.comimport slicc.generate.html as html
3413531Sjairo.balart@metempsy.comimport re
3513531Sjairo.balart@metempsy.com
3613531Sjairo.balart@metempsy.compython_class_map = {
3713531Sjairo.balart@metempsy.com                    "int": "Int",
3813531Sjairo.balart@metempsy.com                    "uint32_t" : "UInt32",
3913531Sjairo.balart@metempsy.com                    "std::string": "String",
4013756Sjairo.balart@metempsy.com                    "bool": "Bool",
4113756Sjairo.balart@metempsy.com                    "CacheMemory": "RubyCache",
4213756Sjairo.balart@metempsy.com                    "WireBuffer": "RubyWireBuffer",
4313756Sjairo.balart@metempsy.com                    "Sequencer": "RubySequencer",
4413756Sjairo.balart@metempsy.com                    "DirectoryMemory": "RubyDirectoryMemory",
4513756Sjairo.balart@metempsy.com                    "MemoryControl": "MemoryControl",
4613756Sjairo.balart@metempsy.com                    "MessageBuffer": "MessageBuffer",
4713531Sjairo.balart@metempsy.com                    "DMASequencer": "DMASequencer",
4813756Sjairo.balart@metempsy.com                    "Prefetcher":"Prefetcher",
4913756Sjairo.balart@metempsy.com                    "Cycles":"Cycles",
5013756Sjairo.balart@metempsy.com                   }
5113756Sjairo.balart@metempsy.com
5213756Sjairo.balart@metempsy.comclass StateMachine(Symbol):
5313756Sjairo.balart@metempsy.com    def __init__(self, symtab, ident, location, pairs, config_parameters):
5413756Sjairo.balart@metempsy.com        super(StateMachine, self).__init__(symtab, ident, location, pairs)
5513531Sjairo.balart@metempsy.com        self.table = None
5613531Sjairo.balart@metempsy.com
5713531Sjairo.balart@metempsy.com        # Data members in the State Machine that have been declared before
5813531Sjairo.balart@metempsy.com        # the opening brace '{'  of the machine.  Note that these along with
5913531Sjairo.balart@metempsy.com        # the members in self.objects form the entire set of data members.
6013531Sjairo.balart@metempsy.com        self.config_parameters = config_parameters
6113531Sjairo.balart@metempsy.com
6213531Sjairo.balart@metempsy.com        self.prefetchers = []
6313531Sjairo.balart@metempsy.com
6413531Sjairo.balart@metempsy.com        for param in config_parameters:
6513531Sjairo.balart@metempsy.com            if param.pointer:
6613531Sjairo.balart@metempsy.com                var = Var(symtab, param.ident, location, param.type_ast.type,
6713531Sjairo.balart@metempsy.com                          "(*m_%s_ptr)" % param.ident, {}, self)
6813531Sjairo.balart@metempsy.com            else:
6913531Sjairo.balart@metempsy.com                var = Var(symtab, param.ident, location, param.type_ast.type,
7013531Sjairo.balart@metempsy.com                          "m_%s" % param.ident, {}, self)
7113531Sjairo.balart@metempsy.com
7213531Sjairo.balart@metempsy.com            self.symtab.registerSym(param.ident, var)
7313531Sjairo.balart@metempsy.com
7413531Sjairo.balart@metempsy.com            if str(param.type_ast.type) == "Prefetcher":
7513531Sjairo.balart@metempsy.com                self.prefetchers.append(var)
7613531Sjairo.balart@metempsy.com
7713531Sjairo.balart@metempsy.com        self.states = orderdict()
7813531Sjairo.balart@metempsy.com        self.events = orderdict()
7913531Sjairo.balart@metempsy.com        self.actions = orderdict()
8013531Sjairo.balart@metempsy.com        self.request_types = orderdict()
8113531Sjairo.balart@metempsy.com        self.transitions = []
8213531Sjairo.balart@metempsy.com        self.in_ports = []
8313531Sjairo.balart@metempsy.com        self.functions = []
8413531Sjairo.balart@metempsy.com
8513531Sjairo.balart@metempsy.com        # Data members in the State Machine that have been declared inside
8613531Sjairo.balart@metempsy.com        # the {} machine.  Note that these along with the config params
8713531Sjairo.balart@metempsy.com        # form the entire set of data members of the machine.
8813531Sjairo.balart@metempsy.com        self.objects = []
8913531Sjairo.balart@metempsy.com        self.TBEType   = None
9013531Sjairo.balart@metempsy.com        self.EntryType = None
9113531Sjairo.balart@metempsy.com        self.debug_flags = set()
9213531Sjairo.balart@metempsy.com        self.debug_flags.add('RubyGenerated')
9313531Sjairo.balart@metempsy.com        self.debug_flags.add('RubySlicc')
9413531Sjairo.balart@metempsy.com
9513531Sjairo.balart@metempsy.com    def __repr__(self):
9613531Sjairo.balart@metempsy.com        return "[StateMachine: %s]" % self.ident
9713531Sjairo.balart@metempsy.com
9813531Sjairo.balart@metempsy.com    def addState(self, state):
9913531Sjairo.balart@metempsy.com        assert self.table is None
10013531Sjairo.balart@metempsy.com        self.states[state.ident] = state
10113531Sjairo.balart@metempsy.com
10213531Sjairo.balart@metempsy.com    def addEvent(self, event):
10313531Sjairo.balart@metempsy.com        assert self.table is None
10413531Sjairo.balart@metempsy.com        self.events[event.ident] = event
10513531Sjairo.balart@metempsy.com
10613531Sjairo.balart@metempsy.com    def addAction(self, action):
10713531Sjairo.balart@metempsy.com        assert self.table is None
10813531Sjairo.balart@metempsy.com
10913531Sjairo.balart@metempsy.com        # Check for duplicate action
11013531Sjairo.balart@metempsy.com        for other in self.actions.itervalues():
11113531Sjairo.balart@metempsy.com            if action.ident == other.ident:
11213531Sjairo.balart@metempsy.com                action.warning("Duplicate action definition: %s" % action.ident)
11313531Sjairo.balart@metempsy.com                action.error("Duplicate action definition: %s" % action.ident)
11413531Sjairo.balart@metempsy.com            if action.short == other.short:
11513531Sjairo.balart@metempsy.com                other.warning("Duplicate action shorthand: %s" % other.ident)
11613531Sjairo.balart@metempsy.com                other.warning("    shorthand = %s" % other.short)
11713531Sjairo.balart@metempsy.com                action.warning("Duplicate action shorthand: %s" % action.ident)
11813531Sjairo.balart@metempsy.com                action.error("    shorthand = %s" % action.short)
11913531Sjairo.balart@metempsy.com
12013531Sjairo.balart@metempsy.com        self.actions[action.ident] = action
12113531Sjairo.balart@metempsy.com
12213531Sjairo.balart@metempsy.com    def addDebugFlag(self, flag):
12313531Sjairo.balart@metempsy.com        self.debug_flags.add(flag)
12413531Sjairo.balart@metempsy.com
12513531Sjairo.balart@metempsy.com    def addRequestType(self, request_type):
12613531Sjairo.balart@metempsy.com        assert self.table is None
12713531Sjairo.balart@metempsy.com        self.request_types[request_type.ident] = request_type
12813531Sjairo.balart@metempsy.com
12913531Sjairo.balart@metempsy.com    def addTransition(self, trans):
13013531Sjairo.balart@metempsy.com        assert self.table is None
13113531Sjairo.balart@metempsy.com        self.transitions.append(trans)
13213756Sjairo.balart@metempsy.com
13313531Sjairo.balart@metempsy.com    def addInPort(self, var):
13413531Sjairo.balart@metempsy.com        self.in_ports.append(var)
13513531Sjairo.balart@metempsy.com
13613531Sjairo.balart@metempsy.com    def addFunc(self, func):
13713756Sjairo.balart@metempsy.com        # register func in the symbol table
13813531Sjairo.balart@metempsy.com        self.symtab.registerSym(str(func), func)
13913531Sjairo.balart@metempsy.com        self.functions.append(func)
14013531Sjairo.balart@metempsy.com
14113531Sjairo.balart@metempsy.com    def addObject(self, obj):
14213531Sjairo.balart@metempsy.com        self.symtab.registerSym(str(obj), obj)
14313531Sjairo.balart@metempsy.com        self.objects.append(obj)
14413531Sjairo.balart@metempsy.com
14513531Sjairo.balart@metempsy.com    def addType(self, type):
14613531Sjairo.balart@metempsy.com        type_ident = '%s' % type.c_ident
14713756Sjairo.balart@metempsy.com
14813756Sjairo.balart@metempsy.com        if type_ident == "%s_TBE" %self.ident:
14913531Sjairo.balart@metempsy.com            if self.TBEType != None:
15013531Sjairo.balart@metempsy.com                self.error("Multiple Transaction Buffer types in a " \
15113531Sjairo.balart@metempsy.com                           "single machine.");
15213531Sjairo.balart@metempsy.com            self.TBEType = type
15313531Sjairo.balart@metempsy.com
15413531Sjairo.balart@metempsy.com        elif "interface" in type and "AbstractCacheEntry" == type["interface"]:
15513531Sjairo.balart@metempsy.com            if "main" in type and "false" == type["main"].lower():
15613531Sjairo.balart@metempsy.com                pass # this isn't the EntryType
15713531Sjairo.balart@metempsy.com            else:
15813531Sjairo.balart@metempsy.com                if self.EntryType != None:
15913531Sjairo.balart@metempsy.com                    self.error("Multiple AbstractCacheEntry types in a " \
16013531Sjairo.balart@metempsy.com                               "single machine.");
16113531Sjairo.balart@metempsy.com                self.EntryType = type
16213531Sjairo.balart@metempsy.com
16313531Sjairo.balart@metempsy.com    # Needs to be called before accessing the table
16413531Sjairo.balart@metempsy.com    def buildTable(self):
16513531Sjairo.balart@metempsy.com        assert self.table is None
16613531Sjairo.balart@metempsy.com
16713531Sjairo.balart@metempsy.com        table = {}
16813756Sjairo.balart@metempsy.com
16913756Sjairo.balart@metempsy.com        for trans in self.transitions:
17013531Sjairo.balart@metempsy.com            # Track which actions we touch so we know if we use them
17113531Sjairo.balart@metempsy.com            # all -- really this should be done for all symbols as
17213531Sjairo.balart@metempsy.com            # part of the symbol table, then only trigger it for
17313531Sjairo.balart@metempsy.com            # Actions, States, Events, etc.
17413531Sjairo.balart@metempsy.com
17513531Sjairo.balart@metempsy.com            for action in trans.actions:
17613531Sjairo.balart@metempsy.com                action.used = True
17713531Sjairo.balart@metempsy.com
17813531Sjairo.balart@metempsy.com            index = (trans.state, trans.event)
17913531Sjairo.balart@metempsy.com            if index in table:
18013756Sjairo.balart@metempsy.com                table[index].warning("Duplicate transition: %s" % table[index])
18113531Sjairo.balart@metempsy.com                trans.error("Duplicate transition: %s" % trans)
18213531Sjairo.balart@metempsy.com            table[index] = trans
18313531Sjairo.balart@metempsy.com
18413531Sjairo.balart@metempsy.com        # Look at all actions to make sure we used them all
18513531Sjairo.balart@metempsy.com        for action in self.actions.itervalues():
18613531Sjairo.balart@metempsy.com            if not action.used:
18713531Sjairo.balart@metempsy.com                error_msg = "Unused action: %s" % action.ident
18813531Sjairo.balart@metempsy.com                if "desc" in action:
18913756Sjairo.balart@metempsy.com                    error_msg += ", "  + action.desc
19013756Sjairo.balart@metempsy.com                action.warning(error_msg)
19113531Sjairo.balart@metempsy.com        self.table = table
19213531Sjairo.balart@metempsy.com
19313531Sjairo.balart@metempsy.com    # determine the port->msg buffer mappings
19413531Sjairo.balart@metempsy.com    def getBufferMaps(self, ident):
19513531Sjairo.balart@metempsy.com        msg_bufs = []
19613531Sjairo.balart@metempsy.com        port_to_buf_map = {}
19713531Sjairo.balart@metempsy.com        in_msg_bufs = {}
19813531Sjairo.balart@metempsy.com        for port in self.in_ports:
19913531Sjairo.balart@metempsy.com            buf_name = "m_%s_ptr" % port.pairs["buffer_expr"].name
20013531Sjairo.balart@metempsy.com            msg_bufs.append(buf_name)
20113531Sjairo.balart@metempsy.com            port_to_buf_map[port] = msg_bufs.index(buf_name)
20213531Sjairo.balart@metempsy.com            if buf_name not in in_msg_bufs:
20313531Sjairo.balart@metempsy.com                in_msg_bufs[buf_name] = [port]
20413756Sjairo.balart@metempsy.com            else:
20513531Sjairo.balart@metempsy.com                in_msg_bufs[buf_name].append(port)
20613531Sjairo.balart@metempsy.com        return port_to_buf_map, in_msg_bufs, msg_bufs
20713531Sjairo.balart@metempsy.com
20813531Sjairo.balart@metempsy.com    def writeCodeFiles(self, path, includes):
20913531Sjairo.balart@metempsy.com        self.printControllerPython(path)
21013531Sjairo.balart@metempsy.com        self.printControllerHH(path)
21113531Sjairo.balart@metempsy.com        self.printControllerCC(path, includes)
21213531Sjairo.balart@metempsy.com        self.printCSwitch(path)
21313756Sjairo.balart@metempsy.com        self.printCWakeup(path, includes)
21413756Sjairo.balart@metempsy.com
21513531Sjairo.balart@metempsy.com    def printControllerPython(self, path):
21613531Sjairo.balart@metempsy.com        code = self.symtab.codeFormatter()
21713531Sjairo.balart@metempsy.com        ident = self.ident
21813531Sjairo.balart@metempsy.com
21913531Sjairo.balart@metempsy.com        py_ident = "%s_Controller" % ident
22013531Sjairo.balart@metempsy.com        c_ident = "%s_Controller" % self.ident
22113531Sjairo.balart@metempsy.com
22213531Sjairo.balart@metempsy.com        code('''
22313531Sjairo.balart@metempsy.comfrom m5.params import *
22413531Sjairo.balart@metempsy.comfrom m5.SimObject import SimObject
22513531Sjairo.balart@metempsy.comfrom Controller import RubyController
22613531Sjairo.balart@metempsy.com
22713756Sjairo.balart@metempsy.comclass $py_ident(RubyController):
22813531Sjairo.balart@metempsy.com    type = '$py_ident'
22913531Sjairo.balart@metempsy.com    cxx_header = 'mem/protocol/${c_ident}.hh'
23013531Sjairo.balart@metempsy.com''')
23113531Sjairo.balart@metempsy.com        code.indent()
23213531Sjairo.balart@metempsy.com        for param in self.config_parameters:
23313531Sjairo.balart@metempsy.com            dflt_str = ''
23413531Sjairo.balart@metempsy.com
23513531Sjairo.balart@metempsy.com            if param.rvalue is not None:
23613531Sjairo.balart@metempsy.com                dflt_str = str(param.rvalue.inline()) + ', '
23713531Sjairo.balart@metempsy.com
23813756Sjairo.balart@metempsy.com            if python_class_map.has_key(param.type_ast.type.c_ident):
23913756Sjairo.balart@metempsy.com                python_type = python_class_map[param.type_ast.type.c_ident]
24013531Sjairo.balart@metempsy.com                code('${{param.ident}} = Param.${{python_type}}(${dflt_str}"")')
24113531Sjairo.balart@metempsy.com
24213531Sjairo.balart@metempsy.com            else:
24313531Sjairo.balart@metempsy.com                self.error("Unknown c++ to python class conversion for c++ " \
24413531Sjairo.balart@metempsy.com                           "type: '%s'. Please update the python_class_map " \
24513531Sjairo.balart@metempsy.com                           "in StateMachine.py", param.type_ast.type.c_ident)
24613531Sjairo.balart@metempsy.com
24713531Sjairo.balart@metempsy.com        code.dedent()
24813531Sjairo.balart@metempsy.com        code.write(path, '%s.py' % py_ident)
24913531Sjairo.balart@metempsy.com
25013531Sjairo.balart@metempsy.com
25113531Sjairo.balart@metempsy.com    def printControllerHH(self, path):
25213756Sjairo.balart@metempsy.com        '''Output the method declarations for the class declaration'''
25313531Sjairo.balart@metempsy.com        code = self.symtab.codeFormatter()
25413531Sjairo.balart@metempsy.com        ident = self.ident
25513531Sjairo.balart@metempsy.com        c_ident = "%s_Controller" % self.ident
25613531Sjairo.balart@metempsy.com
25713531Sjairo.balart@metempsy.com        code('''
25813531Sjairo.balart@metempsy.com/** \\file $c_ident.hh
25913531Sjairo.balart@metempsy.com *
26013531Sjairo.balart@metempsy.com * Auto generated C++ code started by $__file__:$__line__
26113531Sjairo.balart@metempsy.com * Created by slicc definition of Module "${{self.short}}"
26213531Sjairo.balart@metempsy.com */
26313756Sjairo.balart@metempsy.com
26413756Sjairo.balart@metempsy.com#ifndef __${ident}_CONTROLLER_HH__
26513531Sjairo.balart@metempsy.com#define __${ident}_CONTROLLER_HH__
26613531Sjairo.balart@metempsy.com
26713531Sjairo.balart@metempsy.com#include <iostream>
26813531Sjairo.balart@metempsy.com#include <sstream>
26913531Sjairo.balart@metempsy.com#include <string>
27013531Sjairo.balart@metempsy.com
27113531Sjairo.balart@metempsy.com#include "mem/protocol/TransitionResult.hh"
27213531Sjairo.balart@metempsy.com#include "mem/protocol/Types.hh"
27313531Sjairo.balart@metempsy.com#include "mem/ruby/common/Consumer.hh"
27413531Sjairo.balart@metempsy.com#include "mem/ruby/slicc_interface/AbstractController.hh"
27513531Sjairo.balart@metempsy.com#include "params/$c_ident.hh"
27613756Sjairo.balart@metempsy.com
27713531Sjairo.balart@metempsy.com''')
27813531Sjairo.balart@metempsy.com
27913531Sjairo.balart@metempsy.com        seen_types = set()
28013531Sjairo.balart@metempsy.com        for var in self.objects:
28113531Sjairo.balart@metempsy.com            if var.type.ident not in seen_types and not var.type.isPrimitive:
28213531Sjairo.balart@metempsy.com                code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
28313531Sjairo.balart@metempsy.com                seen_types.add(var.type.ident)
28413531Sjairo.balart@metempsy.com
28513531Sjairo.balart@metempsy.com        # for adding information to the protocol debug trace
28613756Sjairo.balart@metempsy.com        code('''
28713756Sjairo.balart@metempsy.comextern std::stringstream ${ident}_transitionComment;
28813531Sjairo.balart@metempsy.com
28913531Sjairo.balart@metempsy.comclass $c_ident : public AbstractController
29013531Sjairo.balart@metempsy.com{
29113531Sjairo.balart@metempsy.com  public:
29213531Sjairo.balart@metempsy.com    typedef ${c_ident}Params Params;
29313531Sjairo.balart@metempsy.com    $c_ident(const Params *p);
29413531Sjairo.balart@metempsy.com    static int getNumControllers();
29513531Sjairo.balart@metempsy.com    void init();
29613531Sjairo.balart@metempsy.com
29713531Sjairo.balart@metempsy.com    MessageBuffer *getMandatoryQueue() const;
29813531Sjairo.balart@metempsy.com    MessageBuffer *getMemoryQueue() const;
29913531Sjairo.balart@metempsy.com    void initNetQueues();
30013531Sjairo.balart@metempsy.com
30113531Sjairo.balart@metempsy.com    void print(std::ostream& out) const;
30213531Sjairo.balart@metempsy.com    void wakeup();
30313531Sjairo.balart@metempsy.com    void resetStats();
30413531Sjairo.balart@metempsy.com    void regStats();
30513531Sjairo.balart@metempsy.com    void collateStats();
30613531Sjairo.balart@metempsy.com
30713531Sjairo.balart@metempsy.com    void recordCacheTrace(int cntrl, CacheRecorder* tr);
30813531Sjairo.balart@metempsy.com    Sequencer* getSequencer() const;
30913531Sjairo.balart@metempsy.com
31013756Sjairo.balart@metempsy.com    int functionalWriteBuffers(PacketPtr&);
31113531Sjairo.balart@metempsy.com
31213531Sjairo.balart@metempsy.com    void countTransition(${ident}_State state, ${ident}_Event event);
31313531Sjairo.balart@metempsy.com    void possibleTransition(${ident}_State state, ${ident}_Event event);
31413531Sjairo.balart@metempsy.com    uint64_t getEventCount(${ident}_Event event);
31513531Sjairo.balart@metempsy.com    bool isPossible(${ident}_State state, ${ident}_Event event);
31613531Sjairo.balart@metempsy.com    uint64_t getTransitionCount(${ident}_State state, ${ident}_Event event);
31713531Sjairo.balart@metempsy.com
31813531Sjairo.balart@metempsy.comprivate:
31913531Sjairo.balart@metempsy.com''')
32013531Sjairo.balart@metempsy.com
32113756Sjairo.balart@metempsy.com        code.indent()
32213756Sjairo.balart@metempsy.com        # added by SS
32313531Sjairo.balart@metempsy.com        for param in self.config_parameters:
32413531Sjairo.balart@metempsy.com            if param.pointer:
32513531Sjairo.balart@metempsy.com                code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;')
32613531Sjairo.balart@metempsy.com            else:
32713531Sjairo.balart@metempsy.com                code('${{param.type_ast.type}} m_${{param.ident}};')
32813531Sjairo.balart@metempsy.com
32913531Sjairo.balart@metempsy.com        code('''
33013531Sjairo.balart@metempsy.comTransitionResult doTransition(${ident}_Event event,
33113531Sjairo.balart@metempsy.com''')
33213531Sjairo.balart@metempsy.com
33313531Sjairo.balart@metempsy.com        if self.EntryType != None:
33413531Sjairo.balart@metempsy.com            code('''
33513531Sjairo.balart@metempsy.com                              ${{self.EntryType.c_ident}}* m_cache_entry_ptr,
33613531Sjairo.balart@metempsy.com''')
33713531Sjairo.balart@metempsy.com        if self.TBEType != None:
33813531Sjairo.balart@metempsy.com            code('''
33913531Sjairo.balart@metempsy.com                              ${{self.TBEType.c_ident}}* m_tbe_ptr,
34013531Sjairo.balart@metempsy.com''')
34113531Sjairo.balart@metempsy.com
34213531Sjairo.balart@metempsy.com        code('''
34313531Sjairo.balart@metempsy.com                              Addr addr);
34413531Sjairo.balart@metempsy.com
34513531Sjairo.balart@metempsy.comTransitionResult doTransitionWorker(${ident}_Event event,
34613531Sjairo.balart@metempsy.com                                    ${ident}_State state,
34713531Sjairo.balart@metempsy.com                                    ${ident}_State& next_state,
34813531Sjairo.balart@metempsy.com''')
34913531Sjairo.balart@metempsy.com
35013531Sjairo.balart@metempsy.com        if self.TBEType != None:
35113531Sjairo.balart@metempsy.com            code('''
35213531Sjairo.balart@metempsy.com                                    ${{self.TBEType.c_ident}}*& m_tbe_ptr,
35313756Sjairo.balart@metempsy.com''')
35413531Sjairo.balart@metempsy.com        if self.EntryType != None:
35513531Sjairo.balart@metempsy.com            code('''
35613531Sjairo.balart@metempsy.com                                    ${{self.EntryType.c_ident}}*& m_cache_entry_ptr,
35713531Sjairo.balart@metempsy.com''')
35813531Sjairo.balart@metempsy.com
35913531Sjairo.balart@metempsy.com        code('''
36013756Sjairo.balart@metempsy.com                                    Addr addr);
36113531Sjairo.balart@metempsy.com
36213531Sjairo.balart@metempsy.comint m_counters[${ident}_State_NUM][${ident}_Event_NUM];
36313531Sjairo.balart@metempsy.comint m_event_counters[${ident}_Event_NUM];
36413531Sjairo.balart@metempsy.combool m_possible[${ident}_State_NUM][${ident}_Event_NUM];
36513531Sjairo.balart@metempsy.com
36613531Sjairo.balart@metempsy.comstatic std::vector<Stats::Vector *> eventVec;
36713531Sjairo.balart@metempsy.comstatic std::vector<std::vector<Stats::Vector *> > transVec;
36813531Sjairo.balart@metempsy.comstatic int m_num_controllers;
36913531Sjairo.balart@metempsy.com
37013531Sjairo.balart@metempsy.com// Internal functions
37113531Sjairo.balart@metempsy.com''')
37213531Sjairo.balart@metempsy.com
37313531Sjairo.balart@metempsy.com        for func in self.functions:
37413531Sjairo.balart@metempsy.com            proto = func.prototype
37513531Sjairo.balart@metempsy.com            if proto:
37613756Sjairo.balart@metempsy.com                code('$proto')
37713531Sjairo.balart@metempsy.com
37813531Sjairo.balart@metempsy.com        if self.EntryType != None:
37913531Sjairo.balart@metempsy.com            code('''
38013531Sjairo.balart@metempsy.com
38113531Sjairo.balart@metempsy.com// Set and Reset for cache_entry variable
38213531Sjairo.balart@metempsy.comvoid set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry);
38313531Sjairo.balart@metempsy.comvoid unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr);
38413531Sjairo.balart@metempsy.com''')
38513531Sjairo.balart@metempsy.com
38613531Sjairo.balart@metempsy.com        if self.TBEType != None:
38713531Sjairo.balart@metempsy.com            code('''
38813531Sjairo.balart@metempsy.com
38913531Sjairo.balart@metempsy.com// Set and Reset for tbe variable
39013531Sjairo.balart@metempsy.comvoid set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe);
39113531Sjairo.balart@metempsy.comvoid unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr);
39213531Sjairo.balart@metempsy.com''')
39313531Sjairo.balart@metempsy.com
39413531Sjairo.balart@metempsy.com        # Prototype the actions that the controller can take
39513531Sjairo.balart@metempsy.com        code('''
39613531Sjairo.balart@metempsy.com
39713531Sjairo.balart@metempsy.com// Actions
39813531Sjairo.balart@metempsy.com''')
39913531Sjairo.balart@metempsy.com        if self.TBEType != None and self.EntryType != None:
40013531Sjairo.balart@metempsy.com            for action in self.actions.itervalues():
40113531Sjairo.balart@metempsy.com                code('/** \\brief ${{action.desc}} */')
40213531Sjairo.balart@metempsy.com                code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& '
40313531Sjairo.balart@metempsy.com                     'm_tbe_ptr, ${{self.EntryType.c_ident}}*& '
40413531Sjairo.balart@metempsy.com                     'm_cache_entry_ptr, Addr addr);')
40513531Sjairo.balart@metempsy.com        elif self.TBEType != None:
40613531Sjairo.balart@metempsy.com            for action in self.actions.itervalues():
40713531Sjairo.balart@metempsy.com                code('/** \\brief ${{action.desc}} */')
40813531Sjairo.balart@metempsy.com                code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& '
40913531Sjairo.balart@metempsy.com                     'm_tbe_ptr, Addr addr);')
41013531Sjairo.balart@metempsy.com        elif self.EntryType != None:
41113531Sjairo.balart@metempsy.com            for action in self.actions.itervalues():
41213531Sjairo.balart@metempsy.com                code('/** \\brief ${{action.desc}} */')
41313531Sjairo.balart@metempsy.com                code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& '
41413531Sjairo.balart@metempsy.com                     'm_cache_entry_ptr, Addr addr);')
41513531Sjairo.balart@metempsy.com        else:
41613531Sjairo.balart@metempsy.com            for action in self.actions.itervalues():
41713531Sjairo.balart@metempsy.com                code('/** \\brief ${{action.desc}} */')
41813531Sjairo.balart@metempsy.com                code('void ${{action.ident}}(Addr addr);')
41913531Sjairo.balart@metempsy.com
42013531Sjairo.balart@metempsy.com        # the controller internal variables
42113531Sjairo.balart@metempsy.com        code('''
42213531Sjairo.balart@metempsy.com
42313531Sjairo.balart@metempsy.com// Objects
42413531Sjairo.balart@metempsy.com''')
42513531Sjairo.balart@metempsy.com        for var in self.objects:
42613531Sjairo.balart@metempsy.com            th = var.get("template", "")
42713531Sjairo.balart@metempsy.com            code('${{var.type.c_ident}}$th* m_${{var.ident}}_ptr;')
42813531Sjairo.balart@metempsy.com
42913531Sjairo.balart@metempsy.com        code.dedent()
43013531Sjairo.balart@metempsy.com        code('};')
43113531Sjairo.balart@metempsy.com        code('#endif // __${ident}_CONTROLLER_H__')
43213531Sjairo.balart@metempsy.com        code.write(path, '%s.hh' % c_ident)
43313531Sjairo.balart@metempsy.com
43413531Sjairo.balart@metempsy.com    def printControllerCC(self, path, includes):
43513531Sjairo.balart@metempsy.com        '''Output the actions for performing the actions'''
43613531Sjairo.balart@metempsy.com
43713531Sjairo.balart@metempsy.com        code = self.symtab.codeFormatter()
43813531Sjairo.balart@metempsy.com        ident = self.ident
43913531Sjairo.balart@metempsy.com        c_ident = "%s_Controller" % self.ident
44013531Sjairo.balart@metempsy.com
44113531Sjairo.balart@metempsy.com        code('''
44213531Sjairo.balart@metempsy.com/** \\file $c_ident.cc
44313531Sjairo.balart@metempsy.com *
44413531Sjairo.balart@metempsy.com * Auto generated C++ code started by $__file__:$__line__
44513531Sjairo.balart@metempsy.com * Created by slicc definition of Module "${{self.short}}"
44613531Sjairo.balart@metempsy.com */
44713531Sjairo.balart@metempsy.com
44813531Sjairo.balart@metempsy.com#include <sys/types.h>
44913531Sjairo.balart@metempsy.com#include <unistd.h>
45013531Sjairo.balart@metempsy.com
45113531Sjairo.balart@metempsy.com#include <cassert>
45213531Sjairo.balart@metempsy.com#include <sstream>
45313531Sjairo.balart@metempsy.com#include <string>
45413531Sjairo.balart@metempsy.com#include <typeinfo>
45513531Sjairo.balart@metempsy.com
45613531Sjairo.balart@metempsy.com#include "base/compiler.hh"
45713531Sjairo.balart@metempsy.com#include "base/cprintf.hh"
45813531Sjairo.balart@metempsy.com
45913531Sjairo.balart@metempsy.com''')
46013690Sjairo.balart@metempsy.com        for f in self.debug_flags:
46113531Sjairo.balart@metempsy.com            code('#include "debug/${{f}}.hh"')
46213531Sjairo.balart@metempsy.com        code('''
46313531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Controller.hh"
46413531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Event.hh"
46513531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_State.hh"
46613531Sjairo.balart@metempsy.com#include "mem/protocol/Types.hh"
46713531Sjairo.balart@metempsy.com#include "mem/ruby/system/RubySystem.hh"
46813531Sjairo.balart@metempsy.com
46913531Sjairo.balart@metempsy.com''')
47013531Sjairo.balart@metempsy.com        for include_path in includes:
47113531Sjairo.balart@metempsy.com            code('#include "${{include_path}}"')
47213531Sjairo.balart@metempsy.com
47313531Sjairo.balart@metempsy.com        code('''
47413531Sjairo.balart@metempsy.com
47513531Sjairo.balart@metempsy.comusing namespace std;
47613690Sjairo.balart@metempsy.com''')
47713531Sjairo.balart@metempsy.com
47813531Sjairo.balart@metempsy.com        # include object classes
47913531Sjairo.balart@metempsy.com        seen_types = set()
48013531Sjairo.balart@metempsy.com        for var in self.objects:
48113531Sjairo.balart@metempsy.com            if var.type.ident not in seen_types and not var.type.isPrimitive:
48213531Sjairo.balart@metempsy.com                code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
48313531Sjairo.balart@metempsy.com            seen_types.add(var.type.ident)
48413531Sjairo.balart@metempsy.com
48513531Sjairo.balart@metempsy.com        num_in_ports = len(self.in_ports)
48613531Sjairo.balart@metempsy.com
48713531Sjairo.balart@metempsy.com        code('''
48813756Sjairo.balart@metempsy.com$c_ident *
48913756Sjairo.balart@metempsy.com${c_ident}Params::create()
49013531Sjairo.balart@metempsy.com{
49113531Sjairo.balart@metempsy.com    return new $c_ident(this);
49213531Sjairo.balart@metempsy.com}
49313531Sjairo.balart@metempsy.com
49413531Sjairo.balart@metempsy.comint $c_ident::m_num_controllers = 0;
49513531Sjairo.balart@metempsy.comstd::vector<Stats::Vector *>  $c_ident::eventVec;
49613531Sjairo.balart@metempsy.comstd::vector<std::vector<Stats::Vector *> >  $c_ident::transVec;
49713531Sjairo.balart@metempsy.com
49813531Sjairo.balart@metempsy.com// for adding information to the protocol debug trace
49913531Sjairo.balart@metempsy.comstringstream ${ident}_transitionComment;
50013531Sjairo.balart@metempsy.com
50113531Sjairo.balart@metempsy.com#ifndef NDEBUG
50213531Sjairo.balart@metempsy.com#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str)
50313531Sjairo.balart@metempsy.com#else
50413531Sjairo.balart@metempsy.com#define APPEND_TRANSITION_COMMENT(str) do {} while (0)
50513531Sjairo.balart@metempsy.com#endif
50613531Sjairo.balart@metempsy.com
50713531Sjairo.balart@metempsy.com/** \\brief constructor */
50813531Sjairo.balart@metempsy.com$c_ident::$c_ident(const Params *p)
50913531Sjairo.balart@metempsy.com    : AbstractController(p)
51013531Sjairo.balart@metempsy.com{
51113531Sjairo.balart@metempsy.com    m_machineID.type = MachineType_${ident};
51213531Sjairo.balart@metempsy.com    m_machineID.num = m_version;
51313531Sjairo.balart@metempsy.com    m_num_controllers++;
51413531Sjairo.balart@metempsy.com
51513531Sjairo.balart@metempsy.com    m_in_ports = $num_in_ports;
51613531Sjairo.balart@metempsy.com''')
51713531Sjairo.balart@metempsy.com        code.indent()
51813531Sjairo.balart@metempsy.com
51913531Sjairo.balart@metempsy.com        #
52013531Sjairo.balart@metempsy.com        # After initializing the universal machine parameters, initialize the
52113531Sjairo.balart@metempsy.com        # this machines config parameters.  Also if these configuration params
52213531Sjairo.balart@metempsy.com        # include a sequencer, connect the it to the controller.
52313531Sjairo.balart@metempsy.com        #
52413531Sjairo.balart@metempsy.com        for param in self.config_parameters:
52513531Sjairo.balart@metempsy.com            if param.pointer:
52613531Sjairo.balart@metempsy.com                code('m_${{param.ident}}_ptr = p->${{param.ident}};')
52713531Sjairo.balart@metempsy.com            else:
52813531Sjairo.balart@metempsy.com                code('m_${{param.ident}} = p->${{param.ident}};')
52913531Sjairo.balart@metempsy.com
53013531Sjairo.balart@metempsy.com            if re.compile("sequencer").search(param.ident):
53113531Sjairo.balart@metempsy.com                code('m_${{param.ident}}_ptr->setController(this);')
53213531Sjairo.balart@metempsy.com
53313531Sjairo.balart@metempsy.com        code('''
53413531Sjairo.balart@metempsy.com
53513531Sjairo.balart@metempsy.comfor (int state = 0; state < ${ident}_State_NUM; state++) {
53613531Sjairo.balart@metempsy.com    for (int event = 0; event < ${ident}_Event_NUM; event++) {
53713531Sjairo.balart@metempsy.com        m_possible[state][event] = false;
53813531Sjairo.balart@metempsy.com        m_counters[state][event] = 0;
53913531Sjairo.balart@metempsy.com    }
54013531Sjairo.balart@metempsy.com}
54113756Sjairo.balart@metempsy.comfor (int event = 0; event < ${ident}_Event_NUM; event++) {
54213531Sjairo.balart@metempsy.com    m_event_counters[event] = 0;
54313531Sjairo.balart@metempsy.com}
54413531Sjairo.balart@metempsy.com''')
54513531Sjairo.balart@metempsy.com        code.dedent()
54613531Sjairo.balart@metempsy.com        code('''
54713531Sjairo.balart@metempsy.com}
54813756Sjairo.balart@metempsy.com
54913531Sjairo.balart@metempsy.comvoid
55013531Sjairo.balart@metempsy.com$c_ident::initNetQueues()
55113531Sjairo.balart@metempsy.com{
55213531Sjairo.balart@metempsy.com    MachineType machine_type = string_to_MachineType("${{self.ident}}");
55313531Sjairo.balart@metempsy.com    int base M5_VAR_USED = MachineType_base_number(machine_type);
55413531Sjairo.balart@metempsy.com
55513531Sjairo.balart@metempsy.com''')
55613531Sjairo.balart@metempsy.com        code.indent()
55713756Sjairo.balart@metempsy.com
55813756Sjairo.balart@metempsy.com        # set for maintaining the vnet, direction pairs already seen for this
55913531Sjairo.balart@metempsy.com        # machine.  This map helps in implementing the check for avoiding
56013531Sjairo.balart@metempsy.com        # multiple message buffers being mapped to the same vnet.
56113531Sjairo.balart@metempsy.com        vnet_dir_set = set()
56213531Sjairo.balart@metempsy.com
56313531Sjairo.balart@metempsy.com        for var in self.config_parameters:
56413531Sjairo.balart@metempsy.com            vid = "m_%s_ptr" % var.ident
56513531Sjairo.balart@metempsy.com            if "network" in var:
56613531Sjairo.balart@metempsy.com                vtype = var.type_ast.type
56713531Sjairo.balart@metempsy.com                code('assert($vid != NULL);')
56813531Sjairo.balart@metempsy.com
56913531Sjairo.balart@metempsy.com                # Network port object
57013531Sjairo.balart@metempsy.com                network = var["network"]
57113531Sjairo.balart@metempsy.com
57213531Sjairo.balart@metempsy.com                if "virtual_network" in var:
57313531Sjairo.balart@metempsy.com                    vnet = var["virtual_network"]
57413531Sjairo.balart@metempsy.com                    vnet_type = var["vnet_type"]
57513531Sjairo.balart@metempsy.com
57613531Sjairo.balart@metempsy.com                    assert (vnet, network) not in vnet_dir_set
57713531Sjairo.balart@metempsy.com                    vnet_dir_set.add((vnet,network))
57813531Sjairo.balart@metempsy.com
57913531Sjairo.balart@metempsy.com                    code('''
58013531Sjairo.balart@metempsy.comm_net_ptr->set${network}NetQueue(m_version + base, $vid->getOrdered(), $vnet,
58113531Sjairo.balart@metempsy.com                                 "$vnet_type", $vid);
58213756Sjairo.balart@metempsy.com''')
58313756Sjairo.balart@metempsy.com                # Set Priority
58413531Sjairo.balart@metempsy.com                if "rank" in var:
58513531Sjairo.balart@metempsy.com                    code('$vid->setPriority(${{var["rank"]}})')
58613531Sjairo.balart@metempsy.com
58713531Sjairo.balart@metempsy.com        code.dedent()
58813531Sjairo.balart@metempsy.com        code('''
58913531Sjairo.balart@metempsy.com}
59013531Sjairo.balart@metempsy.com
59113531Sjairo.balart@metempsy.comvoid
59213531Sjairo.balart@metempsy.com$c_ident::init()
59313531Sjairo.balart@metempsy.com{
59413531Sjairo.balart@metempsy.com    // initialize objects
59513531Sjairo.balart@metempsy.com''')
59613531Sjairo.balart@metempsy.com
59713531Sjairo.balart@metempsy.com        code.indent()
59813531Sjairo.balart@metempsy.com
59913531Sjairo.balart@metempsy.com        for var in self.objects:
60013531Sjairo.balart@metempsy.com            vtype = var.type
60113531Sjairo.balart@metempsy.com            vid = "m_%s_ptr" % var.ident
60213531Sjairo.balart@metempsy.com            if "network" not in var:
60313756Sjairo.balart@metempsy.com                # Not a network port object
60413531Sjairo.balart@metempsy.com                if "primitive" in vtype:
60513531Sjairo.balart@metempsy.com                    code('$vid = new ${{vtype.c_ident}};')
60613531Sjairo.balart@metempsy.com                    if "default" in var:
60713531Sjairo.balart@metempsy.com                        code('(*$vid) = ${{var["default"]}};')
60813531Sjairo.balart@metempsy.com                else:
60913531Sjairo.balart@metempsy.com                    # Normal Object
61013531Sjairo.balart@metempsy.com                    th = var.get("template", "")
61113756Sjairo.balart@metempsy.com                    expr = "%s  = new %s%s" % (vid, vtype.c_ident, th)
61213756Sjairo.balart@metempsy.com                    args = ""
61313531Sjairo.balart@metempsy.com                    if "non_obj" not in vtype and not vtype.isEnumeration:
61413531Sjairo.balart@metempsy.com                        args = var.get("constructor", "")
61513531Sjairo.balart@metempsy.com
61613531Sjairo.balart@metempsy.com                    code('$expr($args);')
61713531Sjairo.balart@metempsy.com                    code('assert($vid != NULL);')
61813531Sjairo.balart@metempsy.com
61913531Sjairo.balart@metempsy.com                    if "default" in var:
62013531Sjairo.balart@metempsy.com                        code('*$vid = ${{var["default"]}}; // Object default')
62113531Sjairo.balart@metempsy.com                    elif "default" in vtype:
62213531Sjairo.balart@metempsy.com                        comment = "Type %s default" % vtype.ident
62313531Sjairo.balart@metempsy.com                        code('*$vid = ${{vtype["default"]}}; // $comment')
62413531Sjairo.balart@metempsy.com
62513531Sjairo.balart@metempsy.com        # Set the prefetchers
62613531Sjairo.balart@metempsy.com        code()
62713531Sjairo.balart@metempsy.com        for prefetcher in self.prefetchers:
62813531Sjairo.balart@metempsy.com            code('${{prefetcher.code}}.setController(this);')
62913531Sjairo.balart@metempsy.com
63013531Sjairo.balart@metempsy.com        code()
63113531Sjairo.balart@metempsy.com        for port in self.in_ports:
63213531Sjairo.balart@metempsy.com            # Set the queue consumers
63313756Sjairo.balart@metempsy.com            code('${{port.code}}.setConsumer(this);')
63413531Sjairo.balart@metempsy.com
63513531Sjairo.balart@metempsy.com        # Initialize the transition profiling
63613531Sjairo.balart@metempsy.com        code()
63713531Sjairo.balart@metempsy.com        for trans in self.transitions:
63813531Sjairo.balart@metempsy.com            # Figure out if we stall
63913531Sjairo.balart@metempsy.com            stall = False
64013531Sjairo.balart@metempsy.com            for action in trans.actions:
64113756Sjairo.balart@metempsy.com                if action.ident == "z_stall":
64213756Sjairo.balart@metempsy.com                    stall = True
64313531Sjairo.balart@metempsy.com
64413531Sjairo.balart@metempsy.com            # Only possible if it is not a 'z' case
64513531Sjairo.balart@metempsy.com            if not stall:
64613531Sjairo.balart@metempsy.com                state = "%s_State_%s" % (self.ident, trans.state.ident)
64713531Sjairo.balart@metempsy.com                event = "%s_Event_%s" % (self.ident, trans.event.ident)
64813531Sjairo.balart@metempsy.com                code('possibleTransition($state, $event);')
64913531Sjairo.balart@metempsy.com
65013531Sjairo.balart@metempsy.com        code.dedent()
65113531Sjairo.balart@metempsy.com        code('''
65213531Sjairo.balart@metempsy.com    AbstractController::init();
65313531Sjairo.balart@metempsy.com    resetStats();
65413531Sjairo.balart@metempsy.com}
65513531Sjairo.balart@metempsy.com''')
65613531Sjairo.balart@metempsy.com
65713531Sjairo.balart@metempsy.com        mq_ident = "NULL"
65813531Sjairo.balart@metempsy.com        for port in self.in_ports:
65913531Sjairo.balart@metempsy.com            if port.code.find("mandatoryQueue_ptr") >= 0:
66013756Sjairo.balart@metempsy.com                mq_ident = "m_mandatoryQueue_ptr"
66113531Sjairo.balart@metempsy.com
66213531Sjairo.balart@metempsy.com        memq_ident = "NULL"
66313531Sjairo.balart@metempsy.com        for port in self.in_ports:
66413531Sjairo.balart@metempsy.com            if port.code.find("responseFromMemory_ptr") >= 0:
66513531Sjairo.balart@metempsy.com                memq_ident = "m_responseFromMemory_ptr"
66613531Sjairo.balart@metempsy.com
66713531Sjairo.balart@metempsy.com        seq_ident = "NULL"
66813531Sjairo.balart@metempsy.com        for param in self.config_parameters:
66913756Sjairo.balart@metempsy.com            if param.ident == "sequencer":
67013756Sjairo.balart@metempsy.com                assert(param.pointer)
67113531Sjairo.balart@metempsy.com                seq_ident = "m_%s_ptr" % param.ident
67213531Sjairo.balart@metempsy.com
67313531Sjairo.balart@metempsy.com        code('''
67413531Sjairo.balart@metempsy.com
67513531Sjairo.balart@metempsy.comvoid
67613531Sjairo.balart@metempsy.com$c_ident::regStats()
67713531Sjairo.balart@metempsy.com{
67813531Sjairo.balart@metempsy.com    AbstractController::regStats();
67913531Sjairo.balart@metempsy.com
68013531Sjairo.balart@metempsy.com    if (m_version == 0) {
68113531Sjairo.balart@metempsy.com        for (${ident}_Event event = ${ident}_Event_FIRST;
68213531Sjairo.balart@metempsy.com             event < ${ident}_Event_NUM; ++event) {
68313531Sjairo.balart@metempsy.com            Stats::Vector *t = new Stats::Vector();
68413531Sjairo.balart@metempsy.com            t->init(m_num_controllers);
68513531Sjairo.balart@metempsy.com            t->name(params()->ruby_system->name() + ".${c_ident}." +
68613531Sjairo.balart@metempsy.com                ${ident}_Event_to_string(event));
68713531Sjairo.balart@metempsy.com            t->flags(Stats::pdf | Stats::total | Stats::oneline |
68813531Sjairo.balart@metempsy.com                     Stats::nozero);
68913531Sjairo.balart@metempsy.com
69013531Sjairo.balart@metempsy.com            eventVec.push_back(t);
69113531Sjairo.balart@metempsy.com        }
69213531Sjairo.balart@metempsy.com
69313756Sjairo.balart@metempsy.com        for (${ident}_State state = ${ident}_State_FIRST;
69413756Sjairo.balart@metempsy.com             state < ${ident}_State_NUM; ++state) {
69513531Sjairo.balart@metempsy.com
69613531Sjairo.balart@metempsy.com            transVec.push_back(std::vector<Stats::Vector *>());
69713531Sjairo.balart@metempsy.com
69813531Sjairo.balart@metempsy.com            for (${ident}_Event event = ${ident}_Event_FIRST;
69913531Sjairo.balart@metempsy.com                 event < ${ident}_Event_NUM; ++event) {
70013531Sjairo.balart@metempsy.com
70113531Sjairo.balart@metempsy.com                Stats::Vector *t = new Stats::Vector();
70213531Sjairo.balart@metempsy.com                t->init(m_num_controllers);
70313531Sjairo.balart@metempsy.com                t->name(params()->ruby_system->name() + ".${c_ident}." +
70413531Sjairo.balart@metempsy.com                        ${ident}_State_to_string(state) +
70513531Sjairo.balart@metempsy.com                        "." + ${ident}_Event_to_string(event));
70613531Sjairo.balart@metempsy.com
70713531Sjairo.balart@metempsy.com                t->flags(Stats::pdf | Stats::total | Stats::oneline |
70813531Sjairo.balart@metempsy.com                         Stats::nozero);
70913531Sjairo.balart@metempsy.com                transVec[state].push_back(t);
71013531Sjairo.balart@metempsy.com            }
71113531Sjairo.balart@metempsy.com        }
71213531Sjairo.balart@metempsy.com    }
71313756Sjairo.balart@metempsy.com}
71413531Sjairo.balart@metempsy.com
71513531Sjairo.balart@metempsy.comvoid
71613531Sjairo.balart@metempsy.com$c_ident::collateStats()
71713531Sjairo.balart@metempsy.com{
71813531Sjairo.balart@metempsy.com    for (${ident}_Event event = ${ident}_Event_FIRST;
71913531Sjairo.balart@metempsy.com         event < ${ident}_Event_NUM; ++event) {
72013531Sjairo.balart@metempsy.com        for (unsigned int i = 0; i < m_num_controllers; ++i) {
72113531Sjairo.balart@metempsy.com            RubySystem *rs = params()->ruby_system;
72213531Sjairo.balart@metempsy.com            std::map<uint32_t, AbstractController *>::iterator it =
72313531Sjairo.balart@metempsy.com                     rs->m_abstract_controls[MachineType_${ident}].find(i);
72413531Sjairo.balart@metempsy.com            assert(it != rs->m_abstract_controls[MachineType_${ident}].end());
72513531Sjairo.balart@metempsy.com            (*eventVec[event])[i] =
72613531Sjairo.balart@metempsy.com                (($c_ident *)(*it).second)->getEventCount(event);
72713531Sjairo.balart@metempsy.com        }
72813531Sjairo.balart@metempsy.com    }
72913531Sjairo.balart@metempsy.com
73013531Sjairo.balart@metempsy.com    for (${ident}_State state = ${ident}_State_FIRST;
73113531Sjairo.balart@metempsy.com         state < ${ident}_State_NUM; ++state) {
73213531Sjairo.balart@metempsy.com
73313531Sjairo.balart@metempsy.com        for (${ident}_Event event = ${ident}_Event_FIRST;
73413531Sjairo.balart@metempsy.com             event < ${ident}_Event_NUM; ++event) {
73513531Sjairo.balart@metempsy.com
73613531Sjairo.balart@metempsy.com            for (unsigned int i = 0; i < m_num_controllers; ++i) {
73713531Sjairo.balart@metempsy.com                RubySystem *rs = params()->ruby_system;
73813531Sjairo.balart@metempsy.com                std::map<uint32_t, AbstractController *>::iterator it =
73913531Sjairo.balart@metempsy.com                         rs->m_abstract_controls[MachineType_${ident}].find(i);
74013531Sjairo.balart@metempsy.com                assert(it != rs->m_abstract_controls[MachineType_${ident}].end());
74113531Sjairo.balart@metempsy.com                (*transVec[state][event])[i] =
74213531Sjairo.balart@metempsy.com                    (($c_ident *)(*it).second)->getTransitionCount(state, event);
74313531Sjairo.balart@metempsy.com            }
74413531Sjairo.balart@metempsy.com        }
74513531Sjairo.balart@metempsy.com    }
74613756Sjairo.balart@metempsy.com}
74713531Sjairo.balart@metempsy.com
74813756Sjairo.balart@metempsy.comvoid
74913756Sjairo.balart@metempsy.com$c_ident::countTransition(${ident}_State state, ${ident}_Event event)
75013756Sjairo.balart@metempsy.com{
75113756Sjairo.balart@metempsy.com    assert(m_possible[state][event]);
75213756Sjairo.balart@metempsy.com    m_counters[state][event]++;
75313531Sjairo.balart@metempsy.com    m_event_counters[event]++;
75413531Sjairo.balart@metempsy.com}
75513531Sjairo.balart@metempsy.comvoid
75613531Sjairo.balart@metempsy.com$c_ident::possibleTransition(${ident}_State state,
75713531Sjairo.balart@metempsy.com                             ${ident}_Event event)
75813531Sjairo.balart@metempsy.com{
75913531Sjairo.balart@metempsy.com    m_possible[state][event] = true;
76013756Sjairo.balart@metempsy.com}
76113531Sjairo.balart@metempsy.com
76213531Sjairo.balart@metempsy.comuint64_t
76313531Sjairo.balart@metempsy.com$c_ident::getEventCount(${ident}_Event event)
76413531Sjairo.balart@metempsy.com{
76513531Sjairo.balart@metempsy.com    return m_event_counters[event];
76613531Sjairo.balart@metempsy.com}
76713531Sjairo.balart@metempsy.com
76813531Sjairo.balart@metempsy.combool
76913531Sjairo.balart@metempsy.com$c_ident::isPossible(${ident}_State state, ${ident}_Event event)
77013531Sjairo.balart@metempsy.com{
77113531Sjairo.balart@metempsy.com    return m_possible[state][event];
77213531Sjairo.balart@metempsy.com}
77313531Sjairo.balart@metempsy.com
77413531Sjairo.balart@metempsy.comuint64_t
77513531Sjairo.balart@metempsy.com$c_ident::getTransitionCount(${ident}_State state,
77613531Sjairo.balart@metempsy.com                             ${ident}_Event event)
77713531Sjairo.balart@metempsy.com{
77813531Sjairo.balart@metempsy.com    return m_counters[state][event];
77913531Sjairo.balart@metempsy.com}
78013531Sjairo.balart@metempsy.com
78113531Sjairo.balart@metempsy.comint
78213531Sjairo.balart@metempsy.com$c_ident::getNumControllers()
78313531Sjairo.balart@metempsy.com{
78413531Sjairo.balart@metempsy.com    return m_num_controllers;
78513756Sjairo.balart@metempsy.com}
78613531Sjairo.balart@metempsy.com
78713531Sjairo.balart@metempsy.comMessageBuffer*
78813531Sjairo.balart@metempsy.com$c_ident::getMandatoryQueue() const
78913531Sjairo.balart@metempsy.com{
79013531Sjairo.balart@metempsy.com    return $mq_ident;
79113531Sjairo.balart@metempsy.com}
79213531Sjairo.balart@metempsy.com
79313756Sjairo.balart@metempsy.comMessageBuffer*
79413531Sjairo.balart@metempsy.com$c_ident::getMemoryQueue() const
79513531Sjairo.balart@metempsy.com{
79613531Sjairo.balart@metempsy.com    return $memq_ident;
79713531Sjairo.balart@metempsy.com}
79813531Sjairo.balart@metempsy.com
79913531Sjairo.balart@metempsy.comSequencer*
80013531Sjairo.balart@metempsy.com$c_ident::getSequencer() const
80113531Sjairo.balart@metempsy.com{
80213531Sjairo.balart@metempsy.com    return $seq_ident;
80313531Sjairo.balart@metempsy.com}
80413531Sjairo.balart@metempsy.com
80513531Sjairo.balart@metempsy.comvoid
80613531Sjairo.balart@metempsy.com$c_ident::print(ostream& out) const
80713756Sjairo.balart@metempsy.com{
80813531Sjairo.balart@metempsy.com    out << "[$c_ident " << m_version << "]";
80913531Sjairo.balart@metempsy.com}
81013531Sjairo.balart@metempsy.com
81113531Sjairo.balart@metempsy.comvoid $c_ident::resetStats()
81213531Sjairo.balart@metempsy.com{
81313531Sjairo.balart@metempsy.com    for (int state = 0; state < ${ident}_State_NUM; state++) {
81413531Sjairo.balart@metempsy.com        for (int event = 0; event < ${ident}_Event_NUM; event++) {
81513531Sjairo.balart@metempsy.com            m_counters[state][event] = 0;
81613531Sjairo.balart@metempsy.com        }
81713531Sjairo.balart@metempsy.com    }
81813531Sjairo.balart@metempsy.com
81913531Sjairo.balart@metempsy.com    for (int event = 0; event < ${ident}_Event_NUM; event++) {
82013531Sjairo.balart@metempsy.com        m_event_counters[event] = 0;
82113531Sjairo.balart@metempsy.com    }
82213531Sjairo.balart@metempsy.com
82313531Sjairo.balart@metempsy.com    AbstractController::resetStats();
82413531Sjairo.balart@metempsy.com}
82513531Sjairo.balart@metempsy.com''')
82613531Sjairo.balart@metempsy.com
82713531Sjairo.balart@metempsy.com        if self.EntryType != None:
82813531Sjairo.balart@metempsy.com            code('''
82913531Sjairo.balart@metempsy.com
83013531Sjairo.balart@metempsy.com// Set and Reset for cache_entry variable
83113531Sjairo.balart@metempsy.comvoid
83213531Sjairo.balart@metempsy.com$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry)
83313531Sjairo.balart@metempsy.com{
83413531Sjairo.balart@metempsy.com  m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry;
83513531Sjairo.balart@metempsy.com}
83613531Sjairo.balart@metempsy.com
83713531Sjairo.balart@metempsy.comvoid
83813531Sjairo.balart@metempsy.com$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr)
83913531Sjairo.balart@metempsy.com{
84013531Sjairo.balart@metempsy.com  m_cache_entry_ptr = 0;
84113531Sjairo.balart@metempsy.com}
84213531Sjairo.balart@metempsy.com''')
84313531Sjairo.balart@metempsy.com
84413531Sjairo.balart@metempsy.com        if self.TBEType != None:
84513531Sjairo.balart@metempsy.com            code('''
84613531Sjairo.balart@metempsy.com
84713531Sjairo.balart@metempsy.com// Set and Reset for tbe variable
84813531Sjairo.balart@metempsy.comvoid
84913531Sjairo.balart@metempsy.com$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe)
85013531Sjairo.balart@metempsy.com{
85113531Sjairo.balart@metempsy.com  m_tbe_ptr = m_new_tbe;
85213531Sjairo.balart@metempsy.com}
85313531Sjairo.balart@metempsy.com
85413531Sjairo.balart@metempsy.comvoid
85513531Sjairo.balart@metempsy.com$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr)
85613531Sjairo.balart@metempsy.com{
85713531Sjairo.balart@metempsy.com  m_tbe_ptr = NULL;
85813531Sjairo.balart@metempsy.com}
85913531Sjairo.balart@metempsy.com''')
86013531Sjairo.balart@metempsy.com
86113531Sjairo.balart@metempsy.com        code('''
86213531Sjairo.balart@metempsy.com
86313531Sjairo.balart@metempsy.comvoid
86413531Sjairo.balart@metempsy.com$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr)
86513531Sjairo.balart@metempsy.com{
86613531Sjairo.balart@metempsy.com''')
86713531Sjairo.balart@metempsy.com        #
86813531Sjairo.balart@metempsy.com        # Record cache contents for all associated caches.
86913531Sjairo.balart@metempsy.com        #
87013531Sjairo.balart@metempsy.com        code.indent()
87113531Sjairo.balart@metempsy.com        for param in self.config_parameters:
87213531Sjairo.balart@metempsy.com            if param.type_ast.type.ident == "CacheMemory":
87313531Sjairo.balart@metempsy.com                assert(param.pointer)
87413531Sjairo.balart@metempsy.com                code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);')
87513531Sjairo.balart@metempsy.com
87613531Sjairo.balart@metempsy.com        code.dedent()
87713531Sjairo.balart@metempsy.com        code('''
87813531Sjairo.balart@metempsy.com}
87913531Sjairo.balart@metempsy.com
88013531Sjairo.balart@metempsy.com// Actions
88113531Sjairo.balart@metempsy.com''')
88213531Sjairo.balart@metempsy.com        if self.TBEType != None and self.EntryType != None:
88313531Sjairo.balart@metempsy.com            for action in self.actions.itervalues():
88413531Sjairo.balart@metempsy.com                if "c_code" not in action:
88513531Sjairo.balart@metempsy.com                 continue
88613531Sjairo.balart@metempsy.com
88713531Sjairo.balart@metempsy.com                code('''
88813531Sjairo.balart@metempsy.com/** \\brief ${{action.desc}} */
88913531Sjairo.balart@metempsy.comvoid
89013531Sjairo.balart@metempsy.com$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, Addr addr)
89113531Sjairo.balart@metempsy.com{
89213531Sjairo.balart@metempsy.com    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
89313531Sjairo.balart@metempsy.com    try {
89413531Sjairo.balart@metempsy.com       ${{action["c_code"]}}
89513531Sjairo.balart@metempsy.com    } catch (const RejectException & e) {
89613531Sjairo.balart@metempsy.com       fatal("Error in action ${{ident}}:${{action.ident}}: "
89713531Sjairo.balart@metempsy.com             "executed a peek statement with the wrong message "
89813531Sjairo.balart@metempsy.com             "type specified. ");
89913531Sjairo.balart@metempsy.com    }
90013531Sjairo.balart@metempsy.com}
90113531Sjairo.balart@metempsy.com
90213531Sjairo.balart@metempsy.com''')
90313531Sjairo.balart@metempsy.com        elif self.TBEType != None:
90413531Sjairo.balart@metempsy.com            for action in self.actions.itervalues():
90513531Sjairo.balart@metempsy.com                if "c_code" not in action:
90613531Sjairo.balart@metempsy.com                 continue
90713531Sjairo.balart@metempsy.com
90813531Sjairo.balart@metempsy.com                code('''
90913531Sjairo.balart@metempsy.com/** \\brief ${{action.desc}} */
91013531Sjairo.balart@metempsy.comvoid
91113531Sjairo.balart@metempsy.com$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, Addr addr)
91213531Sjairo.balart@metempsy.com{
91313531Sjairo.balart@metempsy.com    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
91413531Sjairo.balart@metempsy.com    ${{action["c_code"]}}
91513531Sjairo.balart@metempsy.com}
91613531Sjairo.balart@metempsy.com
91713531Sjairo.balart@metempsy.com''')
91813531Sjairo.balart@metempsy.com        elif self.EntryType != None:
91913531Sjairo.balart@metempsy.com            for action in self.actions.itervalues():
92013531Sjairo.balart@metempsy.com                if "c_code" not in action:
92113531Sjairo.balart@metempsy.com                 continue
92213531Sjairo.balart@metempsy.com
92313531Sjairo.balart@metempsy.com                code('''
92413531Sjairo.balart@metempsy.com/** \\brief ${{action.desc}} */
92513531Sjairo.balart@metempsy.comvoid
92613531Sjairo.balart@metempsy.com$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, Addr addr)
92713531Sjairo.balart@metempsy.com{
92813531Sjairo.balart@metempsy.com    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
92913531Sjairo.balart@metempsy.com    ${{action["c_code"]}}
93013531Sjairo.balart@metempsy.com}
93113531Sjairo.balart@metempsy.com
93213531Sjairo.balart@metempsy.com''')
93313531Sjairo.balart@metempsy.com        else:
93413531Sjairo.balart@metempsy.com            for action in self.actions.itervalues():
93513531Sjairo.balart@metempsy.com                if "c_code" not in action:
93613531Sjairo.balart@metempsy.com                 continue
93713531Sjairo.balart@metempsy.com
93813531Sjairo.balart@metempsy.com                code('''
93913531Sjairo.balart@metempsy.com/** \\brief ${{action.desc}} */
94013531Sjairo.balart@metempsy.comvoid
94113531Sjairo.balart@metempsy.com$c_ident::${{action.ident}}(Addr addr)
94213531Sjairo.balart@metempsy.com{
94313756Sjairo.balart@metempsy.com    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
94413531Sjairo.balart@metempsy.com    ${{action["c_code"]}}
94513531Sjairo.balart@metempsy.com}
94613531Sjairo.balart@metempsy.com
94713531Sjairo.balart@metempsy.com''')
94813531Sjairo.balart@metempsy.com        for func in self.functions:
94913531Sjairo.balart@metempsy.com            code(func.generateCode())
95013531Sjairo.balart@metempsy.com
95113531Sjairo.balart@metempsy.com        # Function for functional writes to messages buffered in the controller
95213531Sjairo.balart@metempsy.com        code('''
95313531Sjairo.balart@metempsy.comint
95413531Sjairo.balart@metempsy.com$c_ident::functionalWriteBuffers(PacketPtr& pkt)
95513531Sjairo.balart@metempsy.com{
95613531Sjairo.balart@metempsy.com    int num_functional_writes = 0;
95713531Sjairo.balart@metempsy.com''')
95813531Sjairo.balart@metempsy.com        for var in self.objects:
95913531Sjairo.balart@metempsy.com            vtype = var.type
96013531Sjairo.balart@metempsy.com            if vtype.isBuffer:
96113531Sjairo.balart@metempsy.com                vid = "m_%s_ptr" % var.ident
96213531Sjairo.balart@metempsy.com                code('num_functional_writes += $vid->functionalWrite(pkt);')
96313531Sjairo.balart@metempsy.com
96413531Sjairo.balart@metempsy.com        for var in self.config_parameters:
96513531Sjairo.balart@metempsy.com            vtype = var.type_ast.type
96613531Sjairo.balart@metempsy.com            if vtype.isBuffer:
96713531Sjairo.balart@metempsy.com                vid = "m_%s_ptr" % var.ident
96813531Sjairo.balart@metempsy.com                code('num_functional_writes += $vid->functionalWrite(pkt);')
96913531Sjairo.balart@metempsy.com
97013531Sjairo.balart@metempsy.com        code('''
97113531Sjairo.balart@metempsy.com    return num_functional_writes;
97213531Sjairo.balart@metempsy.com}
97313531Sjairo.balart@metempsy.com''')
97413531Sjairo.balart@metempsy.com
97513531Sjairo.balart@metempsy.com        code.write(path, "%s.cc" % c_ident)
97613531Sjairo.balart@metempsy.com
97713531Sjairo.balart@metempsy.com    def printCWakeup(self, path, includes):
97813531Sjairo.balart@metempsy.com        '''Output the wakeup loop for the events'''
97913531Sjairo.balart@metempsy.com
98013531Sjairo.balart@metempsy.com        code = self.symtab.codeFormatter()
98113531Sjairo.balart@metempsy.com        ident = self.ident
98213531Sjairo.balart@metempsy.com
98313531Sjairo.balart@metempsy.com        outputRequest_types = True
98413756Sjairo.balart@metempsy.com        if len(self.request_types) == 0:
98513531Sjairo.balart@metempsy.com            outputRequest_types = False
98613531Sjairo.balart@metempsy.com
98713531Sjairo.balart@metempsy.com        code('''
98813531Sjairo.balart@metempsy.com// Auto generated C++ code started by $__file__:$__line__
98913756Sjairo.balart@metempsy.com// ${ident}: ${{self.short}}
99013531Sjairo.balart@metempsy.com
99113531Sjairo.balart@metempsy.com#include <sys/types.h>
99213531Sjairo.balart@metempsy.com#include <unistd.h>
99313531Sjairo.balart@metempsy.com
99413531Sjairo.balart@metempsy.com#include <cassert>
99513531Sjairo.balart@metempsy.com#include <typeinfo>
99613531Sjairo.balart@metempsy.com
99713531Sjairo.balart@metempsy.com#include "base/misc.hh"
99813531Sjairo.balart@metempsy.com
99913531Sjairo.balart@metempsy.com''')
100013531Sjairo.balart@metempsy.com        for f in self.debug_flags:
100113531Sjairo.balart@metempsy.com            code('#include "debug/${{f}}.hh"')
100213531Sjairo.balart@metempsy.com        code('''
100313531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Controller.hh"
100413531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Event.hh"
100513531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_State.hh"
100613531Sjairo.balart@metempsy.com
100713531Sjairo.balart@metempsy.com''')
100813531Sjairo.balart@metempsy.com
100913531Sjairo.balart@metempsy.com        if outputRequest_types:
101013531Sjairo.balart@metempsy.com            code('''#include "mem/protocol/${ident}_RequestType.hh"''')
101113531Sjairo.balart@metempsy.com
101213531Sjairo.balart@metempsy.com        code('''
101313531Sjairo.balart@metempsy.com#include "mem/protocol/Types.hh"
101413531Sjairo.balart@metempsy.com#include "mem/ruby/system/RubySystem.hh"
101513531Sjairo.balart@metempsy.com
101613531Sjairo.balart@metempsy.com''')
101713531Sjairo.balart@metempsy.com
101813531Sjairo.balart@metempsy.com
101913531Sjairo.balart@metempsy.com        for include_path in includes:
102013531Sjairo.balart@metempsy.com            code('#include "${{include_path}}"')
102113531Sjairo.balart@metempsy.com
102213531Sjairo.balart@metempsy.com        port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident)
102313531Sjairo.balart@metempsy.com
102413756Sjairo.balart@metempsy.com        code('''
102513756Sjairo.balart@metempsy.com
102613756Sjairo.balart@metempsy.comusing namespace std;
102713756Sjairo.balart@metempsy.com
102813756Sjairo.balart@metempsy.comvoid
102913756Sjairo.balart@metempsy.com${ident}_Controller::wakeup()
103013756Sjairo.balart@metempsy.com{
103113531Sjairo.balart@metempsy.com    int counter = 0;
103213531Sjairo.balart@metempsy.com    while (true) {
103313531Sjairo.balart@metempsy.com        unsigned char rejected[${{len(msg_bufs)}}];
103413531Sjairo.balart@metempsy.com        memset(rejected, 0, sizeof(unsigned char)*${{len(msg_bufs)}});
103513531Sjairo.balart@metempsy.com        // Some cases will put us into an infinite loop without this limit
103613531Sjairo.balart@metempsy.com        assert(counter <= m_transitions_per_cycle);
103713531Sjairo.balart@metempsy.com        if (counter == m_transitions_per_cycle) {
103813531Sjairo.balart@metempsy.com            // Count how often we are fully utilized
103913531Sjairo.balart@metempsy.com            m_fully_busy_cycles++;
104013531Sjairo.balart@metempsy.com
104113531Sjairo.balart@metempsy.com            // Wakeup in another cycle and try again
104213531Sjairo.balart@metempsy.com            scheduleEvent(Cycles(1));
104313531Sjairo.balart@metempsy.com            break;
104413531Sjairo.balart@metempsy.com        }
104513756Sjairo.balart@metempsy.com''')
104613756Sjairo.balart@metempsy.com
104713531Sjairo.balart@metempsy.com        code.indent()
104813531Sjairo.balart@metempsy.com        code.indent()
104913531Sjairo.balart@metempsy.com
105013531Sjairo.balart@metempsy.com        # InPorts
105113531Sjairo.balart@metempsy.com        #
105213531Sjairo.balart@metempsy.com        for port in self.in_ports:
105313756Sjairo.balart@metempsy.com            code.indent()
105413531Sjairo.balart@metempsy.com            code('// ${ident}InPort $port')
105513531Sjairo.balart@metempsy.com            if port.pairs.has_key("rank"):
105613531Sjairo.balart@metempsy.com                code('m_cur_in_port = ${{port.pairs["rank"]}};')
105713531Sjairo.balart@metempsy.com            else:
105813531Sjairo.balart@metempsy.com                code('m_cur_in_port = 0;')
105913531Sjairo.balart@metempsy.com            if port in port_to_buf_map:
106013531Sjairo.balart@metempsy.com                code('try {')
106113531Sjairo.balart@metempsy.com                code.indent()
106213531Sjairo.balart@metempsy.com            code('${{port["c_code_in_port"]}}')
106313531Sjairo.balart@metempsy.com
106413531Sjairo.balart@metempsy.com            if port in port_to_buf_map:
106513531Sjairo.balart@metempsy.com                code.dedent()
106613531Sjairo.balart@metempsy.com                code('''
106713531Sjairo.balart@metempsy.com            } catch (const RejectException & e) {
106813531Sjairo.balart@metempsy.com                rejected[${{port_to_buf_map[port]}}]++;
106913531Sjairo.balart@metempsy.com            }
107013531Sjairo.balart@metempsy.com''')
107113531Sjairo.balart@metempsy.com            code.dedent()
107213756Sjairo.balart@metempsy.com            code('')
107313531Sjairo.balart@metempsy.com
107413531Sjairo.balart@metempsy.com        code.dedent()
107513531Sjairo.balart@metempsy.com        code.dedent()
107613531Sjairo.balart@metempsy.com        code('''
107713531Sjairo.balart@metempsy.com        // If we got this far, we have nothing left todo or something went
107813531Sjairo.balart@metempsy.com        // wrong''')
107913531Sjairo.balart@metempsy.com        for buf_name, ports in in_msg_bufs.items():
108013531Sjairo.balart@metempsy.com            if len(ports) > 1:
108113531Sjairo.balart@metempsy.com                # only produce checks when a buffer is shared by multiple ports
108213531Sjairo.balart@metempsy.com                code('''
108313531Sjairo.balart@metempsy.com        if (${{buf_name}}->isReady() && rejected[${{port_to_buf_map[ports[0]]}}] == ${{len(ports)}})
108413531Sjairo.balart@metempsy.com        {
108513531Sjairo.balart@metempsy.com            // no port claimed the message on the top of this buffer
108613531Sjairo.balart@metempsy.com            panic("Runtime Error at Ruby Time: %d. "
108713531Sjairo.balart@metempsy.com                  "All ports rejected a message. "
108813531Sjairo.balart@metempsy.com                  "You are probably sending a message type to this controller "
108913531Sjairo.balart@metempsy.com                  "over a virtual network that do not define an in_port for "
109013531Sjairo.balart@metempsy.com                  "the incoming message type.\\n",
109113531Sjairo.balart@metempsy.com                  Cycles(1));
109213531Sjairo.balart@metempsy.com        }
109313531Sjairo.balart@metempsy.com''')
109413531Sjairo.balart@metempsy.com        code('''
109513531Sjairo.balart@metempsy.com        break;
109613531Sjairo.balart@metempsy.com    }
109713531Sjairo.balart@metempsy.com}
109813531Sjairo.balart@metempsy.com''')
109913531Sjairo.balart@metempsy.com
110013531Sjairo.balart@metempsy.com        code.write(path, "%s_Wakeup.cc" % self.ident)
110113531Sjairo.balart@metempsy.com
110213531Sjairo.balart@metempsy.com    def printCSwitch(self, path):
110313531Sjairo.balart@metempsy.com        '''Output switch statement for transition table'''
110413531Sjairo.balart@metempsy.com
110513531Sjairo.balart@metempsy.com        code = self.symtab.codeFormatter()
110613531Sjairo.balart@metempsy.com        ident = self.ident
110713531Sjairo.balart@metempsy.com
110813531Sjairo.balart@metempsy.com        code('''
110913531Sjairo.balart@metempsy.com// Auto generated C++ code started by $__file__:$__line__
111013531Sjairo.balart@metempsy.com// ${ident}: ${{self.short}}
111113531Sjairo.balart@metempsy.com
111213531Sjairo.balart@metempsy.com#include <cassert>
111313531Sjairo.balart@metempsy.com
111413531Sjairo.balart@metempsy.com#include "base/misc.hh"
111513531Sjairo.balart@metempsy.com#include "base/trace.hh"
111613531Sjairo.balart@metempsy.com#include "debug/ProtocolTrace.hh"
111713531Sjairo.balart@metempsy.com#include "debug/RubyGenerated.hh"
111813531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Controller.hh"
111913531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_Event.hh"
112013531Sjairo.balart@metempsy.com#include "mem/protocol/${ident}_State.hh"
112113531Sjairo.balart@metempsy.com#include "mem/protocol/Types.hh"
112213531Sjairo.balart@metempsy.com#include "mem/ruby/system/RubySystem.hh"
112313531Sjairo.balart@metempsy.com
112413531Sjairo.balart@metempsy.com#define HASH_FUN(state, event)  ((int(state)*${ident}_Event_NUM)+int(event))
112513531Sjairo.balart@metempsy.com
112613531Sjairo.balart@metempsy.com#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str())
112713531Sjairo.balart@metempsy.com#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str(""))
112813531Sjairo.balart@metempsy.com
112913531Sjairo.balart@metempsy.comTransitionResult
113013531Sjairo.balart@metempsy.com${ident}_Controller::doTransition(${ident}_Event event,
113113531Sjairo.balart@metempsy.com''')
113213531Sjairo.balart@metempsy.com        if self.EntryType != None:
113313531Sjairo.balart@metempsy.com            code('''
113413531Sjairo.balart@metempsy.com                                  ${{self.EntryType.c_ident}}* m_cache_entry_ptr,
113513531Sjairo.balart@metempsy.com''')
113613531Sjairo.balart@metempsy.com        if self.TBEType != None:
113713531Sjairo.balart@metempsy.com            code('''
113813531Sjairo.balart@metempsy.com                                  ${{self.TBEType.c_ident}}* m_tbe_ptr,
113913531Sjairo.balart@metempsy.com''')
114013531Sjairo.balart@metempsy.com        code('''
114113531Sjairo.balart@metempsy.com                                  Addr addr)
114213531Sjairo.balart@metempsy.com{
114313531Sjairo.balart@metempsy.com''')
114413531Sjairo.balart@metempsy.com        code.indent()
114513531Sjairo.balart@metempsy.com
114613531Sjairo.balart@metempsy.com        if self.TBEType != None and self.EntryType != None:
114713531Sjairo.balart@metempsy.com            code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);')
1148        elif self.TBEType != None:
1149            code('${ident}_State state = getState(m_tbe_ptr, addr);')
1150        elif self.EntryType != None:
1151            code('${ident}_State state = getState(m_cache_entry_ptr, addr);')
1152        else:
1153            code('${ident}_State state = getState(addr);')
1154
1155        code('''
1156${ident}_State next_state = state;
1157
1158DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n",
1159        *this, curCycle(), ${ident}_State_to_string(state),
1160        ${ident}_Event_to_string(event), addr);
1161
1162TransitionResult result =
1163''')
1164        if self.TBEType != None and self.EntryType != None:
1165            code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);')
1166        elif self.TBEType != None:
1167            code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);')
1168        elif self.EntryType != None:
1169            code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);')
1170        else:
1171            code('doTransitionWorker(event, state, next_state, addr);')
1172
1173        port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident)
1174
1175        code('''
1176
1177if (result == TransitionResult_Valid) {
1178    DPRINTF(RubyGenerated, "next_state: %s\\n",
1179            ${ident}_State_to_string(next_state));
1180    countTransition(state, event);
1181
1182    DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %#x %s\\n",
1183             curTick(), m_version, "${ident}",
1184             ${ident}_Event_to_string(event),
1185             ${ident}_State_to_string(state),
1186             ${ident}_State_to_string(next_state),
1187             addr, GET_TRANSITION_COMMENT());
1188
1189    CLEAR_TRANSITION_COMMENT();
1190''')
1191        if self.TBEType != None and self.EntryType != None:
1192            code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);')
1193            code('setAccessPermission(m_cache_entry_ptr, addr, next_state);')
1194        elif self.TBEType != None:
1195            code('setState(m_tbe_ptr, addr, next_state);')
1196            code('setAccessPermission(addr, next_state);')
1197        elif self.EntryType != None:
1198            code('setState(m_cache_entry_ptr, addr, next_state);')
1199            code('setAccessPermission(m_cache_entry_ptr, addr, next_state);')
1200        else:
1201            code('setState(addr, next_state);')
1202            code('setAccessPermission(addr, next_state);')
1203
1204        code('''
1205} else if (result == TransitionResult_ResourceStall) {
1206    DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n",
1207             curTick(), m_version, "${ident}",
1208             ${ident}_Event_to_string(event),
1209             ${ident}_State_to_string(state),
1210             ${ident}_State_to_string(next_state),
1211             addr, "Resource Stall");
1212} else if (result == TransitionResult_ProtocolStall) {
1213    DPRINTF(RubyGenerated, "stalling\\n");
1214    DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %#x %s\\n",
1215             curTick(), m_version, "${ident}",
1216             ${ident}_Event_to_string(event),
1217             ${ident}_State_to_string(state),
1218             ${ident}_State_to_string(next_state),
1219             addr, "Protocol Stall");
1220}
1221
1222return result;
1223''')
1224        code.dedent()
1225        code('''
1226}
1227
1228TransitionResult
1229${ident}_Controller::doTransitionWorker(${ident}_Event event,
1230                                        ${ident}_State state,
1231                                        ${ident}_State& next_state,
1232''')
1233
1234        if self.TBEType != None:
1235            code('''
1236                                        ${{self.TBEType.c_ident}}*& m_tbe_ptr,
1237''')
1238        if self.EntryType != None:
1239                  code('''
1240                                        ${{self.EntryType.c_ident}}*& m_cache_entry_ptr,
1241''')
1242        code('''
1243                                        Addr addr)
1244{
1245    switch(HASH_FUN(state, event)) {
1246''')
1247
1248        # This map will allow suppress generating duplicate code
1249        cases = orderdict()
1250
1251        for trans in self.transitions:
1252            case_string = "%s_State_%s, %s_Event_%s" % \
1253                (self.ident, trans.state.ident, self.ident, trans.event.ident)
1254
1255            case = self.symtab.codeFormatter()
1256            # Only set next_state if it changes
1257            if trans.state != trans.nextState:
1258                if trans.nextState.isWildcard():
1259                    # When * is encountered as an end state of a transition,
1260                    # the next state is determined by calling the
1261                    # machine-specific getNextState function. The next state
1262                    # is determined before any actions of the transition
1263                    # execute, and therefore the next state calculation cannot
1264                    # depend on any of the transitionactions.
1265                    case('next_state = getNextState(addr);')
1266                else:
1267                    ns_ident = trans.nextState.ident
1268                    case('next_state = ${ident}_State_${ns_ident};')
1269
1270            actions = trans.actions
1271            request_types = trans.request_types
1272
1273            # Check for resources
1274            case_sorter = []
1275            res = trans.resources
1276            for key,val in res.iteritems():
1277                val = '''
1278if (!%s.areNSlotsAvailable(%s, clockEdge()))
1279    return TransitionResult_ResourceStall;
1280''' % (key.code, val)
1281                case_sorter.append(val)
1282
1283            # Check all of the request_types for resource constraints
1284            for request_type in request_types:
1285                val = '''
1286if (!checkResourceAvailable(%s_RequestType_%s, addr)) {
1287    return TransitionResult_ResourceStall;
1288}
1289''' % (self.ident, request_type.ident)
1290                case_sorter.append(val)
1291
1292            # Emit the code sequences in a sorted order.  This makes the
1293            # output deterministic (without this the output order can vary
1294            # since Map's keys() on a vector of pointers is not deterministic
1295            for c in sorted(case_sorter):
1296                case("$c")
1297
1298            # Record access types for this transition
1299            for request_type in request_types:
1300                case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);')
1301
1302            # Figure out if we stall
1303            stall = False
1304            for action in actions:
1305                if action.ident == "z_stall":
1306                    stall = True
1307                    break
1308
1309            if stall:
1310                case('return TransitionResult_ProtocolStall;')
1311            else:
1312                if self.TBEType != None and self.EntryType != None:
1313                    for action in actions:
1314                        case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);')
1315                elif self.TBEType != None:
1316                    for action in actions:
1317                        case('${{action.ident}}(m_tbe_ptr, addr);')
1318                elif self.EntryType != None:
1319                    for action in actions:
1320                        case('${{action.ident}}(m_cache_entry_ptr, addr);')
1321                else:
1322                    for action in actions:
1323                        case('${{action.ident}}(addr);')
1324                case('return TransitionResult_Valid;')
1325
1326            case = str(case)
1327
1328            # Look to see if this transition code is unique.
1329            if case not in cases:
1330                cases[case] = []
1331
1332            cases[case].append(case_string)
1333
1334        # Walk through all of the unique code blocks and spit out the
1335        # corresponding case statement elements
1336        for case,transitions in cases.iteritems():
1337            # Iterative over all the multiple transitions that share
1338            # the same code
1339            for trans in transitions:
1340                code('  case HASH_FUN($trans):')
1341            code('    $case\n')
1342
1343        code('''
1344      default:
1345        panic("Invalid transition\\n"
1346              "%s time: %d addr: %s event: %s state: %s\\n",
1347              name(), curCycle(), addr, event, state);
1348    }
1349
1350    return TransitionResult_Valid;
1351}
1352''')
1353        code.write(path, "%s_Transitions.cc" % self.ident)
1354
1355
1356    # **************************
1357    # ******* HTML Files *******
1358    # **************************
1359    def frameRef(self, click_href, click_target, over_href, over_num, text):
1360        code = self.symtab.codeFormatter(fix_newlines=False)
1361        code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\"
1362    if (parent.frames[$over_num].location != parent.location + '$over_href') {
1363        parent.frames[$over_num].location='$over_href'
1364    }\">
1365    ${{html.formatShorthand(text)}}
1366    </A>""")
1367        return str(code)
1368
1369    def writeHTMLFiles(self, path):
1370        # Create table with no row hilighted
1371        self.printHTMLTransitions(path, None)
1372
1373        # Generate transition tables
1374        for state in self.states.itervalues():
1375            self.printHTMLTransitions(path, state)
1376
1377        # Generate action descriptions
1378        for action in self.actions.itervalues():
1379            name = "%s_action_%s.html" % (self.ident, action.ident)
1380            code = html.createSymbol(action, "Action")
1381            code.write(path, name)
1382
1383        # Generate state descriptions
1384        for state in self.states.itervalues():
1385            name = "%s_State_%s.html" % (self.ident, state.ident)
1386            code = html.createSymbol(state, "State")
1387            code.write(path, name)
1388
1389        # Generate event descriptions
1390        for event in self.events.itervalues():
1391            name = "%s_Event_%s.html" % (self.ident, event.ident)
1392            code = html.createSymbol(event, "Event")
1393            code.write(path, name)
1394
1395    def printHTMLTransitions(self, path, active_state):
1396        code = self.symtab.codeFormatter()
1397
1398        code('''
1399<HTML>
1400<BODY link="blue" vlink="blue">
1401
1402<H1 align="center">${{html.formatShorthand(self.short)}}:
1403''')
1404        code.indent()
1405        for i,machine in enumerate(self.symtab.getAllType(StateMachine)):
1406            mid = machine.ident
1407            if i != 0:
1408                extra = " - "
1409            else:
1410                extra = ""
1411            if machine == self:
1412                code('$extra$mid')
1413            else:
1414                code('$extra<A target="Table" href="${mid}_table.html">$mid</A>')
1415        code.dedent()
1416
1417        code("""
1418</H1>
1419
1420<TABLE border=1>
1421<TR>
1422  <TH> </TH>
1423""")
1424
1425        for event in self.events.itervalues():
1426            href = "%s_Event_%s.html" % (self.ident, event.ident)
1427            ref = self.frameRef(href, "Status", href, "1", event.short)
1428            code('<TH bgcolor=white>$ref</TH>')
1429
1430        code('</TR>')
1431        # -- Body of table
1432        for state in self.states.itervalues():
1433            # -- Each row
1434            if state == active_state:
1435                color = "yellow"
1436            else:
1437                color = "white"
1438
1439            click = "%s_table_%s.html" % (self.ident, state.ident)
1440            over = "%s_State_%s.html" % (self.ident, state.ident)
1441            text = html.formatShorthand(state.short)
1442            ref = self.frameRef(click, "Table", over, "1", state.short)
1443            code('''
1444<TR>
1445  <TH bgcolor=$color>$ref</TH>
1446''')
1447
1448            # -- One column for each event
1449            for event in self.events.itervalues():
1450                trans = self.table.get((state,event), None)
1451                if trans is None:
1452                    # This is the no transition case
1453                    if state == active_state:
1454                        color = "#C0C000"
1455                    else:
1456                        color = "lightgrey"
1457
1458                    code('<TD bgcolor=$color>&nbsp;</TD>')
1459                    continue
1460
1461                next = trans.nextState
1462                stall_action = False
1463
1464                # -- Get the actions
1465                for action in trans.actions:
1466                    if action.ident == "z_stall" or \
1467                       action.ident == "zz_recycleMandatoryQueue":
1468                        stall_action = True
1469
1470                # -- Print out "actions/next-state"
1471                if stall_action:
1472                    if state == active_state:
1473                        color = "#C0C000"
1474                    else:
1475                        color = "lightgrey"
1476
1477                elif active_state and next.ident == active_state.ident:
1478                    color = "aqua"
1479                elif state == active_state:
1480                    color = "yellow"
1481                else:
1482                    color = "white"
1483
1484                code('<TD bgcolor=$color>')
1485                for action in trans.actions:
1486                    href = "%s_action_%s.html" % (self.ident, action.ident)
1487                    ref = self.frameRef(href, "Status", href, "1",
1488                                        action.short)
1489                    code('  $ref')
1490                if next != state:
1491                    if trans.actions:
1492                        code('/')
1493                    click = "%s_table_%s.html" % (self.ident, next.ident)
1494                    over = "%s_State_%s.html" % (self.ident, next.ident)
1495                    ref = self.frameRef(click, "Table", over, "1", next.short)
1496                    code("$ref")
1497                code("</TD>")
1498
1499            # -- Each row
1500            if state == active_state:
1501                color = "yellow"
1502            else:
1503                color = "white"
1504
1505            click = "%s_table_%s.html" % (self.ident, state.ident)
1506            over = "%s_State_%s.html" % (self.ident, state.ident)
1507            ref = self.frameRef(click, "Table", over, "1", state.short)
1508            code('''
1509  <TH bgcolor=$color>$ref</TH>
1510</TR>
1511''')
1512        code('''
1513<!- Column footer->
1514<TR>
1515  <TH> </TH>
1516''')
1517
1518        for event in self.events.itervalues():
1519            href = "%s_Event_%s.html" % (self.ident, event.ident)
1520            ref = self.frameRef(href, "Status", href, "1", event.short)
1521            code('<TH bgcolor=white>$ref</TH>')
1522        code('''
1523</TR>
1524</TABLE>
1525</BODY></HTML>
1526''')
1527
1528
1529        if active_state:
1530            name = "%s_table_%s.html" % (self.ident, active_state.ident)
1531        else:
1532            name = "%s_table.html" % self.ident
1533        code.write(path, name)
1534
1535__all__ = [ "StateMachine" ]
1536