ruby: memory controllers now inherit from an abstract "MemoryControl" class
[gem5.git] / src / mem / slicc / symbols / StateMachine.py
index b0d663c43b76a55d412ce8099213a791f83fbe1d..8f4676c4221e76c261bf3127f6353b81fe7b3768 100644 (file)
@@ -30,14 +30,16 @@ 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": "RubyMemoryControl",
+                    "MemoryControl": "MemoryControl",
                     "DMASequencer": "DMASequencer"
                     }
 
@@ -166,9 +168,6 @@ class StateMachine(Symbol):
         self.printProfileDumperCC(path)
         self.printProfileDumperHH(path)
 
-        for func in self.functions:
-            func.writeCodeFiles(path)
-
     def printControllerPython(self, path):
         code = self.symtab.codeFormatter()
         ident = self.ident
@@ -220,15 +219,14 @@ class $py_ident(RubyController):
 #include <sstream>
 #include <string>
 
-#include "params/$c_ident.hh"
-
-#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/protocol/${ident}_ProfileDumper.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()
@@ -255,9 +253,9 @@ public:
     const int & getVersion() const;
     const std::string toString() const;
     const std::string getName() const;
-    const MachineType getMachineType() 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;
@@ -266,6 +264,8 @@ public:
     void clearStats();
     void blockOnQueue(Address addr, MessageBuffer* port);
     void unblock(Address addr);
+    void recordCacheTrace(int cntrl, CacheRecorder* tr);
+    Sequencer* getSequencer() const;
 
 private:
 ''')
@@ -324,7 +324,7 @@ MachineID m_machineID;
 bool m_is_blocking;
 std::map<Address, MessageBuffer*> m_block_map;
 typedef std::vector<MessageBuffer*> MsgVecType;
-typedef m5::hash_map< Address, MsgVecType* > WaitingBufType;
+typedef std::map< Address, MsgVecType* > WaitingBufType;
 WaitingBufType m_waiting_buffers;
 int m_max_in_port_rank;
 int m_cur_in_port_rank;
@@ -408,14 +408,20 @@ void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr);
  * Created by slicc definition of Module "${{self.short}}"
  */
 
+#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"
@@ -455,6 +461,7 @@ $c_ident::$c_ident(const Params *p)
     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
@@ -470,10 +477,13 @@ $c_ident::$c_ident(const Params *p)
         # params include a sequencer.  This information will be used later for
         # contecting the sequencer back to the L1 cache controller.
         #
-        contains_sequencer = False
+        contains_dma_sequencer = False
+        sequencers = []
         for param in self.config_parameters:
-            if param.name == "sequencer" or param.name == "dma_sequencer":
-                contains_sequencer = True
+            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:
@@ -484,19 +494,27 @@ $c_ident::$c_ident(const Params *p)
         # includes passing the sequencer a pointer to the controller.
         #
         if self.ident == "L1Cache":
-            if not contains_sequencer:
+            if not sequencers:
                 self.error("The L1Cache controller must include the sequencer " \
                            "configuration parameter")
 
-            code('''
-m_sequencer_ptr->setController(this);
-''')
+            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_sequencer:
+            if not contains_dma_sequencer:
                 self.error("The DMA controller must include the sequencer " \
                            "configuration parameter")
 
@@ -584,12 +602,13 @@ $c_ident::init()
                 network = var["network"]
                 ordered =  var["ordered"]
                 vnet = var["virtual_network"]
+                vnet_type = var["vnet_type"]
 
                 assert var.machine is not None
                 code('''
 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);
+$vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet, "$vnet_type");
 ''')
 
                 code('assert($vid != NULL);')
@@ -602,7 +621,7 @@ $vid = m_net_ptr->get${network}NetQueue(m_version + base, $ordered, $vnet);
                 # Set randomization
                 if "random" in var:
                     # A buffer
-                    code('$vid->setRandomization(${{var["random"]}})')
+                    code('$vid->setRandomization(${{var["random"]}});')
 
                 # Set Priority
                 if "rank" in var:
@@ -667,6 +686,12 @@ $vid->setDescription("[Version " + to_string(m_version) + ", ${ident}, name=${{v
         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()
@@ -680,6 +705,12 @@ $c_ident::getMandatoryQueue() const
     return $mq_ident;
 }
 
+Sequencer*
+$c_ident::getSequencer() const
+{
+    return $seq_ident;
+}
+
 const int &
 $c_ident::getVersion() const
 {
@@ -698,12 +729,6 @@ $c_ident::getName() const
     return m_name;
 }
 
-const MachineType
-$c_ident::getMachineType() const
-{
-    return MachineType_${ident};
-}
-
 void
 $c_ident::stallBuffer(MessageBuffer* buf, Address addr)
 {
@@ -718,19 +743,54 @@ $c_ident::stallBuffer(MessageBuffer* buf, Address addr)
 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.
     //
-    // 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);
+
+    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();
     }
-    delete m_waiting_buffers[addr];
-    m_waiting_buffers.erase(addr);
 }
 
 void
@@ -839,6 +899,23 @@ $c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr)
 
         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:
@@ -851,7 +928,7 @@ $c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr)
 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\\n");
+    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
     ${{action["c_code"]}}
 }
 
@@ -866,7 +943,7 @@ $c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.Entry
 void
 $c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr)
 {
-    DPRINTF(RubyGenerated, "executing\\n");
+    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
     ${{action["c_code"]}}
 }
 
@@ -881,7 +958,7 @@ $c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address
 void
 $c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr)
 {
-    DPRINTF(RubyGenerated, "executing\\n");
+    DPRINTF(RubyGenerated, "executing ${{action.ident}}\\n");
     ${{action["c_code"]}}
 }
 
@@ -896,11 +973,14 @@ $c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, con
 void
 $c_ident::${{action.ident}}(const Address& addr)
 {
-    DPRINTF(RubyGenerated, "executing\\n");
+    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):
@@ -913,15 +993,19 @@ $c_ident::${{action.ident}}(const Address& addr)
 // Auto generated C++ code started by $__file__:$__line__
 // ${ident}: ${{self.short}}
 
+#include <sys/types.h>
+#include <unistd.h>
+
 #include <cassert>
 
 #include "base/misc.hh"
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/slicc_interface/RubySlicc_includes.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;
@@ -985,11 +1069,13 @@ ${ident}_Controller::wakeup()
 
 #include "base/misc.hh"
 #include "base/trace.hh"
-#include "mem/ruby/common/Global.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))
@@ -1013,13 +1099,13 @@ ${ident}_Controller::doTransition(${ident}_Event event,
 {
 ''')
         if self.TBEType != None and self.EntryType != None:
