ruby: memory controllers now inherit from an abstract "MemoryControl" class
[gem5.git] / src / mem / slicc / symbols / StateMachine.py
index 0f32cebf6cf4c7cd3b684b8fc9f59324eee8f5fb..8f4676c4221e76c261bf3127f6353b81fe7b3768 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",
+                    "std::string": "String",
+                    "bool": "Bool",
+                    "CacheMemory": "RubyCache",
+                    "WireBuffer": "RubyWireBuffer",
+                    "Sequencer": "RubySequencer",
+                    "DirectoryMemory": "RubyDirectoryMemory",
+                    "MemoryControl": "MemoryControl",
+                    "DMASequencer": "DMASequencer"
+                    }
 
 class StateMachine(Symbol):
     def __init__(self, symtab, ident, location, pairs, config_parameters):
         super(StateMachine, self).__init__(symtab, ident, location, pairs)
         self.table = None
         self.config_parameters = config_parameters
+
         for param in config_parameters:
-            var = Var(symtab, param.name, location, param.type_ast.type,
-                      "m_%s" % param.name, {}, self)
+            if param.pointer:
+                var = Var(symtab, param.name, location, param.type_ast.type,
+                          "(*m_%s_ptr)" % param.name, {}, self)
+            else:
+                var = Var(symtab, param.name, location, param.type_ast.type,
+                          "m_%s" % param.name, {}, self)
             self.symtab.registerSym(param.name, var)
 
         self.states = orderdict()
@@ -48,6 +65,8 @@ class StateMachine(Symbol):
         self.in_ports = []
         self.functions = []
         self.objects = []
+        self.TBEType   = None
+        self.EntryType = None
 
         self.message_buffer_names = []
 
@@ -93,6 +112,21 @@ class StateMachine(Symbol):
     def addObject(self, 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
@@ -131,12 +165,11 @@ class StateMachine(Symbol):
         self.printCWakeup(path)
         self.printProfilerCC(path)
         self.printProfilerHH(path)
-
-        for func in self.functions:
-            func.writeCodeFiles(path)
+        self.printProfileDumperCC(path)
+        self.printProfileDumperHH(path)
 
     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
@@ -153,37 +186,47 @@ class $py_ident(RubyController):
             dflt_str = ''
             if param.default is not None:
                 dflt_str = str(param.default) + ', '
-            code('${{param.name}} = Param.Int(${dflt_str}"")')
+            if 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}"")')
+            else:
+                self.error("Unknown c++ to python class conversion for c++ " \
+                           "type: '%s'. Please update the python_class_map " \
+                           "in StateMachine.py", param.type_ast.type.c_ident)
         code.dedent()
         code.write(path, '%s.py' % py_ident)
         
 
     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/${ident}_ProfileDumper.hh"
+#include "mem/protocol/${ident}_Profiler.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()
@@ -194,11 +237,13 @@ class $py_ident(RubyController):
 
         # for adding information to the protocol debug trace
         code('''
-extern stringstream ${ident}_transitionComment;
+extern std::stringstream ${ident}_transitionComment;
+
+class $c_ident : public AbstractController
+{
+// the coherence checker needs to call isBlockExclusive() and isBlockShared()
+// making the Chip a friend class is an easy way to do this for now
 
-class $c_ident : public AbstractController {
-#ifdef CHECK_COHERENCE
-#endif /* CHECK_COHERENCE */
 public:
     typedef ${c_ident}Params Params;
     $c_ident(const Params *p);
@@ -206,41 +251,87 @@ public:
     void init();
     MessageBuffer* getMandatoryQueue() const;
     const int & getVersion() const;
-    const string toString() const;
-    const string getName() const;
-    const MachineType getMachineType() const;
-    void print(ostream& out) const;
-    void printConfig(ostream& out) const;
+    const std::string toString() const;
+    const std::string getName() const;
+    void stallBuffer(MessageBuffer* buf, Address addr);
+    void wakeUpBuffers(Address addr);
+    void wakeUpAllBuffers();
+    void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; }
+    void print(std::ostream& out) const;
+    void printConfig(std::ostream& out) const;
     void wakeup();
-    void printStats(ostream& out) const { s_profiler.dumpStats(out); }
-    void clearStats() { s_profiler.clearStats(); }
+    void printStats(std::ostream& out) const;
+    void clearStats();
     void blockOnQueue(Address addr, MessageBuffer* port);
     void unblock(Address addr);
+    void recordCacheTrace(int cntrl, CacheRecorder* tr);
+    Sequencer* getSequencer() const;
+
 private:
 ''')
 
         code.indent()
         # added by SS
         for param in self.config_parameters:
