Srikant Bharadwaj has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/32298 )

Change subject: mem-garnet: Revamp SerDes execution.
......................................................................

mem-garnet: Revamp SerDes execution.

Earlier type of modelling creates problems when deserializing
to non-multiple ratios. This change upgrades serdes to serialize
and deserialize to exact message sizes. This commit also
fixes some debug messages within garnet.

Change-Id: I9606af75943f69fc97a768113f03e997cac92e0f
---
M src/mem/ruby/network/garnet2.0/Credit.cc
M src/mem/ruby/network/garnet2.0/Credit.hh
M src/mem/ruby/network/garnet2.0/NetworkBridge.cc
M src/mem/ruby/network/garnet2.0/NetworkBridge.hh
M src/mem/ruby/network/garnet2.0/flit.cc
M src/mem/ruby/network/garnet2.0/flit.hh
6 files changed, 102 insertions(+), 40 deletions(-)



diff --git a/src/mem/ruby/network/garnet2.0/Credit.cc b/src/mem/ruby/network/garnet2.0/Credit.cc
index 7c293cf..7619079 100644
--- a/src/mem/ruby/network/garnet2.0/Credit.cc
+++ b/src/mem/ruby/network/garnet2.0/Credit.cc
@@ -63,10 +63,20 @@
         // So send a credit in any case
         return new Credit(m_vc, true, m_time);
     }
-    if (des_id % num_flits) {
-        return NULL;
-    }

     return new Credit(m_vc, false, m_time);
 }

+void
+Credit::print(std::ostream& out) const
+{
+    out << "[Credit:: ";
+    out << "Type=" << m_type << " ";
+    out << "VC=" << m_vc << " ";
+    out << "FreeVC=" << m_is_free_signal << " ";
+    out << "Set Time=" << m_time << " ";
+    out << "]";
+}
+
+
+
diff --git a/src/mem/ruby/network/garnet2.0/Credit.hh b/src/mem/ruby/network/garnet2.0/Credit.hh
index ea5aee7..1f3c347 100644
--- a/src/mem/ruby/network/garnet2.0/Credit.hh
+++ b/src/mem/ruby/network/garnet2.0/Credit.hh
@@ -53,6 +53,7 @@
     // Functions used by SerDes
     flit* serialize(int ser_id, int parts, uint32_t bWidth);
     flit* deserialize(int des_id, int num_flits, uint32_t bWidth);
+    void print(std::ostream& out) const;

     ~Credit() {};

diff --git a/src/mem/ruby/network/garnet2.0/NetworkBridge.cc b/src/mem/ruby/network/garnet2.0/NetworkBridge.cc
index 0073c65..1cf560f 100644
--- a/src/mem/ruby/network/garnet2.0/NetworkBridge.cc
+++ b/src/mem/ruby/network/garnet2.0/NetworkBridge.cc
@@ -50,6 +50,7 @@

     cdcLatency = p->cdc_latency;
     serDesLatency = p->serdes_latency;
+    lastScheduledAt = 0;

     nLink = p->link;
     if (mType == FROM_LINK_) {
@@ -64,6 +65,8 @@
     }

     lenBuffer.resize(p->vcs_per_vnet * p->virt_nets);
+    sizeSent.resize(p->vcs_per_vnet * p->virt_nets);
+    flitsSent.resize(p->vcs_per_vnet * p->virt_nets);
     extraCredit.resize(p->vcs_per_vnet * p->virt_nets);
 }

@@ -96,9 +99,14 @@
         totLatency = latency + cdcLatency;
     }

-    t_flit->set_time(link_consumer->getObject()->clockEdge(totLatency));
+    Tick sendTime = link_consumer->getObject()->clockEdge(totLatency);
+    Tick nextAvailTick = lastScheduledAt + link_consumer->getObject()->\
+            cyclesToTicks(Cycles(1));
+    sendTime = std::max(nextAvailTick, sendTime);
+    t_flit->set_time(sendTime);
+    lastScheduledAt = sendTime;
     linkBuffer.insert(t_flit);
-    link_consumer->scheduleEvent(totLatency);
+    link_consumer->scheduleEventAbsolute(sendTime);
 }

 void
@@ -130,29 +138,52 @@
             // Deserialize
             // This deserializer combines flits from the
             // same message together
-            // TODO: Allow heterogenous flits
             int num_flits = 0;