-            code('${ident}_State state = ${ident}_getState(m_tbe_ptr, m_cache_entry_ptr, addr);')
+            code('${ident}_State state = getState(m_tbe_ptr, m_cache_entry_ptr, addr);')
         elif self.TBEType != None:
-            code('${ident}_State state = ${ident}_getState(m_tbe_ptr, addr);')
+            code('${ident}_State state = getState(m_tbe_ptr, addr);')
         elif self.EntryType != None:
-            code('${ident}_State state = ${ident}_getState(m_cache_entry_ptr, addr);')
+            code('${ident}_State state = getState(m_cache_entry_ptr, addr);')
         else:
-            code('${ident}_State state = ${ident}_getState(addr);')
+            code('${ident}_State state = getState(addr);')
 
         code('''
     ${ident}_State next_state = state;
@@ -1047,40 +1133,44 @@ ${ident}_Controller::doTransition(${ident}_Event event,
         DPRINTF(RubyGenerated, "next_state: %s\\n",
                 ${ident}_State_to_string(next_state));
         m_profiler.countTransition(state, event);
-        DPRINTFR(ProtocolTrace, "%7d %3s %10s%20s %6s>%-6s %s %s\\n",
-            g_eventQueue_ptr->getTime(), m_version, "${ident}",
-            ${ident}_Event_to_string(event),
-            ${ident}_State_to_string(state),
-            ${ident}_State_to_string(next_state),
-            addr, GET_TRANSITION_COMMENT());
+        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('${ident}_setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);')
+            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('${ident}_setState(m_tbe_ptr, addr, next_state);')
+            code('setState(m_tbe_ptr, addr, next_state);')
+            code('setAccessPermission(addr, next_state);')
         elif self.EntryType != None:
-            code('${ident}_setState(m_cache_entry_ptr, addr, next_state);')
+            code('setState(m_cache_entry_ptr, addr, next_state);')
+            code('setAccessPermission(m_cache_entry_ptr, addr, next_state);')
         else:
-            code('${ident}_setState(addr, next_state);')
+            code('setState(addr, next_state);')
+            code('setAccessPermission(addr, next_state);')
 
         code('''
     } else if (result == TransitionResult_ResourceStall) {
-        DPRINTFR(ProtocolTrace, "%7s %3s %10s%20s %6s>%-6s %s %s\\n",
-            g_eventQueue_ptr->getTime(), m_version, "${ident}",
-            ${ident}_Event_to_string(event),
-            ${ident}_State_to_string(state),
-            ${ident}_State_to_string(next_state),
-            addr, "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) {
         DPRINTF(RubyGenerated, "stalling\\n");
-        DPRINTFR(ProtocolTrace, "%7s %3s %10s%20s %6s>%-6s %s %s\\n",
-            g_eventQueue_ptr->getTime(), m_version, "${ident}",
-            ${ident}_Event_to_string(event),
-            ${ident}_State_to_string(state),
-            ${ident}_State_to_string(next_state),
-            addr, "Protocol 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, "Protocol Stall");
     }
 
     return result;
@@ -1183,8 +1273,8 @@ if (!%s.areNSlotsAvailable(%s))
         code('''
       default:
         fatal("Invalid transition\\n"
-              "version: %d time: %d addr: %s event: %s state: %s\\n",
-              m_version, g_eventQueue_ptr->getTime(), addr, event, state);
+              "%s time: %d addr: %s event: %s state: %s\\n",
+              name(), g_eventQueue_ptr->getTime(), addr, event, state);
     }
     return TransitionResult_Valid;
 }
@@ -1206,8 +1296,8 @@ if (!%s.areNSlotsAvailable(%s))
 #include <iostream>
 #include <vector>
 
-#include "${ident}_Profiler.hh"
 #include "${ident}_Event.hh"
+#include "${ident}_Profiler.hh"
 
 typedef std::vector<${ident}_Profiler *> ${ident}_profilers;
 
@@ -1301,9 +1391,9 @@ ${ident}_ProfileDumper::dumpStats(std::ostream& out) const
 #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
 {