-            code('int m_${{param.ident}};')
+            if param.pointer:
+                code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;')
+            else:
+                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;
+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);
+
+std::string m_name;
 int m_transitions_per_cycle;
 int m_buffer_size;
 int m_recycle_latency;
-map< string, string > m_cfg;
+std::map<std::string, std::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;
+std::map<Address, MessageBuffer*> m_block_map;
+typedef std::vector<MessageBuffer*> MsgVecType;
+typedef std::map< Address, MsgVecType* > WaitingBufType;
+WaitingBufType m_waiting_buffers;
+int m_max_in_port_rank;
+int m_cur_in_port_rank;
+static ${ident}_ProfileDumper s_profileDumper;
+${ident}_Profiler m_profiler;
 static int m_num_controllers;
+
 // Internal functions
 ''')
 
@@ -249,18 +340,47 @@ 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);
+''')
+
         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", "")
@@ -271,30 +391,43 @@ static int m_num_controllers;
 
         code.dedent()
         code('};')
-        code('#endif // ${ident}_CONTROLLER_H')
+        code('#endif // __${ident}_CONTROLLER_H__')
         code.write(path, '%s.hh' % c_ident)
 
     def printControllerCC(self, path):
         '''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/slicc_interface/RubySlicc_includes.hh"
 #include "mem/ruby/system/System.hh"
+
+using namespace std;
 ''')
 
         # include object classes
@@ -311,11 +444,13 @@ ${c_ident}Params::create()
     return new $c_ident(this);
 }
 
-
 int $c_ident::m_num_controllers = 0;
+${ident}_ProfileDumper $c_ident::s_profileDumper;
 
+// for adding information to the protocol debug trace
 stringstream ${ident}_transitionComment;
 #define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str)
+
 /** \\brief constructor */
 $c_ident::$c_ident(const Params *p)
     : AbstractController(p)
@@ -325,11 +460,68 @@ $c_ident::$c_ident(const Params *p)
     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_name = "${ident}";
 ''')
+        #
+        # max_port_rank is used to size vectors and thus should be one plus the
+        # largest port rank
+        #
+        max_port_rank = self.in_ports[0].pairs["max_port_rank"] + 1
+        code('    m_max_in_port_rank = $max_port_rank;')
         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.
+        #
+        contains_dma_sequencer = False
+        sequencers = []
         for param in self.config_parameters:
-            code('m_${{param.name}} = p->${{param.name}};')
+            if param.name == "dma_sequencer":
+                contains_dma_sequencer = True
+            elif re.compile("sequencer").search(param.name):
+                sequencers.append(param.name)
+            if param.pointer:
+                code('m_${{param.name}}_ptr = p->${{param.name}};')
+            else:
+                code('m_${{param.name}} = p->${{param.name}};')
 
+        #
+        # 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 sequencers:
+                self.error("The L1Cache controller must include the sequencer " \
+                           "configuration parameter")
+
+            for seq in sequencers:
+                code('''
+m_${{seq}}_ptr->setController(this);
+    ''')
+
+        else:
+            for seq in sequencers:
+                code('''
+m_${{seq}}_ptr->setController(this);
+    ''')
+
+        #
+        # For the DMA controller, pass the sequencer a pointer to the
+        # controller.
+        #
+        if self.ident == "DMA":
+            if not contains_dma_sequencer:
+                self.error("The DMA controller must include the sequencer " \
+                           "configuration parameter")
+
+            code('''
+m_dma_sequencer_ptr->setController(this);
+''')
+            
         code('m_num_controllers++;')
         for var in self.objects:
             if var.ident.find("mandatoryQueue") >= 0:
@@ -339,13 +531,19 @@ $c_ident::$c_ident(const Params *p)
         code('''
 }
 
