ruby: message buffers: significant changes
[gem5.git] / src / mem / slicc / symbols / StateMachine.py
index b5c12fe25b5f65f50b51a2bab1887b4e6d98a56f..7360136128f9ff5bac3c708306bdb8a3a5a5bb63 100644 (file)
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from m5.util import code_formatter, orderdict
+from m5.util import orderdict
 
 from slicc.symbols.Symbol import Symbol
 from slicc.symbols.Var import Var
 import slicc.generate.html as html
+import re
 
-python_class_map = {"int": "Int",
-                    "string": "String",
+python_class_map = {
+                    "int": "Int",
+                    "uint32_t" : "UInt32",
+                    "std::string": "String",
                     "bool": "Bool",
                     "CacheMemory": "RubyCache",
+                    "WireBuffer": "RubyWireBuffer",
                     "Sequencer": "RubySequencer",
                     "DirectoryMemory": "RubyDirectoryMemory",
-                    "MemoryControl": "RubyMemoryControl",
-                    "DMASequencer": "DMASequencer"
-                    }
+                    "MemoryControl": "MemoryControl",
+                    "DMASequencer": "DMASequencer",
+                    "Prefetcher":"Prefetcher",
+                    "Cycles":"Cycles",
+                   }
 
 class StateMachine(Symbol):
     def __init__(self, symtab, ident, location, pairs, config_parameters):
         super(StateMachine, self).__init__(symtab, ident, location, pairs)
         self.table = None
+
+        # Data members in the State Machine that have been declared before
+        # the opening brace '{'  of the machine.  Note that these along with
+        # the members in self.objects form the entire set of data members.
         self.config_parameters = config_parameters
+
+        self.prefetchers = []
+
         for param in config_parameters:
             if param.pointer:
-                var = Var(symtab, param.name, location, param.type_ast.type,
-                          "(*m_%s_ptr)" % param.name, {}, self)
+                var = Var(symtab, param.ident, location, param.type_ast.type,
+                          "(*m_%s_ptr)" % param.ident, {}, self)
             else:
-                var = Var(symtab, param.name, location, param.type_ast.type,
-                          "m_%s" % param.name, {}, self)
-            self.symtab.registerSym(param.name, var)
+                var = Var(symtab, param.ident, location, param.type_ast.type,
+                          "m_%s" % param.ident, {}, self)
+
+            self.symtab.registerSym(param.ident, var)
+
+            if str(param.type_ast.type) == "Prefetcher":
+                self.prefetchers.append(var)
 
         self.states = orderdict()
         self.events = orderdict()
         self.actions = orderdict()
+        self.request_types = orderdict()
         self.transitions = []
         self.in_ports = []
         self.functions = []
-        self.objects = []
 
-        self.message_buffer_names = []
+        # Data members in the State Machine that have been declared inside
+        # the {} machine.  Note that these along with the config params
+        # form the entire set of data members of the machine.
+        self.objects = []
+        self.TBEType   = None
+        self.EntryType = None
 
     def __repr__(self):
         return "[StateMachine: %s]" % self.ident
@@ -92,6 +114,10 @@ class StateMachine(Symbol):
 
         self.actions[action.ident] = action
 
+    def addRequestType(self, request_type):
+        assert self.table is None
+        self.request_types[request_type.ident] = request_type
+
     def addTransition(self, trans):
         assert self.table is None
         self.transitions.append(trans)
@@ -105,8 +131,24 @@ class StateMachine(Symbol):
         self.functions.append(func)
 
     def addObject(self, obj):
+        self.symtab.registerSym(str(obj), obj)
         self.objects.append(obj)
 
+    def addType(self, type):
+        type_ident = '%s' % type.c_ident
+
+        if type_ident == "%s_TBE" %self.ident:
+            if self.TBEType != None:
+                self.error("Multiple Transaction Buffer types in a " \
+                           "single machine.");
+            self.TBEType = type
+
+        elif "interface" in type and "AbstractCacheEntry" == type["interface"]:
+            if self.EntryType != None:
+                self.error("Multiple AbstractCacheEntry types in a " \
+                           "single machine.");
+            self.EntryType = type
+
     # Needs to be called before accessing the table
     def buildTable(self):
         assert self.table is None
@@ -137,23 +179,20 @@ class StateMachine(Symbol):
                 action.warning(error_msg)
         self.table = table
 
-    def writeCodeFiles(self, path):
+    def writeCodeFiles(self, path, includes):
         self.printControllerPython(path)
         self.printControllerHH(path)
-        self.printControllerCC(path)
+        self.printControllerCC(path, includes)
         self.printCSwitch(path)