+            int flitPossible = 0;
             if (t_flit->get_type() == CREDIT_) {
- num_flits = (int)ceil((float)target_width/(float)cur_width);
+                lenBuffer[vc]++;
+                assert(extraCredit[vc].front());
+                if (lenBuffer[vc] == extraCredit[vc].front()) {
+                    flitPossible = 1;
+                    extraCredit[vc].pop();
+                    lenBuffer[vc] = 0;
+                }
             } else if (t_flit->get_type() == TAIL_ ||
                        t_flit->get_type() == HEAD_TAIL_) {
-                num_flits = 1;
+                // If its the end of packet, then send whatever
+                // is available.
+                int sizeAvail = (t_flit->msgSize - sizeSent[vc]);
+                flitPossible = ceil((float)sizeAvail/(float)target_width);
+                assert (flitPossible < 2);
+                num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
+                // Stop tracking the packet.
+                flitsSent[vc] = 0;
+                sizeSent[vc] = 0;
             } else {
-                num_flits = (int)ceil((float)std::min(t_flit->msgSize,
-                                       target_width)/(float)cur_width);
+                // If we are yet to receive the complete packet
+                // track the size recieved and flits deserialized.
+                int sizeAvail =
+                    ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
+                flitPossible = floor((float)sizeAvail/(float)target_width);
+                assert (flitPossible < 2);
+                num_flits = (t_flit->get_id() + 1) - flitsSent[vc];
+                if (flitPossible) {
+                    sizeSent[vc] += target_width;
+                    flitsSent[vc] = t_flit->get_id() + 1;
+                }
             }
-            assert(num_flits > 0);

-            DPRINTF(RubyNetwork, "Deserialize :%d -----> %d "
-                "num-flits-needed:%d vc:%d\n",
-                cur_width, target_width, num_flits, vc);
+            DPRINTF(RubyNetwork, "Deserialize :%dB -----> %dB "
+                " vc:%d\n", cur_width, target_width, vc);

-            // lenBuffer acts as the buffer for deserialization
+            flit *fl = NULL;
+            if (flitPossible) {
+                fl = t_flit->deserialize(lenBuffer[vc], num_flits,
+                    target_width);
+            }

-            lenBuffer[vc]++;
-            flit *fl = t_flit->deserialize(lenBuffer[vc], num_flits,
-                target_width);
-
+            // Inform the credit serializer about the number
+            // of flits that were generated.
             if (t_flit->get_type() != CREDIT_ && fl) {
                 coBridge->neutralize(vc, num_flits);
             }
@@ -171,24 +202,43 @@
             "(vc:%d, Original Message Size: %d)\n",
                 cur_width, target_width, vc, t_flit->msgSize);

-            int num_parts = 0;
+            int flitPossible = 0;
             if (t_flit->get_type() == CREDIT_) {
+                // We store the deserialization ratio and then
+                // access it when serializing credits in the
+                // oppposite direction.
                 assert(extraCredit[vc].front());
-                num_parts = extraCredit[vc].front();
+                flitPossible = extraCredit[vc].front();
                 extraCredit[vc].pop();
+            } else if (t_flit->get_type() == HEAD_ ||
+                    t_flit->get_type() == BODY_) {
+                int sizeAvail =
+                    ((t_flit->get_id() + 1)*cur_width) - sizeSent[vc];
+                flitPossible = floor((float)sizeAvail/(float)target_width);
+                if (flitPossible) {
+                    sizeSent[vc] += flitPossible*target_width;
+                    flitsSent[vc] += flitPossible;
+                }
             } else {
-                num_parts = (int)ceil((float)cur_width/
-                            (float)target_width);
+                int sizeAvail = t_flit->msgSize - sizeSent[vc];
+                flitPossible = ceil((float)sizeAvail/(float)target_width);
+                sizeSent[vc] = 0;
+                flitsSent[vc] = 0;
             }
-            assert(num_parts > 0);
+            assert(flitPossible > 0);

-            DPRINTF(RubyNetwork, "Serialized into %d parts\n", num_parts);
             // Schedule all the flits
             // num_flits could be zero for credits