-void $c_ident::init()
+void
+$c_ident::init()
 {
+    MachineType machine_type;
+    int base;
+
     m_machineID.type = MachineType_${ident};
     m_machineID.num = m_version;
 
-    // Objects
-    s_profiler.setVersion(m_version);
+    // initialize objects
+    m_profiler.setVersion(m_version);
+    s_profileDumper.registerProfiler(&m_profiler);
+
 ''')
 
         code.indent()
@@ -373,18 +571,16 @@ void $c_ident::init()
                                 args = "m_number_of_TBEs"
                             else:
                                 args = var.get("constructor_hack", "")
-                            args = "(%s)" % args
 
-                        code('$expr$args;')
-                    else:
-                        code(';')
+                        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:
@@ -400,15 +596,19 @@ void $c_ident::init()
                     if vtype.isBuffer and \
                            "rank" in var and "trigger_queue" not in var:
                         code('$vid->setPriority(${{var["rank"]}});')
+
             else:
                 # Network port object
                 network = var["network"]
                 ordered =  var["ordered"]
                 vnet = var["virtual_network"]
+                vnet_type = var["vnet_type"]
 
                 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);
+machine_type = string_to_MachineType("${{var.machine.ident}}");
+base = MachineType_base_number(machine_type);
+$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type");
 ''')
 
                 code('assert($vid != NULL);')
@@ -421,7 +621,7 @@ $vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string
                 # Set randomization
                 if "random" in var:
                     # A buffer
-                    code('$vid->setRandomization(${{var["random"]}})')
+                    code('$vid->setRandomization(${{var["random"]}});')
 
                 # Set Priority
                 if "rank" in var:
@@ -431,25 +631,35 @@ $vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string
                 if vtype.isBuffer:
                     code('''
 if (m_buffer_size > 0) {
-    $vid->setSize(m_buffer_size);
+    $vid->resize(m_buffer_size);
 }
 ''')
 
                 # set description (may be overriden later by port def)
-                code('$vid->setDescription("[Version " + int_to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");')
+                code('''
+$vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");
+
+''')
+
+            if vtype.isBuffer:
+                if "recycle_latency" in var:
+                    code('$vid->setRecycleLatency(${{var["recycle_latency"]}});')
+                else:
+                    code('$vid->setRecycleLatency(m_recycle_latency);')
+
 
         # Set the queue consumers
-        code.insert_newline()
+        code()
         for port in self.in_ports:
             code('${{port.code}}.setConsumer(this);')
 
         # Set the queue descriptions
-        code.insert_newline()
+        code()
         for port in self.in_ports:
-            code('${{port.code}}.setDescription("[Version " + int_to_string(m_version) + ", $ident, $port]");')
+            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
@@ -461,11 +671,7 @@ 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('m_profiler.possibleTransition($state, $event);')
 
         code.dedent()
         code('}')