-        self.printCWakeup(path)
-        self.printProfilerCC(path)
-        self.printProfilerHH(path)
-
-        for func in self.functions:
-            func.writeCodeFiles(path)
+        self.printCWakeup(path, includes)
 
     def printControllerPython(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
+
         py_ident = "%s_Controller" % ident
         c_ident = "%s_Controller" % self.ident
+
         code('''
 from m5.params import *
 from m5.SimObject import SimObject
@@ -161,15 +200,25 @@ from Controller import RubyController
 
 class $py_ident(RubyController):
     type = '$py_ident'
+    cxx_header = 'mem/protocol/${c_ident}.hh'
 ''')
         code.indent()
         for param in self.config_parameters:
             dflt_str = ''
-            if param.default is not None:
-                dflt_str = str(param.default) + ', '
-            if python_class_map.has_key(param.type_ast.type.c_ident):
+
+            if param.rvalue is not None:
+                dflt_str = str(param.rvalue.inline()) + ', '
+
+            if param.type_ast.type.c_ident == "MessageBuffer":
+                if param["network"] == "To":
+                    code('${{param.ident}} = MasterPort(${dflt_str}"")')
+                else:
+                    code('${{param.ident}} = SlavePort(${dflt_str}"")')
+
+            elif python_class_map.has_key(param.type_ast.type.c_ident):
                 python_type = python_class_map[param.type_ast.type.c_ident]
-                code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")')
+                code('${{param.ident}} = Param.${{python_type}}(${dflt_str}"")')
+
             else:
                 self.error("Unknown c++ to python class conversion for c++ " \
                            "type: '%s'. Please update the python_class_map " \
@@ -180,63 +229,71 @@ class $py_ident(RubyController):
 
     def printControllerHH(self, path):
         '''Output the method declarations for the class declaration'''
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
         c_ident = "%s_Controller" % self.ident
 
-        self.message_buffer_names = []
-
         code('''
-/** \\file $ident.hh
+/** \\file $c_ident.hh
  *
  * Auto generated C++ code started by $__file__:$__line__
  * Created by slicc definition of Module "${{self.short}}"
  */
 
-#ifndef ${ident}_CONTROLLER_H
-#define ${ident}_CONTROLLER_H
+#ifndef __${ident}_CONTROLLER_HH__
+#define __${ident}_CONTROLLER_HH__
 
-#include "params/$c_ident.hh"
+#include <iostream>
+#include <sstream>
+#include <string>
 
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/slicc_interface/AbstractController.hh"
 #include "mem/protocol/TransitionResult.hh"
 #include "mem/protocol/Types.hh"
-#include "mem/protocol/${ident}_Profiler.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
+#include "params/$c_ident.hh"
 ''')
 
         seen_types = set()
         for var in self.objects:
             if var.type.ident not in seen_types and not var.type.isPrimitive:
                 code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
-            seen_types.add(var.type.ident)
+                seen_types.add(var.type.ident)
 
         # for adding information to the protocol debug trace
         code('''
-extern stringstream ${ident}_transitionComment;
+extern std::stringstream ${ident}_transitionComment;
 
-class $c_ident : public AbstractController {
-#ifdef CHECK_COHERENCE
-#endif /* CHECK_COHERENCE */
-public:
+class $c_ident : public AbstractController
+{
+  public:
     typedef ${c_ident}Params Params;
     $c_ident(const Params *p);
     static int getNumControllers();
     void init();
+
     MessageBuffer* getMandatoryQueue() const;
-    const int & getVersion() const;
-    const string toString() const;
-    const string getName() const;
-    const MachineType getMachineType() const;
-    void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; }
-    void print(ostream& out) const;
-    void printConfig(ostream& out) const;
+    void setNetQueue(const std::string& name, MessageBuffer *b);
+
+    void print(std::ostream& out) const;
     void wakeup();
-    void printStats(ostream& out) const;
-    void clearStats();
-    void blockOnQueue(Address addr, MessageBuffer* port);
-    void unblock(Address addr);
+    void resetStats();
+    void regStats();
+    void collateStats();
+
+    void recordCacheTrace(int cntrl, CacheRecorder* tr);
+    Sequencer* getSequencer() const;
+
+    bool functionalReadBuffers(PacketPtr&);
+    uint32_t functionalWriteBuffers(PacketPtr&);
+
+    void countTransition(${ident}_State state, ${ident}_Event event);
+    void possibleTransition(${ident}_State state, ${ident}_Event event);
+    uint64 getEventCount(${ident}_Event event);
+    bool isPossible(${ident}_State state, ${ident}_Event event);
+    uint64 getTransitionCount(${ident}_State state, ${ident}_Event event);
+
 private:
 ''')
 
@@ -249,22 +306,46 @@ private:
                 code('${{param.type_ast.type}} m_${{param.ident}};')
 
         code('''
-int m_number_of_TBEs;
-
-TransitionResult doTransition(${ident}_Event event, ${ident}_State state, const Address& addr); // in ${ident}_Transitions.cc
-TransitionResult doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr); // in ${ident}_Transitions.cc
-string m_name;
-int m_transitions_per_cycle;
-int m_buffer_size;
-int m_recycle_latency;
-map< string, string > m_cfg;
-NodeID m_version;
-Network* m_net_ptr;
-MachineID m_machineID;
-bool m_is_blocking;
-map< Address, MessageBuffer* > m_block_map;
-${ident}_Profiler s_profiler;
+TransitionResult doTransition(${ident}_Event event,
+''')
+
+        if self.EntryType != None:
+            code('''
+                              ${{self.EntryType.c_ident}}* m_cache_entry_ptr,
+''')
+        if self.TBEType != None:
+            code('''
+                              ${{self.TBEType.c_ident}}* m_tbe_ptr,
+''')
+
+        code('''
+                              const Address addr);
+
+TransitionResult doTransitionWorker(${ident}_Event event,
+                                    ${ident}_State state,
+                                    ${ident}_State& next_state,
+''')
+
+        if self.TBEType != None:
+            code('''
+                                    ${{self.TBEType.c_ident}}*& m_tbe_ptr,
+''')
+        if self.EntryType != None:
+            code('''
+                                    ${{self.EntryType.c_ident}}*& m_cache_entry_ptr,
+''')
+
+        code('''
+                                    const Address& addr);
+
+int m_counters[${ident}_State_NUM][${ident}_Event_NUM];
+int m_event_counters[${ident}_Event_NUM];
+bool m_possible[${ident}_State_NUM][${ident}_Event_NUM];
+
+static std::vector<Stats::Vector *> eventVec;
+static std::vector<std::vector<Stats::Vector *> > transVec;
 static int m_num_controllers;
+
 // Internal functions
 ''')
 
@@ -273,52 +354,100 @@ static int m_num_controllers;
             if proto:
                 code('$proto')
 
+        if self.EntryType != None:
+            code('''
+
+// Set and Reset for cache_entry variable
+void set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry);
+void unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr);
+''')
+
+        if self.TBEType != None:
+            code('''
+
+// Set and Reset for tbe variable
+void set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe);
+void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr);
+''')
+
+        # Prototype the actions that the controller can take
         code('''
 
 // Actions
 ''')
-        for action in self.actions.itervalues():
-            code('/** \\brief ${{action.desc}} */')
-            code('void ${{action.ident}}(const Address& addr);')
+        if self.TBEType != None and self.EntryType != None:
+            for action in self.actions.itervalues():
+                code('/** \\brief ${{action.desc}} */')
+                code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& '
+                     'm_tbe_ptr, ${{self.EntryType.c_ident}}*& '
+                     'm_cache_entry_ptr, const Address& addr);')
+        elif self.TBEType != None:
+            for action in self.actions.itervalues():
+                code('/** \\brief ${{action.desc}} */')
+                code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& '
+                     'm_tbe_ptr, const Address& addr);')
+        elif self.EntryType != None:
+            for action in self.actions.itervalues():
+                code('/** \\brief ${{action.desc}} */')
+                code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& '
+                     'm_cache_entry_ptr, const Address& addr);')
+        else:
+            for action in self.actions.itervalues():
+                code('/** \\brief ${{action.desc}} */')
+                code('void ${{action.ident}}(const Address& addr);')
 
         # the controller internal variables
         code('''
 
-// Object
+// Objects
 ''')
         for var in self.objects:
-            th = var.get("template_hack", "")
-            code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;')
-
-            if var.type.ident == "MessageBuffer":
-                self.message_buffer_names.append("m_%s_ptr" % var.c_ident)
+            th = var.get("template", "")
+            code('${{var.type.c_ident}}$th* m_${{var.ident}}_ptr;')
 
         code.dedent()
         code('};')
-        code('#endif // ${ident}_CONTROLLER_H')
+        code('#endif // __${ident}_CONTROLLER_H__')
         code.write(path, '%s.hh' % c_ident)
 
