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