@@ -480,97 +686,343 @@ if (m_buffer_size > 0) {
         else:
             mq_ident = "NULL"
 
+        seq_ident = "NULL"
+        for param in self.config_parameters:
+            if param.name == "sequencer":
+                assert(param.pointer)
+                seq_ident = "m_%s_ptr" % param.name
+
         code('''
-int $c_ident::getNumControllers() {
+int
+$c_ident::getNumControllers()
+{
     return m_num_controllers;
 }
 
-MessageBuffer* $c_ident::getMandatoryQueue() const {
+MessageBuffer*
+$c_ident::getMandatoryQueue() const
+{
     return $mq_ident;
 }
 
-const int & $c_ident::getVersion() const{
+Sequencer*
+$c_ident::getSequencer() const
+{
+    return $seq_ident;
+}
+
+const int &
+$c_ident::getVersion() const
+{
     return m_version;
 }
 
-const string $c_ident::toString() const{
+const string
+$c_ident::toString() const
+{
     return "$c_ident";
 }
 
-const string $c_ident::getName() const{
+const string
+$c_ident::getName() const
+{
     return m_name;
 }
-const MachineType $c_ident::getMachineType() const{
-    return MachineType_${ident};
+
+void
+$c_ident::stallBuffer(MessageBuffer* buf, Address addr)
+{
+    if (m_waiting_buffers.count(addr) == 0) {
+        MsgVecType* msgVec = new MsgVecType;
+        msgVec->resize(m_max_in_port_rank, NULL);
+        m_waiting_buffers[addr] = msgVec;
+    }
+    (*(m_waiting_buffers[addr]))[m_cur_in_port_rank] = buf;
+}
+
+void
+$c_ident::wakeUpBuffers(Address addr)
+{
+    if (m_waiting_buffers.count(addr) > 0) {
+        //
+        // Wake up all possible lower rank (i.e. lower priority) buffers that could
+        // be waiting on this message.
+        //
+        for (int in_port_rank = m_cur_in_port_rank - 1;
+             in_port_rank >= 0;
+             in_port_rank--) {
+            if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) {
+                (*(m_waiting_buffers[addr]))[in_port_rank]->reanalyzeMessages(addr);
+            }
+        }
+        delete m_waiting_buffers[addr];
+        m_waiting_buffers.erase(addr);
+    }
+}
+
+void
+$c_ident::wakeUpAllBuffers()
+{
+    //
+    // Wake up all possible buffers that could be waiting on any message.
+    //
+
+    std::vector<MsgVecType*> wokeUpMsgVecs;
+    
+    if(m_waiting_buffers.size() > 0) {
+        for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin();
+             buf_iter != m_waiting_buffers.end();
+             ++buf_iter) {
+             for (MsgVecType::iterator vec_iter = buf_iter->second->begin();
+                  vec_iter != buf_iter->second->end();
+                  ++vec_iter) {
+                  if (*vec_iter != NULL) {
+                      (*vec_iter)->reanalyzeAllMessages();
+                  }
+             }
+             wokeUpMsgVecs.push_back(buf_iter->second);
+        }
+
+        for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin();
+             wb_iter != wokeUpMsgVecs.end();
+             ++wb_iter) {
+             delete (*wb_iter);
+        }
+
+        m_waiting_buffers.clear();
+    }
 }
 
-void $c_ident::blockOnQueue(Address addr, MessageBuffer* port) {
+void
+$c_ident::blockOnQueue(Address addr, MessageBuffer* port)
+{
     m_is_blocking = true;
     m_block_map[addr] = port;
 }
-void $c_ident::unblock(Address addr) {
+
+void
+$c_ident::unblock(Address addr)
+{
     m_block_map.erase(addr);
     if (m_block_map.size() == 0) {
        m_is_blocking = false;
     }
 }
 
-void $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; }
+void
+$c_ident::print(ostream& out) const
+{
+    out << "[$c_ident " << m_version << "]";
+}
 
-void $c_ident::printConfig(ostream& out) const {
+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;
+    map<string, string>::const_iterator it;
+    for (it = m_cfg.begin(); it != m_cfg.end(); it++)
+        out << "  " << it->first << ": " << it->second << endl;
+}
+
+void
+$c_ident::printStats(ostream& out) const
+{
+''')
+        #
+        # 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 == "DirectoryMemory" or \
+                   param.type_ast.type.ident == "MemoryControl":
+                assert(param.pointer)
+                code('    m_${{param.ident}}_ptr->printStats(out);')
+
+        code('''
+    if (m_version == 0) {
+        s_profileDumper.dumpStats(out);
     }
 }
 
-// Actions
+void $c_ident::clearStats() {
 ''')
+        #
+        # Cache and Memory Controllers have specific profilers associated with
+        # them.  These stats must be cleared too.
+        #
+        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->clearStats();')
 
-        for action in self.actions.itervalues():
-            if "c_code" not in action:
-                continue
+        code('''
+    m_profiler.clearStats();
+}
+''')
 
+        if self.EntryType != None:
             code('''
+
+// 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;
+}
+''')
+
+        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::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr)
+{
+  m_tbe_ptr = NULL;
+}
+''')
+
+        code('''
+
+void
+$c_ident::recordCacheTrace(int cntrl, CacheRecorder* tr)
+{
+''')
+        #
+        # Record cache contents for all associated caches.
+        #
+        code.indent()
+        for param in self.config_parameters:
+            if param.type_ast.type.ident == "CacheMemory":
+                assert(param.pointer)
+                code('m_${{param.ident}}_ptr->recordCacheContents(cntrl, tr);')
+
+        code.dedent()
+        code('''
+}
+
+// Actions
+''')
+        if self.TBEType != None and 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.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"]}}
+}
+
+''')
+        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}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr)
+{
+    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)
+void
+$c_ident::${{action.ident}}(const Address& addr)
 {
-    DEBUG_MSG(GENERATED_COMP, HighPrio, "executing");
+    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
     ${{action["c_code"]}}
 }
 
 ''')
+        for func in self.functions:
+            code(func.generateCode())
+
         code.write(path, "%s.cc" % c_ident)
 
     def printCWakeup(self, path):
         '''Output the wakeup loop for the events'''
 
-        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 "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"
 #include "mem/protocol/Types.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/slicc_interface/RubySlicc_includes.hh"
 #include "mem/ruby/system/System.hh"
 
-void ${ident}_Controller::wakeup()
-{
+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
+            g_system_ptr->getProfiler()->controllerBusy(m_machineID);
+
+            // Wakeup in another cycle and try again
+            g_eventQueue_ptr->scheduleEvent(this, 1);
             break;
         }
 ''')