-    def printControllerCC(self, path):
+    def printControllerCC(self, path, includes):
         '''Output the actions for performing the actions'''
 
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
         c_ident = "%s_Controller" % self.ident
 
         code('''
-/** \\file $ident.cc
+/** \\file $c_ident.cc
  *
  * Auto generated C++ code started by $__file__:$__line__
  * Created by slicc definition of Module "${{self.short}}"
  */
 
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cassert>
+#include <sstream>
+#include <string>
+
+#include "base/compiler.hh"
+#include "base/cprintf.hh"
+#include "debug/RubyGenerated.hh"
+#include "debug/RubySlicc.hh"
 #include "mem/protocol/${ident}_Controller.hh"
-#include "mem/protocol/${ident}_State.hh"
 #include "mem/protocol/${ident}_Event.hh"
+#include "mem/protocol/${ident}_State.hh"
 #include "mem/protocol/Types.hh"
+#include "mem/ruby/common/Global.hh"
 #include "mem/ruby/system/System.hh"
+''')
+        for include_path in includes:
+            code('#include "${{include_path}}"')
+
+        code('''
+
+using namespace std;
 ''')
 
         # include object classes
@@ -328,6 +457,8 @@ static int m_num_controllers;
                 code('#include "mem/protocol/${{var.type.c_ident}}.hh"')
             seen_types.add(var.type.ident)
 
+        num_in_ports = len(self.in_ports)
+
         code('''
 $c_ident *
 ${c_ident}Params::create()
@@ -335,86 +466,164 @@ ${c_ident}Params::create()
     return new $c_ident(this);
 }
 
-
 int $c_ident::m_num_controllers = 0;
+std::vector<Stats::Vector *>  $c_ident::eventVec;
+std::vector<std::vector<Stats::Vector *> >  $c_ident::transVec;
 
+// for adding information to the protocol debug trace
 stringstream ${ident}_transitionComment;
+
+#ifndef NDEBUG
 #define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str)
+#else
+#define APPEND_TRANSITION_COMMENT(str) do {} while (0)
+#endif
+
 /** \\brief constructor */
 $c_ident::$c_ident(const Params *p)
     : AbstractController(p)
 {
-    m_version = p->version;
-    m_transitions_per_cycle = p->transitions_per_cycle;
-    m_buffer_size = p->buffer_size;
-    m_recycle_latency = p->recycle_latency;
-    m_number_of_TBEs = p->number_of_TBEs;
-    m_is_blocking = false;
+    m_machineID.type = MachineType_${ident};
+    m_machineID.num = m_version;
+    m_num_controllers++;
+
+    m_in_ports = $num_in_ports;
 ''')
         code.indent()
 
         #
         # After initializing the universal machine parameters, initialize the
-        # this machines config parameters.  Also detemine if these configuration
-        # params include a sequencer.  This information will be used later for
-        # contecting the sequencer back to the L1 cache controller.
+        # this machines config parameters.  Also if these configuration params
+        # include a sequencer, connect the it to the controller.
         #
-        contains_sequencer = False
         for param in self.config_parameters:
-            if param.name == "sequencer" or param.name == "dma_sequencer":
-                contains_sequencer = True
+
+            # Do not initialize messgage buffers since they are initialized
+            # when the port based connections are made.
+            if param.type_ast.type.c_ident == "MessageBuffer":
+                continue
+
             if param.pointer:
-                code('m_${{param.name}}_ptr = p->${{param.name}};')
+                code('m_${{param.ident}}_ptr = p->${{param.ident}};')
             else:
-                code('m_${{param.name}} = p->${{param.name}};')
+                code('m_${{param.ident}} = p->${{param.ident}};')
 
-        #
-        # For the l1 cache controller, add the special atomic support which 
-        # includes passing the sequencer a pointer to the controller.
-        #
-        if self.ident == "L1Cache":
-            if not contains_sequencer:
-                self.error("The L1Cache controller must include the sequencer " \
-                           "configuration parameter")
+            if re.compile("sequencer").search(param.ident):
+                code('m_${{param.ident}}_ptr->setController(this);')
+            
+        for var in self.objects:
+            if var.ident.find("mandatoryQueue") >= 0:
+                code('''
+m_${{var.ident}}_ptr = new ${{var.type.c_ident}}();
+m_${{var.ident}}_ptr->setReceiver(this);
+''')
 
