ruby: message buffers: significant changes
[gem5.git] / src / mem / ruby / network / garnet / fixed-pipeline / NetworkInterface_d.cc
index 0dd51019ce30770d1fa2fe0a2c00410a73e1bd4a..7384cc6a7296b914c747f79b4ce880afe69d1139 100644 (file)
 #include <cassert>
 #include <cmath>
 
+#include "base/cast.hh"
 #include "base/stl_helpers.hh"
 #include "debug/RubyNetwork.hh"
-#include "mem/ruby/buffers/MessageBuffer.hh"
+#include "mem/ruby/network/MessageBuffer.hh"
 #include "mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.hh"
 #include "mem/ruby/network/garnet/fixed-pipeline/flitBuffer_d.hh"
 #include "mem/ruby/slicc_interface/NetworkMessage.hh"
 using namespace std;
 using m5::stl_helpers::deletePointers;
 
-NetworkInterface_d::NetworkInterface_d(int id, int virtual_networks,
-                                       GarnetNetwork_d *network_ptr)
+NetworkInterface_d::NetworkInterface_d(const Params *p)
+    : ClockedObject(p), Consumer(this)
 {
-    m_id = id;
-    m_net_ptr = network_ptr;
-    m_virtual_networks  = virtual_networks;
-    m_vc_per_vnet = m_net_ptr->getVCsPerClass();
+    m_id = p->id;
+    m_virtual_networks  = p->virt_nets;
+    m_vc_per_vnet = p->vcs_per_vnet;
     m_num_vcs = m_vc_per_vnet*m_virtual_networks;
 
     m_vc_round_robin = 0;
     m_ni_buffers.resize(m_num_vcs);
     m_ni_enqueue_time.resize(m_num_vcs);
-    inNode_ptr.resize(m_virtual_networks);
-    outNode_ptr.resize(m_virtual_networks);
     creditQueue = new flitBuffer_d();
 
     // instantiating the NI flit buffers
     for (int i = 0; i < m_num_vcs; i++) {
         m_ni_buffers[i] = new flitBuffer_d();
-        m_ni_enqueue_time[i] = INFINITE_;
+        m_ni_enqueue_time[i] = Cycles(INFINITE_);
     }
+
     m_vc_allocator.resize(m_virtual_networks); // 1 allocator per vnet
     for (int i = 0; i < m_virtual_networks; i++) {
         m_vc_allocator[i] = 0;
     }
+}
 
+void
+NetworkInterface_d::init()
+{
     for (int i = 0; i < m_num_vcs; i++) {
         m_out_vc_state.push_back(new OutVcState_d(i, m_net_ptr));
-        m_out_vc_state[i]->setState(IDLE_, g_eventQueue_ptr->getTime());
     }
 }
 
@@ -104,16 +106,20 @@ NetworkInterface_d::addOutPort(NetworkLink_d *out_link,
 }
 
 void
-NetworkInterface_d::addNode(vector<MessageBuffer *>& in,
-                            vector<MessageBuffer *>& out)
+NetworkInterface_d::addNode(map<int, MessageBuffer *>& in,
+                            map<int, MessageBuffer *>& out)
 {
-    assert(in.size() == m_virtual_networks);
     inNode_ptr = in;
     outNode_ptr = out;
-    for (int j = 0; j < m_virtual_networks; j++) {
 
+    for (auto& it : in) {
         // the protocol injects messages into the NI
-        inNode_ptr[j]->setConsumer(this);
+        it.second->setConsumer(this);
+        it.second->setReceiver(this);
+    }
+
+    for (auto& it : out) {
+        it.second->setSender(this);
     }
 }
 
@@ -164,21 +170,18 @@ NetworkInterface_d::flitisizeMessage(MsgPtr msg_ptr, int vnet)
             // flitisized and an output vc is acquired
             net_msg_ptr->getInternalDestination().removeNetDest(personal_dest);
         }
-        if (num_flits > 1) { // data packet
-            // defining ctrl vnet to be 1-flit packets
-            // and data vnet to be > 1 flit packets
-            m_net_ptr->set_vnet_type(vc, DATA_VNET_);
-            m_out_vc_state[vc]->set_credit_count();
-        }
 
         for (int i = 0; i < num_flits; i++) {
-            m_net_ptr->increment_injected_flits();
-            flit_d *fl = new flit_d(i, vc, vnet, num_flits, new_msg_ptr);
-            fl->set_delay(g_eventQueue_ptr->getTime() - msg_ptr->getTime());
+            m_net_ptr->increment_injected_flits(vnet);
+            flit_d *fl = new flit_d(i, vc, vnet, num_flits, new_msg_ptr,
+                curCycle());
+
+            fl->set_delay(curCycle() - ticksToCycles(msg_ptr->getTime()));
             m_ni_buffers[vc]->insert(fl);
         }