-            for (int i = 0; i < num_parts; i++) {
+            for (int i = 0; i < flitPossible; i++) {
                 // Ignore neutralized credits
-                flit *fl = t_flit->serialize(i, num_parts, target_width);
+ flit *fl = t_flit->serialize(i, flitPossible, target_width);
                 scheduleFlit(fl, serDesLatency);
+                DPRINTF(RubyNetwork, "Serialized to flit[%d of %d parts]:"
+                " %s\n", i+1, flitPossible, *fl);
+            }
+
+            if (t_flit->get_type() != CREDIT_) {
+                coBridge->neutralize(vc, flitPossible);
             }
             // Delete this flit, new flit is sent in any case
             delete t_flit;
diff --git a/src/mem/ruby/network/garnet2.0/NetworkBridge.hh b/src/mem/ruby/network/garnet2.0/NetworkBridge.hh
index 1e041bd..f6c6b97 100644
--- a/src/mem/ruby/network/garnet2.0/NetworkBridge.hh
+++ b/src/mem/ruby/network/garnet2.0/NetworkBridge.hh
@@ -89,8 +89,12 @@
     Cycles cdcLatency;
     Cycles serDesLatency;

+    Tick lastScheduledAt;
+
     // Used by Credit Deserializer
     std::vector<int> lenBuffer;
+    std::vector<int> sizeSent;
+    std::vector<int> flitsSent;
     std::vector<std::queue<int>> extraCredit;

 };
diff --git a/src/mem/ruby/network/garnet2.0/flit.cc b/src/mem/ruby/network/garnet2.0/flit.cc
index 9631b5c..bad80b7 100644
--- a/src/mem/ruby/network/garnet2.0/flit.cc
+++ b/src/mem/ruby/network/garnet2.0/flit.cc
@@ -65,9 +65,10 @@
 {
     assert(m_width > bWidth);

-    // Assuming all flits get broken into equal parts
-    int new_id = (m_id*parts) + ser_id;
-    int new_size = m_size*parts;
+    int ratio = (int)ceil(m_width/bWidth);
+    int new_id = (m_id*ratio) + ser_id;
+    int new_size = (int)ceil((float)msgSize/(float)bWidth);
+    assert(new_id < new_size);

     flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
                     new_size, m_msg_ptr, msgSize, bWidth, m_time);
@@ -79,14 +80,10 @@
 flit *
 flit::deserialize(int des_id, int num_flits, uint32_t bWidth)
 {
-    if ((m_type == HEAD_ || m_type == BODY_) &&
-       ((m_id + 1) % num_flits)) {
-        return NULL;
-    }
-
-    // Assuming all flits are joined into equal parts
-    int new_id = (int) floor((float)m_id/(float)num_flits);
-    int new_size = (int) ceil((float)m_size/(float)num_flits);
+    int ratio = (int)ceil((float)bWidth/(float)m_width);
+    int new_id = ((int)ceil((float)(m_id+1)/(float)ratio)) - 1;
+    int new_size = (int) ceil((float)msgSize/(float)bWidth);
+    assert(new_id < new_size);

     flit *fl = new flit(new_id, m_vc, m_vnet, m_route,
                     new_size, m_msg_ptr, msgSize, bWidth, m_time);
@@ -109,7 +106,7 @@
     out << "Src Router=" << m_route.src_router << " ";
     out << "Dest NI=" << m_route.dest_ni << " ";
     out << "Dest Router=" << m_route.dest_router << " ";
-    out << "Enqueue Time=" << m_enqueue_time << " ";
+    out << "Set Time=" << m_time << " ";
     out << "Width=" << m_width<< " ";
     out << "]";
 }
diff --git a/src/mem/ruby/network/garnet2.0/flit.hh b/src/mem/ruby/network/garnet2.0/flit.hh
index 9907ccd..ce6c982 100644
--- a/src/mem/ruby/network/garnet2.0/flit.hh
+++ b/src/mem/ruby/network/garnet2.0/flit.hh
@@ -73,7 +73,7 @@
     void set_enqueue_time(Tick time) { m_enqueue_time = time; }

     void increment_hops() { m_route.hops_traversed++; }
-    void print(std::ostream& out) const;
+    virtual void print(std::ostream& out) const;

     bool
     is_stage(flit_stage stage, Tick time)

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/32298
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: feature-heterogarnet
Gerrit-Change-Id: I9606af75943f69fc97a768113f03e997cac92e0f
Gerrit-Change-Number: 32298
Gerrit-PatchSet: 1
Gerrit-Owner: Srikant Bharadwaj <srikant.bharad...@amd.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to