-            code('''
-m_sequencer_ptr->setController(this);
+        code('''
+
+for (int state = 0; state < ${ident}_State_NUM; state++) {
+    for (int event = 0; event < ${ident}_Event_NUM; event++) {
+        m_possible[state][event] = false;
+        m_counters[state][event] = 0;
+    }
+}
+for (int event = 0; event < ${ident}_Event_NUM; event++) {
+    m_event_counters[event] = 0;
+}
 ''')
-        #
-        # For the DMA controller, pass the sequencer a pointer to the
-        # controller.
-        #
-        if self.ident == "DMA":
-            if not contains_sequencer:
-                self.error("The DMA controller must include the sequencer " \
-                           "configuration parameter")
+        code.dedent()
+        code('''
+}
+
+void
+$c_ident::setNetQueue(const std::string& name, MessageBuffer *b)
+{
+    MachineType machine_type = string_to_MachineType("${{self.ident}}");
+    int base M5_VAR_USED = MachineType_base_number(machine_type);
 
-            code('''
-m_dma_sequencer_ptr->setController(this);
 ''')
-            
-        code('m_num_controllers++;')
-        for var in self.objects:
-            if var.ident.find("mandatoryQueue") >= 0:
-                code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();')
+        code.indent()
+
+        # set for maintaining the vnet, direction pairs already seen for this
+        # machine.  This map helps in implementing the check for avoiding
+        # multiple message buffers being mapped to the same vnet.
+        vnet_dir_set = set()
+
+        for var in self.config_parameters:
+            if "network" in var:
+                vtype = var.type_ast.type
+                vid = "m_%s_ptr" % var.ident
+
+                code('''
+if ("${{var.ident}}" == name) {
+    $vid = b;
+    assert($vid != NULL);
+''')
+                code.indent()
+                # Network port object
+                network = var["network"]
+                ordered =  var["ordered"]
+
+                if "virtual_network" in var:
+                    vnet = var["virtual_network"]
+                    vnet_type = var["vnet_type"]
+
+                    assert (vnet, network) not in vnet_dir_set
+                    vnet_dir_set.add((vnet,network))
+
+                    code('''
+m_net_ptr->set${network}NetQueue(m_version + base, $ordered, $vnet,
+                                 "$vnet_type", b);
+''')
+                # Set the end
+                if network == "To":
+                    code('$vid->setSender(this);')
+                else:
+                    code('$vid->setReceiver(this);')
+
+                # Set ordering
+                code('$vid->setOrdering(${{var["ordered"]}});')
+
+                # Set randomization
+                if "random" in var:
+                    # A buffer
+                    code('$vid->setRandomization(${{var["random"]}});')
+
+                # Set Priority
+                if "rank" in var:
+                    code('$vid->setPriority(${{var["rank"]}})')
+
+                # Set buffer size
+                code('$vid->resize(m_buffer_size);')
+
+                if "recycle_latency" in var:
+                    code('$vid->setRecycleLatency( ' \
+                         'Cycles(${{var["recycle_latency"]}}));')
+                else:
+                    code('$vid->setRecycleLatency(m_recycle_latency);')
+
+                # set description (may be overriden later by port def)
+                code('''
+$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.ident}}]");
+''')
+                code.dedent()
+                code('}\n')
 
         code.dedent()
         code('''
 }
 
-void $c_ident::init()
+void
+$c_ident::init()
 {
-    m_machineID.type = MachineType_${ident};
-    m_machineID.num = m_version;
+    // initialize objects
 
-    // Objects
-    s_profiler.setVersion(m_version);
 ''')
 
         code.indent()
+
         for var in self.objects:
             vtype = var.type
-            vid = "m_%s_ptr" % var.c_ident
+            vid = "m_%s_ptr" % var.ident
             if "network" not in var:
                 # Not a network port object
                 if "primitive" in vtype:
@@ -423,34 +632,24 @@ void $c_ident::init()
                         code('(*$vid) = ${{var["default"]}};')
                 else:
                     # Normal Object
-                    # added by SS
-                    if "factory" in var:
-                        code('$vid = ${{var["factory"]}};')
-                    elif var.ident.find("mandatoryQueue") < 0:
-                        th = var.get("template_hack", "")
+                    if var.ident.find("mandatoryQueue") < 0:
+                        th = var.get("template", "")
                         expr = "%s  = new %s%s" % (vid, vtype.c_ident, th)
-
                         args = ""
                         if "non_obj" not in vtype and not vtype.isEnumeration:
-                            if expr.find("TBETable") >= 0:
-                                args = "m_number_of_TBEs"
-                            else:
-                                args = var.get("constructor_hack", "")
-                            args = "(%s)" % args
-
-                        code('$expr$args;')
-                    else:
-                        code(';')
+                            args = var.get("constructor", "")
+                        code('$expr($args);')
 
                     code('assert($vid != NULL);')
 
                     if "default" in var:
-                        code('(*$vid) = ${{var["default"]}}; // Object default')
+                        code('*$vid = ${{var["default"]}}; // Object default')
                     elif "default" in vtype:
-                        code('(*$vid) = ${{vtype["default"]}}; // Type ${{vtype.ident}} default')
+                        comment = "Type %s default" % vtype.ident
+                        code('*$vid = ${{vtype["default"]}}; // $comment')
 
                     # Set ordering
-                    if "ordered" in var and "trigger_queue" not in var:
+                    if "ordered" in var:
                         # A buffer
                         code('$vid->setOrdering(${{var["ordered"]}});')
 
@@ -460,59 +659,40 @@ void $c_ident::init()
                         code('$vid->setRandomization(${{var["random"]}});')
 
                     # Set Priority
-                    if vtype.isBuffer and \
-                           "rank" in var and "trigger_queue" not in var:
+                    if vtype.isBuffer and "rank" in var:
                         code('$vid->setPriority(${{var["rank"]}});')
-            else:
-                # Network port object
-                network = var["network"]
-                ordered =  var["ordered"]
-                vnet = var["virtual_network"]
-
-                assert var.machine is not None
-                code('''
-$vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string_to_MachineType("${{var.machine.ident}}")), $ordered, $vnet);
-''')
-
-                code('assert($vid != NULL);')
-
-                # Set ordering
-                if "ordered" in var:
-                    # A buffer
-                    code('$vid->setOrdering(${{var["ordered"]}});')
-
-                # Set randomization
-                if "random" in var:
-                    # A buffer
-                    code('$vid->setRandomization(${{var["random"]}})')
-
-                # Set Priority
-                if "rank" in var:
-                    code('$vid->setPriority(${{var["rank"]}})')
 
-                # Set buffer size
-                if vtype.isBuffer:
-                    code('''
-if (m_buffer_size > 0) {
-    $vid->setSize(m_buffer_size);
-}
-''')
+                    # Set sender and receiver for trigger queue
+                    if var.ident.find("triggerQueue") >= 0:
+                        code('$vid->setSender(this);')
+                        code('$vid->setReceiver(this);')
+                    elif vtype.c_ident == "TimerTable":
+                        code('$vid->setClockObj(this);')
+                    elif var.ident.find("optionalQueue") >= 0:
+                        code('$vid->setSender(this);')
+                        code('$vid->setReceiver(this);')
+
+            if vtype.isBuffer:
+                if "recycle_latency" in var:
+                    code('$vid->setRecycleLatency( ' \
+                         'Cycles(${{var["recycle_latency"]}}));')
+                else:
+                    code('$vid->setRecycleLatency(m_recycle_latency);')
 
-                # set description (may be overriden later by port def)
-                code('$vid->setDescription("[Version " + int_to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");')
+        # Set the prefetchers
+        code()
+        for prefetcher in self.prefetchers:
+            code('${{prefetcher.code}}.setController(this);')
 
-        # Set the queue consumers
-        code.insert_newline()
+        code()
         for port in self.in_ports:
+            # Set the queue consumers
             code('${{port.code}}.setConsumer(this);')
-
-        # Set the queue descriptions
-        code.insert_newline()
-        for port in self.in_ports:
-            code('${{port.code}}.setDescription("[Version " + int_to_string(m_version) + ", $ident, $port]");')
+            # Set the queue descriptions
+            code('${{port.code}}.setDescription("[Version " + to_string(m_version) + ", $ident, $port]");')
 
         # Initialize the transition profiling
-        code.insert_newline()
+        code()
         for trans in self.transitions:
             # Figure out if we stall
             stall = False
@@ -524,148 +704,395 @@ if (m_buffer_size > 0) {
             if not stall:
                 state = "%s_State_%s" % (self.ident, trans.state.ident)
                 event = "%s_Event_%s" % (self.ident, trans.event.ident)
-                code('s_profiler.possibleTransition($state, $event);')
-
-        # added by SS to initialize recycle_latency of message buffers
-        for buf in self.message_buffer_names:
-            code("$buf->setRecycleLatency(m_recycle_latency);")
+                code('possibleTransition($state, $event);')
 
         code.dedent()
-        code('}')
+        code('''
+    AbstractController::init();
+    resetStats();
+}
+''')
 
-        has_mandatory_q = False
+        mq_ident = "NULL"
         for port in self.in_ports:
             if port.code.find("mandatoryQueue_ptr") >= 0:
-                has_mandatory_q = True
+                mq_ident = "m_mandatoryQueue_ptr"
 
-        if has_mandatory_q:
-            mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident
-        else:
-            mq_ident = "NULL"
+        seq_ident = "NULL"
+        for param in self.config_parameters:
+            if param.ident == "sequencer":
+                assert(param.pointer)
+                seq_ident = "m_%s_ptr" % param.ident
 
         code('''
-int $c_ident::getNumControllers() {
-    return m_num_controllers;
+
+void
+$c_ident::regStats()
+{
+    AbstractController::regStats();
+
+    if (m_version == 0) {
+        for (${ident}_Event event = ${ident}_Event_FIRST;
+             event < ${ident}_Event_NUM; ++event) {
+            Stats::Vector *t = new Stats::Vector();
+            t->init(m_num_controllers);
+            t->name(g_system_ptr->name() + ".${c_ident}." +
+                ${ident}_Event_to_string(event));
+            t->flags(Stats::pdf | Stats::total | Stats::oneline |
+                     Stats::nozero);
+
+            eventVec.push_back(t);
+        }
+
+        for (${ident}_State state = ${ident}_State_FIRST;
+             state < ${ident}_State_NUM; ++state) {
+
+            transVec.push_back(std::vector<Stats::Vector *>());
+
+            for (${ident}_Event event = ${ident}_Event_FIRST;
+                 event < ${ident}_Event_NUM; ++event) {
+
+                Stats::Vector *t = new Stats::Vector();
+                t->init(m_num_controllers);
+                t->name(g_system_ptr->name() + ".${c_ident}." +
+                        ${ident}_State_to_string(state) +
+                        "." + ${ident}_Event_to_string(event));
+
+                t->flags(Stats::pdf | Stats::total | Stats::oneline |
+                         Stats::nozero);
+                transVec[state].push_back(t);
+            }
+        }
+    }
 }
 
-MessageBuffer* $c_ident::getMandatoryQueue() const {
-    return $mq_ident;
+void
+$c_ident::collateStats()
+{
+    for (${ident}_Event event = ${ident}_Event_FIRST;
+         event < ${ident}_Event_NUM; ++event) {
+        for (unsigned int i = 0; i < m_num_controllers; ++i) {
+            std::map<uint32_t, AbstractController *>::iterator it =
+                                g_abs_controls[MachineType_${ident}].find(i);
+            assert(it != g_abs_controls[MachineType_${ident}].end());
+            (*eventVec[event])[i] =
+                (($c_ident *)(*it).second)->getEventCount(event);
+        }
+    }
+
+    for (${ident}_State state = ${ident}_State_FIRST;
+         state < ${ident}_State_NUM; ++state) {
+
+        for (${ident}_Event event = ${ident}_Event_FIRST;
+             event < ${ident}_Event_NUM; ++event) {
+
+            for (unsigned int i = 0; i < m_num_controllers; ++i) {
+                std::map<uint32_t, AbstractController *>::iterator it =
+                                g_abs_controls[MachineType_${ident}].find(i);
+                assert(it != g_abs_controls[MachineType_${ident}].end());
+                (*transVec[state][event])[i] =
+                    (($c_ident *)(*it).second)->getTransitionCount(state, event);
+            }
+        }
+    }
 }
 
-const int & $c_ident::getVersion() const{
-    return m_version;
+void
+$c_ident::countTransition(${ident}_State state, ${ident}_Event event)
+{
+    assert(m_possible[state][event]);
+    m_counters[state][event]++;
+    m_event_counters[event]++;
+}
+void
+$c_ident::possibleTransition(${ident}_State state,
+                             ${ident}_Event event)
+{
+    m_possible[state][event] = true;
 }
 
-const string $c_ident::toString() const{
-    return "$c_ident";
+uint64
+$c_ident::getEventCount(${ident}_Event event)
+{
+    return m_event_counters[event];
 }
 
-const string $c_ident::getName() const{
-    return m_name;
+bool
+$c_ident::isPossible(${ident}_State state, ${ident}_Event event)
+{
+    return m_possible[state][event];
 }
-const MachineType $c_ident::getMachineType() const{
-    return MachineType_${ident};
+
+uint64
+$c_ident::getTransitionCount(${ident}_State state,
+                             ${ident}_Event event)
+{
+    return m_counters[state][event];
 }
 
-void $c_ident::blockOnQueue(Address addr, MessageBuffer* port) {
-    m_is_blocking = true;
-    m_block_map[addr] = port;
+int
+$c_ident::getNumControllers()
+{
+    return m_num_controllers;
 }
-void $c_ident::unblock(Address addr) {
-    m_block_map.erase(addr);
-    if (m_block_map.size() == 0) {
-       m_is_blocking = false;
-    }
+
+MessageBuffer*
+$c_ident::getMandatoryQueue() const
+{
+    return $mq_ident;
 }
 
-void $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; }
+Sequencer*
+$c_ident::getSequencer() const
+{
+    return $seq_ident;
+}
+
+void
+$c_ident::print(ostream& out) const
+{
+    out << "[$c_ident " << m_version << "]";
+}
 
-void $c_ident::printConfig(ostream& out) const {
-    out << "$c_ident config: " << m_name << endl;
-    out << "  version: " << m_version << endl;
-    for (map<string, string>::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) {
-        out << "  " << (*it).first << ": " << (*it).second << endl;
+void $c_ident::resetStats()
+{
+    for (int state = 0; state < ${ident}_State_NUM; state++) {
+        for (int event = 0; event < ${ident}_Event_NUM; event++) {
+            m_counters[state][event] = 0;
+        }
     }
+
+    for (int event = 0; event < ${ident}_Event_NUM; event++) {
+        m_event_counters[event] = 0;
+    }
+
+    AbstractController::resetStats();
 }
+''')
+
+        if self.EntryType != None:
+            code('''
 
-void $c_ident::printStats(ostream& out) const {
+// Set and Reset for cache_entry variable
+void
+$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry)
+{
+  m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry;
+}
+
+void
+$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr)
+{
+  m_cache_entry_ptr = 0;
+}
 ''')
-        #
-        # Cache and Memory Controllers have specific profilers associated with
-        # them.  Print out these stats before dumping state transition stats.
-        #
-        for param in self.config_parameters:
-            if param.type_ast.type.ident == "CacheMemory" or \
-                   param.type_ast.type.ident == "MemoryControl":
-                assert(param.pointer)
-                code('    m_${{param.ident}}_ptr->printStats(out);')
 
-        code('''
-    s_profiler.dumpStats(out);
+        if self.TBEType != None:
+            code('''
+
+// Set and Reset for tbe variable
+void
+$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe)
+{
+  m_tbe_ptr = m_new_tbe;
 }
 
-void $c_ident::clearStats() {
+void
+$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr)
+{
+  m_tbe_ptr = NULL;
+}
+''')
+
+        code('''
+
+void
+$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr)
+{
 ''')
         #
-        # Cache and Memory Controllers have specific profilers associated with
-        # them.  These stats must be cleared too.
+        # Record cache contents for all associated caches.
         #
+        code.indent()
         for param in self.config_parameters:
-            if param.type_ast.type.ident == "CacheMemory" or \
-                   param.type_ast.type.ident == "MemoryControl":
+            if param.type_ast.type.ident == "CacheMemory":
                 assert(param.pointer)
-                code('    m_${{param.ident}}_ptr->clearStats();')
+                code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);')
 
+        code.dedent()
         code('''
-    s_profiler.clearStats();
 }
 
 // Actions
 ''')
+        if self.TBEType != None and self.EntryType != None:
+            for action in self.actions.itervalues():
+                if "c_code" not in action:
+                 continue
 
-        for action in self.actions.itervalues():
-            if "c_code" not in action:
-                continue
+                code('''
+/** \\brief ${{action.desc}} */
+void
+$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr)
+{
+    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
+    ${{action["c_code"]}}
+}
 