-        m_ni_enqueue_time[vc] = g_eventQueue_ptr->getTime();
-        m_out_vc_state[vc]->setState(ACTIVE_, g_eventQueue_ptr->getTime());
+
+        m_ni_enqueue_time[vc] = curCycle();
+        m_out_vc_state[vc]->setState(ACTIVE_, curCycle());
     }
     return true ;
 }
@@ -194,7 +197,7 @@ NetworkInterface_d::calculateVC(int vnet)
                         m_vc_allocator[vnet] = 0;
 
                 if (m_out_vc_state[(vnet*m_vc_per_vnet) + delta]->isInState(
-                    IDLE_, g_eventQueue_ptr->getTime())) {
+                    IDLE_, curCycle())) {
                         return ((vnet*m_vc_per_vnet) + delta);
                 }
         }
@@ -214,18 +217,20 @@ NetworkInterface_d::calculateVC(int vnet)
 void
 NetworkInterface_d::wakeup()
 {
-    DPRINTF(RubyNetwork, "m_id: %d woke up at time: %lld",
-            m_id, g_eventQueue_ptr->getTime());
+    DPRINTF(RubyNetwork, "m_id: %d woke up at time: %lld", m_id, curCycle());
 
     MsgPtr msg_ptr;
 
     // Checking for messages coming from the protocol
     // can pick up a message/cycle for each virtual net
-    for (int vnet = 0; vnet < m_virtual_networks; vnet++) {
-        while (inNode_ptr[vnet]->isReady()) { // Is there a message waiting
-            msg_ptr = inNode_ptr[vnet]->peekMsgPtr();
+    for (auto it = inNode_ptr.begin(); it != inNode_ptr.end(); ++it) {
+        int vnet = (*it).first;
+        MessageBuffer *b = (*it).second;
+
+        while (b->isReady()) { // Is there a message waiting
+            msg_ptr = b->peekMsgPtr();
             if (flitisizeMessage(msg_ptr, vnet)) {
-                inNode_ptr[vnet]->pop();
+                b->dequeue();
             } else {
                 break;
             }
@@ -237,38 +242,40 @@ NetworkInterface_d::wakeup()
 
     /*********** Picking messages destined for this NI **********/
 
-    if (inNetLink->isReady()) {
+    if (inNetLink->isReady(curCycle())) {
         flit_d *t_flit = inNetLink->consumeLink();
         bool free_signal = false;
         if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) {
             free_signal = true;
 
             outNode_ptr[t_flit->get_vnet()]->enqueue(
-                t_flit->get_msg_ptr(), 1);
+                t_flit->get_msg_ptr(), Cycles(1));
         }
         // Simply send a credit back since we are not buffering
         // this flit in the NI
-        flit_d *credit_flit = new flit_d(t_flit->get_vc(), free_signal);
+        flit_d *credit_flit = new flit_d(t_flit->get_vc(), free_signal,
+                                         curCycle());
         creditQueue->insert(credit_flit);
-        g_eventQueue_ptr->scheduleEvent(m_ni_credit_link, 1);
-
-        m_net_ptr->increment_received_flits();
-        int network_delay = g_eventQueue_ptr->getTime() -
-                            t_flit->get_enqueue_time();
-        int queueing_delay = t_flit->get_delay();
-        m_net_ptr->increment_network_latency(network_delay);
-        m_net_ptr->increment_queueing_latency(queueing_delay);
+        m_ni_credit_link->
+            scheduleEventAbsolute(clockEdge(Cycles(1)));
+
+        int vnet = t_flit->get_vnet();
+        m_net_ptr->increment_received_flits(vnet);
+        Cycles network_delay = curCycle() - t_flit->get_enqueue_time();
+        Cycles queueing_delay = t_flit->get_delay();
+
+        m_net_ptr->increment_network_latency(network_delay, vnet);
+        m_net_ptr->increment_queueing_latency(queueing_delay, vnet);
         delete t_flit;
     }
 
     /****************** Checking for credit link *******/
 
-    if (m_credit_link->isReady()) {
+    if (m_credit_link->isReady(curCycle())) {
         flit_d *t_flit = m_credit_link->consumeLink();
         m_out_vc_state[t_flit->get_vc()]->increment_credit();
         if (t_flit->is_free_signal()) {
-            m_out_vc_state[t_flit->get_vc()]->setState(IDLE_,
-                g_eventQueue_ptr->getTime());
+            m_out_vc_state[t_flit->get_vc()]->setState(IDLE_, curCycle());
         }
         delete t_flit;
     }
@@ -294,7 +301,9 @@ NetworkInterface_d::scheduleOutputLink()
             vc = 0;
 
         // model buffer backpressure
-        if (m_ni_buffers[vc]->isReady() && m_out_vc_state[vc]->has_credits()) {
+        if (m_ni_buffers[vc]->isReady(curCycle()) &&
+            m_out_vc_state[vc]->has_credits()) {
+
             bool is_candidate_vc = true;
             int t_vnet = get_vnet(vc);
             int vc_base = t_vnet * m_vc_per_vnet;
@@ -303,7 +312,7 @@ NetworkInterface_d::scheduleOutputLink()
                 for (int vc_offset = 0; vc_offset < m_vc_per_vnet;
                      vc_offset++) {
                     int t_vc = vc_base + vc_offset;
-                    if (m_ni_buffers[t_vc]->isReady()) {
+                    if (m_ni_buffers[t_vc]->isReady(curCycle())) {
                         if (m_ni_enqueue_time[t_vc] < m_ni_enqueue_time[vc]) {
                             is_candidate_vc = false;
                             break;
@@ -317,14 +326,14 @@ NetworkInterface_d::scheduleOutputLink()
             m_out_vc_state[vc]->decrement_credit();
             // Just removing the flit
             flit_d *t_flit = m_ni_buffers[vc]->getTopFlit();
-            t_flit->set_time(g_eventQueue_ptr->getTime() + 1);
+            t_flit->set_time(curCycle() + Cycles(1));
             outSrcQueue->insert(t_flit);
             // schedule the out link
-            g_eventQueue_ptr->scheduleEvent(outNetLink, 1);
+            outNetLink->scheduleEventAbsolute(clockEdge(Cycles(1)));
 
             if (t_flit->get_type() == TAIL_ ||
                t_flit->get_type() == HEAD_TAIL_) {
-                m_ni_enqueue_time[vc] = INFINITE_;
+                m_ni_enqueue_time[vc] = Cycles(INFINITE_);
             }
             return;
         }
@@ -334,7 +343,7 @@ NetworkInterface_d::scheduleOutputLink()
 int
 NetworkInterface_d::get_vnet(int vc)
 {
-    for (int i = 0; i < m_net_ptr->getNumberOfVirtualNetworks(); i++) {
+    for (int i = 0; i < m_virtual_networks; i++) {
         if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
             return i;
         }
@@ -345,30 +354,44 @@ NetworkInterface_d::get_vnet(int vc)
 void
 NetworkInterface_d::checkReschedule()
 {
-    for (int vnet = 0; vnet < m_virtual_networks; vnet++) {
-        if (inNode_ptr[vnet]->isReady()) { // Is there a message waiting
-            g_eventQueue_ptr->scheduleEvent(this, 1);
+    for (const auto& it : inNode_ptr) {
+        MessageBuffer *b = it.second;
+
+        while (b->isReady()) { // Is there a message waiting
+            scheduleEvent(Cycles(1));
             return;
         }
     }
+
     for (int vc = 0; vc < m_num_vcs; vc++) {
-        if (m_ni_buffers[vc]->isReadyForNext()) {
-            g_eventQueue_ptr->scheduleEvent(this, 1);
+        if (m_ni_buffers[vc]->isReady(curCycle() + Cycles(1))) {
+            scheduleEvent(Cycles(1));
             return;
         }
     }
 }
 
 void
-NetworkInterface_d::printConfig(std::ostream& out) const
+NetworkInterface_d::print(std::ostream& out) const
 {
-    out << "[Network Interface " << m_id << "] - ";
-    out << "[inLink " << inNetLink->get_id() << "] - ";
-    out << "[outLink " << outNetLink->get_id() << "]" << std::endl;
+    out << "[Network Interface]";
 }
 
-void
-NetworkInterface_d::print(std::ostream& out) const
+uint32_t
+NetworkInterface_d::functionalWrite(Packet *pkt)
 {
-    out << "[Network Interface]";
+    uint32_t num_functional_writes = 0;
+    for (unsigned int i  = 0; i < m_num_vcs; ++i) {
+        num_functional_writes += m_ni_buffers[i]->functionalWrite(pkt);
+    }
+
+    num_functional_writes += outSrcQueue->functionalWrite(pkt);
+    return num_functional_writes;
+}
+
+NetworkInterface_d *
+GarnetNetworkInterface_dParams::create()
+{
+    return new NetworkInterface_d(this);
 }
+