@@ -583,6 +1035,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_rank = ${{port.pairs["rank"]}};')
+            else:
+                code('m_cur_in_port_rank = 0;')
             code('${{port["c_code_in_port"]}}')
             code.dedent()
 
@@ -593,6 +1049,7 @@ void ${ident}_Controller::wakeup()
         code('''
         break;  // If we got this far, we have nothing left todo
     }
+    // g_eventQueue_ptr->scheduleEvent(this, 1);
 }
 ''')
 
@@ -601,18 +1058,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))
@@ -620,58 +1083,115 @@ 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)
 {
+''')
+        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;
 
-    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);
+    DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n",
+            *this,
+            g_eventQueue_ptr->getTime(),
+            ${ident}_State_to_string(state),
+            ${ident}_Event_to_string(event),
+            addr);
 
-    TransitionResult result = doTransitionWorker(event, state, next_state, 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) {
-        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());
-        }
-    CLEAR_TRANSITION_COMMENT();
-    ${ident}_setState(addr, next_state);
+        DPRINTF(RubyGenerated, "next_state: %s\\n",
+                ${ident}_State_to_string(next_state));
+        m_profiler.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();
+''')
+        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);')
 
+        code('''
     } 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");
-        }
+        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) {
-        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");
-        }
+        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");
     }
 
     return result;
 }
 
-TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr
-)
+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)) {
 ''')
@@ -683,7 +1203,7 @@ 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
@@ -697,9 +1217,8 @@ TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, $
             for key,val in res.iteritems():
                 if key.type.ident != "DNUCAStopTable":
                     val = '''
-if (!%s.areNSlotsAvailable(%s)) {
+if (!%s.areNSlotsAvailable(%s))
     return TransitionResult_ResourceStall;
-}
 ''' % (key.code, val)
                 case_sorter.append(val)
 
@@ -720,8 +1239,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)
@@ -739,46 +1268,143 @@ if (!%s.areNSlotsAvailable(%s)) {
             # the same code
             for trans in transitions:
                 code('  case HASH_FUN($trans):')
-            code('  {')
             code('    $case')
-            code('  }')
 
         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(), g_eventQueue_ptr->getTime(), addr, event, state);
     }
     return TransitionResult_Valid;
 }
 ''')
         code.write(path, "%s_Transitions.cc" % self.ident)
 
+    def printProfileDumperHH(self, path):
+        code = self.symtab.codeFormatter()
+        ident = self.ident
+
+        code('''
+// Auto generated C++ code started by $__file__:$__line__
+// ${ident}: ${{self.short}}
+
+#ifndef __${ident}_PROFILE_DUMPER_HH__
+#define __${ident}_PROFILE_DUMPER_HH__
+
+#include <cassert>
+#include <iostream>
+#include <vector>
+
+#include "${ident}_Event.hh"
+#include "${ident}_Profiler.hh"
+
+typedef std::vector<${ident}_Profiler *> ${ident}_profilers;
+
+class ${ident}_ProfileDumper
+{
+  public:
+    ${ident}_ProfileDumper();
+    void registerProfiler(${ident}_Profiler* profiler);
+    void dumpStats(std::ostream& out) const;
+
+  private:
+    ${ident}_profilers m_profilers;
+};
+
+#endif // __${ident}_PROFILE_DUMPER_HH__
+''')
+        code.write(path, "%s_ProfileDumper.hh" % self.ident)
+
+    def printProfileDumperCC(self, path):
+        code = self.symtab.codeFormatter()
+        ident = self.ident
+
+        code('''
+// Auto generated C++ code started by $__file__:$__line__
+// ${ident}: ${{self.short}}
+
+#include "mem/protocol/${ident}_ProfileDumper.hh"
+
+${ident}_ProfileDumper::${ident}_ProfileDumper()
+{
+}
+
+void
+${ident}_ProfileDumper::registerProfiler(${ident}_Profiler* profiler)
+{
+    m_profilers.push_back(profiler);
+}
+
+void
+${ident}_ProfileDumper::dumpStats(std::ostream& out) const
+{
+    out << " --- ${ident} ---\\n";
+    out << " - Event Counts -\\n";
+    for (${ident}_Event event = ${ident}_Event_FIRST;
+         event < ${ident}_Event_NUM;
+         ++event) {
+        out << (${ident}_Event) event << " [";
+        uint64 total = 0;
+        for (int i = 0; i < m_profilers.size(); i++) {
+             out << m_profilers[i]->getEventCount(event) << " ";
+             total += m_profilers[i]->getEventCount(event);
+        }
+        out << "] " << total << "\\n";
+    }
+    out << "\\n";
+    out << " - Transitions -\\n";
+    for (${ident}_State state = ${ident}_State_FIRST;
+         state < ${ident}_State_NUM;
+         ++state) {
+        for (${ident}_Event event = ${ident}_Event_FIRST;
+             event < ${ident}_Event_NUM;
+             ++event) {
+            if (m_profilers[0]->isPossible(state, event)) {
+                out << (${ident}_State) state << "  "
+                    << (${ident}_Event) event << " [";
+                uint64 total = 0;
+                for (int i = 0; i < m_profilers.size(); i++) {
+                     out << m_profilers[i]->getTransitionCount(state, event) << " ";
+                     total += m_profilers[i]->getTransitionCount(state, event);
+                }
+                out << "] " << total << "\\n";
+            }
+        }
+        out << "\\n";
+    }
+}
+''')
+        code.write(path, "%s_ProfileDumper.cc" % self.ident)
+
     def printProfilerHH(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
 
         code('''
 // Auto generated C++ code started by $__file__:$__line__
 // ${ident}: ${{self.short}}
 