-            code('''
+''')
+        elif self.TBEType != None:
+            for action in self.actions.itervalues():
+                if "c_code" not in action:
+                 continue
+
+                code('''
 /** \\brief ${{action.desc}} */
-void $c_ident::${{action.ident}}(const Address& addr)
+void
+$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr)
 {
-    DEBUG_MSG(GENERATED_COMP, HighPrio, "executing");
+    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
     ${{action["c_code"]}}
 }
 
 ''')
+        elif self.EntryType != None:
+            for action in self.actions.itervalues():
+                if "c_code" not in action:
+                 continue
+
+                code('''
+/** \\brief ${{action.desc}} */
+void
+$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr)
+{
+    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
+    ${{action["c_code"]}}
+}
+
+''')
+        else:
+            for action in self.actions.itervalues():
+                if "c_code" not in action:
+                 continue
+
+                code('''
+/** \\brief ${{action.desc}} */
+void
+$c_ident::${{action.ident}}(const Address& addr)
+{
+    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
+    ${{action["c_code"]}}
+}
+
+''')
+        for func in self.functions:
+            code(func.generateCode())
+
+        # Function for functional reads from messages buffered in the controller
+        code('''
+bool
+$c_ident::functionalReadBuffers(PacketPtr& pkt)
+{
+''')
+        for var in self.objects:
+            vtype = var.type
+            if vtype.isBuffer:
+                vid = "m_%s_ptr" % var.ident
+                code('if ($vid->functionalRead(pkt)) { return true; }')
+
+        for var in self.config_parameters:
+            vtype = var.type_ast.type
+            if vtype.isBuffer:
+                vid = "m_%s_ptr" % var.ident
+                code('if ($vid->functionalRead(pkt)) { return true; }')
+
+        code('''
+                return false;
+}
+''')
+
+        # Function for functional writes to messages buffered in the controller
+        code('''
+uint32_t
+$c_ident::functionalWriteBuffers(PacketPtr& pkt)
+{
+    uint32_t num_functional_writes = 0;
+''')
+        for var in self.objects:
+            vtype = var.type
+            if vtype.isBuffer:
+                vid = "m_%s_ptr" % var.ident
+                code('num_functional_writes += $vid->functionalWrite(pkt);')
+
+        for var in self.config_parameters:
+            vtype = var.type_ast.type
+            if vtype.isBuffer:
+                vid = "m_%s_ptr" % var.ident
+                code('num_functional_writes += $vid->functionalWrite(pkt);')
+
+        code('''
+    return num_functional_writes;
+}
+''')
+
         code.write(path, "%s.cc" % c_ident)
 
-    def printCWakeup(self, path):
+    def printCWakeup(self, path, includes):
         '''Output the wakeup loop for the events'''
 
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
 
+        outputRequest_types = True
+        if len(self.request_types) == 0:
+            outputRequest_types = False
+
         code('''
 // Auto generated C++ code started by $__file__:$__line__
 // ${ident}: ${{self.short}}
 
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cassert>
+
+#include "base/misc.hh"
+#include "debug/RubySlicc.hh"
 #include "mem/protocol/${ident}_Controller.hh"
-#include "mem/protocol/${ident}_State.hh"
 #include "mem/protocol/${ident}_Event.hh"
+#include "mem/protocol/${ident}_State.hh"
+''')
+
+        if outputRequest_types:
+            code('''#include "mem/protocol/${ident}_RequestType.hh"''')
+
+        code('''
 #include "mem/protocol/Types.hh"
+#include "mem/ruby/common/Global.hh"
 #include "mem/ruby/system/System.hh"
+''')
 
-void ${ident}_Controller::wakeup()
-{
 
+        for include_path in includes:
+            code('#include "${{include_path}}"')
+
+        code('''
+
+using namespace std;
+
+void
+${ident}_Controller::wakeup()
+{
     int counter = 0;
     while (true) {
         // Some cases will put us into an infinite loop without this limit
         assert(counter <= m_transitions_per_cycle);
         if (counter == m_transitions_per_cycle) {
-            g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we\'re fully utilized
-            g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again
+            // Count how often we are fully utilized
+            m_fully_busy_cycles++;
+
+            // Wakeup in another cycle and try again
+            scheduleEvent(Cycles(1));
             break;
         }
 ''')
@@ -678,6 +1105,10 @@ void ${ident}_Controller::wakeup()
         for port in self.in_ports:
             code.indent()
             code('// ${ident}InPort $port')
+            if port.pairs.has_key("rank"):
+                code('m_cur_in_port = ${{port.pairs["rank"]}};')
+            else:
+                code('m_cur_in_port = 0;')
             code('${{port["c_code_in_port"]}}')
             code.dedent()
 
@@ -696,18 +1127,24 @@ void ${ident}_Controller::wakeup()
     def printCSwitch(self, path):
         '''Output switch statement for transition table'''
 
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
 
         code('''
 // Auto generated C++ code started by $__file__:$__line__
 // ${ident}: ${{self.short}}
 
-#include "mem/ruby/common/Global.hh"
+#include <cassert>
+
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "debug/ProtocolTrace.hh"
+#include "debug/RubyGenerated.hh"
 #include "mem/protocol/${ident}_Controller.hh"
-#include "mem/protocol/${ident}_State.hh"
 #include "mem/protocol/${ident}_Event.hh"
+#include "mem/protocol/${ident}_State.hh"
 #include "mem/protocol/Types.hh"
+#include "mem/ruby/common/Global.hh"
 #include "mem/ruby/system/System.hh"
 
 #define HASH_FUN(state, event)  ((int(state)*${ident}_Event_NUM)+int(event))
@@ -715,58 +1152,119 @@ void ${ident}_Controller::wakeup()
 #define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str())
 #define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str(""))
 
-TransitionResult ${ident}_Controller::doTransition(${ident}_Event event, ${ident}_State state, const Address& addr
-)
+TransitionResult
+${ident}_Controller::doTransition(${ident}_Event event,
+''')
+        if self.EntryType != None:
+            code('''
+                                  ${{self.EntryType.c_ident}}* m_cache_entry_ptr,
+''')
+        if self.TBEType != None:
+            code('''
+                                  ${{self.TBEType.c_ident}}* m_tbe_ptr,
+''')
+        code('''
+                                  const Address addr)
 {
-    ${ident}_State next_state = state;
-
-    DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
-    DEBUG_MSG(GENERATED_COMP, MedPrio, *this);
-    DEBUG_EXPR(GENERATED_COMP, MedPrio, g_eventQueue_ptr->getTime());
-    DEBUG_EXPR(GENERATED_COMP, MedPrio,state);
-    DEBUG_EXPR(GENERATED_COMP, MedPrio,event);
-    DEBUG_EXPR(GENERATED_COMP, MedPrio,addr);
-
-    TransitionResult result = doTransitionWorker(event, state, next_state, addr);
-
-    if (result == TransitionResult_Valid) {
-        DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state);
-        DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
-        s_profiler.countTransition(state, event);
-        if (Debug::getProtocolTrace()) {
-            g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
-                    ${ident}_State_to_string(state),
-                    ${ident}_Event_to_string(event),
-                    ${ident}_State_to_string(next_state), GET_TRANSITION_COMMENT());
-        }
+''')
+        code.indent()
+
+        if self.TBEType != None and self.EntryType != None:
+            code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);')
+        elif self.TBEType != None:
+            code('${ident}_State state = getState(m_tbe_ptr, addr);')
+        elif self.EntryType != None:
+            code('${ident}_State state = getState(m_cache_entry_ptr, addr);')
+        else:
+            code('${ident}_State state = getState(addr);')
+
+        code('''
+${ident}_State next_state = state;
+
+DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n",
+        *this, curCycle(), ${ident}_State_to_string(state),
+        ${ident}_Event_to_string(event), addr);
+
+TransitionResult result =
+''')
+        if self.TBEType != None and self.EntryType != None:
+            code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);')
+        elif self.TBEType != None:
+            code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);')
+        elif self.EntryType != None:
+            code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);')
+        else:
+            code('doTransitionWorker(event, state, next_state, addr);')
+
+        code('''
+
+if (result == TransitionResult_Valid) {
+    DPRINTF(RubyGenerated, "next_state: %s\\n",
+            ${ident}_State_to_string(next_state));
+    countTransition(state, event);
+
+    DPRINTFR(ProtocolTrace, "%15d %3s %10s%20s %6s>%-6s %s %s\\n",
+             curTick(), m_version, "${ident}",
+             ${ident}_Event_to_string(event),
+             ${ident}_State_to_string(state),
+             ${ident}_State_to_string(next_state),
+             addr, GET_TRANSITION_COMMENT());
+
     CLEAR_TRANSITION_COMMENT();
-    ${ident}_setState(addr, next_state);
-
-    } else if (result == TransitionResult_ResourceStall) {
-        if (Debug::getProtocolTrace()) {
-            g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
-                   ${ident}_State_to_string(state),
-                   ${ident}_Event_to_string(event),
-                   ${ident}_State_to_string(next_state),
-                   "Resource Stall");
-        }
-    } else if (result == TransitionResult_ProtocolStall) {
-        DEBUG_MSG(GENERATED_COMP, HighPrio, "stalling");
-        DEBUG_NEWLINE(GENERATED_COMP, MedPrio);
-        if (Debug::getProtocolTrace()) {
-            g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr,
-                   ${ident}_State_to_string(state),
-                   ${ident}_Event_to_string(event),
-                   ${ident}_State_to_string(next_state),
-                   "Protocol Stall");
-        }
-    }
+''')
+        if self.TBEType != None and self.EntryType != None:
+            code('setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);')
+            code('setAccessPermission(m_cache_entry_ptr, addr, next_state);')
+        elif self.TBEType != None:
+            code('setState(m_tbe_ptr, addr, next_state);')
+            code('setAccessPermission(addr, next_state);')
+        elif self.EntryType != None:
+            code('setState(m_cache_entry_ptr, addr, next_state);')
+            code('setAccessPermission(m_cache_entry_ptr, addr, next_state);')
+        else:
+            code('setState(addr, next_state);')
+            code('setAccessPermission(addr, next_state);')
 