-#ifndef ${ident}_PROFILER_H
-#define ${ident}_PROFILER_H
+#ifndef __${ident}_PROFILER_HH__
+#define __${ident}_PROFILER_HH__
+
+#include <cassert>
+#include <iostream>
 
-#include "mem/ruby/common/Global.hh"
-#include "mem/protocol/${ident}_State.hh"
 #include "mem/protocol/${ident}_Event.hh"
+#include "mem/protocol/${ident}_State.hh"
+#include "mem/ruby/common/TypeDefines.hh"
 
-class ${ident}_Profiler {
+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;
+    uint64 getEventCount(${ident}_Event event);
+    bool isPossible(${ident}_State state, ${ident}_Event event);
+    uint64 getTransitionCount(${ident}_State state, ${ident}_Event event);
     void clearStats();
 
   private:
@@ -788,18 +1414,20 @@ class ${ident}_Profiler {
     int m_version;
 };
 
-#endif // ${ident}_PROFILER_H
+#endif // __${ident}_PROFILER_HH__
 ''')
         code.write(path, "%s_Profiler.hh" % self.ident)
 
     def printProfilerCC(self, path):
-        code = code_formatter()
+        code = self.symtab.codeFormatter()
         ident = self.ident
 
         code('''
 // Auto generated C++ code started by $__file__:$__line__
 // ${ident}: ${{self.short}}
 
+#include <cassert>
+
 #include "mem/protocol/${ident}_Profiler.hh"
 
 ${ident}_Profiler::${ident}_Profiler()
@@ -814,11 +1442,15 @@ ${ident}_Profiler::${ident}_Profiler()
         m_event_counters[event] = 0;
     }
 }
-void ${ident}_Profiler::setVersion(int version)
+
+void
+${ident}_Profiler::setVersion(int version)
 {
     m_version = version;
 }
-void ${ident}_Profiler::clearStats()
+
+void
+${ident}_Profiler::clearStats()
 {
     for (int state = 0; state < ${ident}_State_NUM; state++) {
         for (int event = 0; event < ${ident}_Event_NUM; event++) {
@@ -830,50 +1462,53 @@ void ${ident}_Profiler::clearStats()
         m_event_counters[event] = 0;
     }
 }
-void ${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event)
+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)
+void
+${ident}_Profiler::possibleTransition(${ident}_State state,
+                                      ${ident}_Event event)
 {
     m_possible[state][event] = true;
 }
-void ${ident}_Profiler::dumpStats(ostream& out) const
+
+uint64
+${ident}_Profiler::getEventCount(${ident}_Event event)
 {
-    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;
-    }
+    return m_event_counters[event];
+}
+
+bool
+${ident}_Profiler::isPossible(${ident}_State state, ${ident}_Event event)
+{
+    return m_possible[state][event];
 }
+
+uint64
+${ident}_Profiler::getTransitionCount(${ident}_State state,
+                                      ${ident}_Event event)
+{
+    return m_counters[state][event];
+}
+
 ''')
         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):
@@ -903,10 +1538,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)}}:
 ''')
@@ -990,13 +1626,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('/')
@@ -1004,8 +1639,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:
@@ -1021,6 +1655,7 @@ void ${ident}_Profiler::dumpStats(ostream& out) const
 </TR>
 ''')
         code('''
+<!- Column footer->     
 <TR>
   <TH> </TH>
 ''')