-    return result;
+        code('''
+} else if (result == TransitionResult_ResourceStall) {
+    DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n",
+             curTick(), m_version, "${ident}",
+             ${ident}_Event_to_string(event),
+             ${ident}_State_to_string(state),
+             ${ident}_State_to_string(next_state),
+             addr, "Resource Stall");
+} else if (result == TransitionResult_ProtocolStall) {
+    DPRINTF(RubyGenerated, "stalling\\n");
+    DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\\n",
+             curTick(), m_version, "${ident}",
+             ${ident}_Event_to_string(event),
+             ${ident}_State_to_string(state),
+             ${ident}_State_to_string(next_state),
+             addr, "Protocol Stall");
 }
 
-TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr
-)
+return result;
+''')
+        code.dedent()
+        code('''
+}
+
+TransitionResult
+${ident}_Controller::doTransitionWorker(${ident}_Event event,
+                                        ${ident}_State state,
+                                        ${ident}_State& next_state,
+''')
+
+        if self.TBEType != None:
+            code('''
+                                        ${{self.TBEType.c_ident}}*& m_tbe_ptr,
+''')
+        if self.EntryType != None:
+                  code('''
+                                        ${{self.EntryType.c_ident}}*& m_cache_entry_ptr,
+''')
+        code('''
+                                        const Address& addr)
 {
     switch(HASH_FUN(state, event)) {
 ''')
@@ -778,26 +1276,33 @@ TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, $
             case_string = "%s_State_%s, %s_Event_%s" % \
                 (self.ident, trans.state.ident, self.ident, trans.event.ident)
 
-            case = code_formatter()
+            case = self.symtab.codeFormatter()
             # Only set next_state if it changes
             if trans.state != trans.nextState:
                 ns_ident = trans.nextState.ident
                 case('next_state = ${ident}_State_${ns_ident};')
 
             actions = trans.actions
+            request_types = trans.request_types
 
             # Check for resources
             case_sorter = []
             res = trans.resources
             for key,val in res.iteritems():
-                if key.type.ident != "DNUCAStopTable":
-                    val = '''
-if (!%s.areNSlotsAvailable(%s)) {
+                val = '''
+if (!%s.areNSlotsAvailable(%s))
     return TransitionResult_ResourceStall;
-}
 ''' % (key.code, val)
                 case_sorter.append(val)
 
+            # Check all of the request_types for resource constraints
+            for request_type in request_types:
+                val = '''
+if (!checkResourceAvailable(%s_RequestType_%s, addr)) {
+    return TransitionResult_ResourceStall;
+}
+''' % (self.ident, request_type.ident)
+                case_sorter.append(val)
 
             # Emit the code sequences in a sorted order.  This makes the
             # output deterministic (without this the output order can vary
@@ -805,6 +1310,10 @@ if (!%s.areNSlotsAvailable(%s)) {
             for c in sorted(case_sorter):
                 case("$c")
 
+            # Record access types for this transition
+            for request_type in request_types:
+                case('recordRequestType(${ident}_RequestType_${{request_type.ident}}, addr);')
+
             # Figure out if we stall
             stall = False
             for action in actions:
@@ -815,8 +1324,18 @@ if (!%s.areNSlotsAvailable(%s)) {
             if stall:
                 case('return TransitionResult_ProtocolStall;')
             else:
-                for action in actions:
-                    case('${{action.ident}}(addr);')
+                if self.TBEType != None and self.EntryType != None:
+                    for action in actions:
+                        case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);')
+                elif self.TBEType != None:
+                    for action in actions:
+                        case('${{action.ident}}(m_tbe_ptr, addr);')
+                elif self.EntryType != None:
+                    for action in actions:
+                        case('${{action.ident}}(m_cache_entry_ptr, addr);')
+                else:
+                    for action in actions:
+                        case('${{action.ident}}(addr);')
                 case('return TransitionResult_Valid;')
 
             case = str(case)
@@ -834,141 +1353,32 @@ if (!%s.areNSlotsAvailable(%s)) {
             # the same code
             for trans in transitions:
                 code('  case HASH_FUN($trans):')
-            code('  {')
-            code('    $case')
-            code('  }')
+            code('    $case\n')
 
         code('''
       default:
-        WARN_EXPR(m_version);
-        WARN_EXPR(g_eventQueue_ptr->getTime());
-        WARN_EXPR(addr);
-        WARN_EXPR(event);
-        WARN_EXPR(state);
-        ERROR_MSG(\"Invalid transition\");
+        fatal("Invalid transition\\n"
+              "%s time: %d addr: %s event: %s state: %s\\n",
+              name(), curCycle(), addr, event, state);
     }
+
     return TransitionResult_Valid;
 }
 ''')
         code.write(path, "%s_Transitions.cc" % self.ident)
 
-    def printProfilerHH(self, path):
-        code = code_formatter()
-        ident = self.ident
-
-        code('''
-// Auto generated C++ code started by $__file__:$__line__
-// ${ident}: ${{self.short}}
-
-#ifndef ${ident}_PROFILER_H
-#define ${ident}_PROFILER_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/protocol/${ident}_State.hh"
-#include "mem/protocol/${ident}_Event.hh"
-
-class ${ident}_Profiler {
-  public:
-    ${ident}_Profiler();
-    void setVersion(int version);
-    void countTransition(${ident}_State state, ${ident}_Event event);
-    void possibleTransition(${ident}_State state, ${ident}_Event event);
-    void dumpStats(ostream& out) const;
-    void clearStats();
-
-  private:
-    int m_counters[${ident}_State_NUM][${ident}_Event_NUM];
-    int m_event_counters[${ident}_Event_NUM];
-    bool m_possible[${ident}_State_NUM][${ident}_Event_NUM];
-    int m_version;
-};
-
-#endif // ${ident}_PROFILER_H
-''')
-        code.write(path, "%s_Profiler.hh" % self.ident)
-
-    def printProfilerCC(self, path):
-        code = code_formatter()
-        ident = self.ident
-
-        code('''
-// Auto generated C++ code started by $__file__:$__line__
-// ${ident}: ${{self.short}}
-
-#include "mem/protocol/${ident}_Profiler.hh"
-
-${ident}_Profiler::${ident}_Profiler()
-{
-    for (int state = 0; state < ${ident}_State_NUM; state++) {
-        for (int event = 0; event < ${ident}_Event_NUM; event++) {
-            m_possible[state][event] = false;
-            m_counters[state][event] = 0;
-        }
-    }
-    for (int event = 0; event < ${ident}_Event_NUM; event++) {
-        m_event_counters[event] = 0;
-    }
-}
-void ${ident}_Profiler::setVersion(int version)
-{
-    m_version = version;
-}
-void ${ident}_Profiler::clearStats()
-{
-    for (int state = 0; state < ${ident}_State_NUM; state++) {
-        for (int event = 0; event < ${ident}_Event_NUM; event++) {
-            m_counters[state][event] = 0;
-        }
-    }
-
-    for (int event = 0; event < ${ident}_Event_NUM; event++) {
-        m_event_counters[event] = 0;
-    }
-}
-void ${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event)
-{
-    assert(m_possible[state][event]);
-    m_counters[state][event]++;
-    m_event_counters[event]++;
-}
-void ${ident}_Profiler::possibleTransition(${ident}_State state, ${ident}_Event event)
-{
-    m_possible[state][event] = true;
-}
-void ${ident}_Profiler::dumpStats(ostream& out) const
-{
-    out << " --- ${ident} " << m_version << " ---" << endl;
-    out << " - Event Counts -" << endl;
-    for (int event = 0; event < ${ident}_Event_NUM; event++) {
-        int count = m_event_counters[event];
-        out << (${ident}_Event) event << "  " << count << endl;
-    }
-    out << endl;
-    out << " - Transitions -" << endl;
-    for (int state = 0; state < ${ident}_State_NUM; state++) {
-        for (int event = 0; event < ${ident}_Event_NUM; event++) {
-            if (m_possible[state][event]) {
-                int count = m_counters[state][event];
-                out << (${ident}_State) state << "  " << (${ident}_Event) event << "  " << count;
-                if (count == 0) {
-                    out << " <-- ";
-                }
-                out << endl;
-            }
-        }
-        out << endl;
-    }
-}
-''')
-        code.write(path, "%s_Profiler.cc" % self.ident)
 
     # **************************
     # ******* HTML Files *******
     # **************************
-    def frameRef(self, click_href, click_target, over_href, over_target_num,
-                 text):
-        code = code_formatter(fix_newlines=False)
-        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>""")
+    def frameRef(self, click_href, click_target, over_href, over_num, text):
+        code = self.symtab.codeFormatter(fix_newlines=False)
+        code("""<A href=\"$click_href\" target=\"$click_target\" onmouseover=\"
+    if (parent.frames[$over_num].location != parent.location + '$over_href') {
+        parent.frames[$over_num].location='$over_href'
+    }\">
+    ${{html.formatShorthand(text)}}
+    </A>""")
         return str(code)
 
     def writeHTMLFiles(self, path):
@@ -998,10 +1408,11 @@ void ${ident}_Profiler::dumpStats(ostream& out) const
             code.write(path, name)
 
     def printHTMLTransitions(self, path, active_state):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
 
         code('''
-<HTML><BODY link="blue" vlink="blue">
+<HTML>
+<BODY link="blue" vlink="blue">
 
 <H1 align="center">${{html.formatShorthand(self.short)}}:
 ''')
@@ -1085,13 +1496,12 @@ void ${ident}_Profiler::dumpStats(ostream& out) const
                 else:
                     color = "white"
 
-                fix = code.nofix()
                 code('<TD bgcolor=$color>')
                 for action in trans.actions:
                     href = "%s_action_%s.html" % (self.ident, action.ident)
                     ref = self.frameRef(href, "Status", href, "1",
                                         action.short)
-                    code('  $ref\n')
+                    code('  $ref')
                 if next != state:
                     if trans.actions:
                         code('/')
@@ -1099,8 +1509,7 @@ void ${ident}_Profiler::dumpStats(ostream& out) const
                     over = "%s_State_%s.html" % (self.ident, next.ident)
                     ref = self.frameRef(click, "Table", over, "1", next.short)
                     code("$ref")
-                code("</TD>\n")
-                code.fix(fix)
+                code("</TD>")
 
             # -- Each row
             if state == active_state:
@@ -1116,6 +1525,7 @@ void ${ident}_Profiler::dumpStats(ostream& out) const
 </TR>
 ''')
         code('''
+<!- Column footer->     
 <TR>
   <TH> </TH>
 ''')