summaryrefslogtreecommitdiff
path: root/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc')
-rw-r--r--src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc514
1 files changed, 265 insertions, 249 deletions
diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc
index 3cda065ad..a33776c17 100644
--- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc
+++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc
@@ -39,139 +39,153 @@
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(int id, int virtual_networks,
+ GarnetNetwork_d *network_ptr)
{
- m_id = id;
- m_net_ptr = network_ptr;
- m_virtual_networks = virtual_networks;
- m_vc_per_vnet = m_net_ptr->getVCsPerClass();
- 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();
-
- for(int i =0; i < m_num_vcs; i++)
- {
- m_ni_buffers[i] = new flitBuffer_d(); // instantiating the NI flit buffers
- m_ni_enqueue_time[i] = INFINITE_;
- }
- m_vc_allocator.resize(m_virtual_networks); // 1 allocator per virtual net
- for(int i = 0; i < m_virtual_networks; i++)
- {
- m_vc_allocator[i] = 0;
- }
-
- 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());
- }
+ m_id = id;
+ m_net_ptr = network_ptr;
+ m_virtual_networks = virtual_networks;
+ m_vc_per_vnet = m_net_ptr->getVCsPerClass();
+ 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_vc_allocator.resize(m_virtual_networks); // 1 allocator per vnet
+ for (int i = 0; i < m_virtual_networks; i++) {
+ m_vc_allocator[i] = 0;
+ }
+
+ 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());
+ }
}
NetworkInterface_d::~NetworkInterface_d()
{
- deletePointers(m_out_vc_state);
- deletePointers(m_ni_buffers);
- delete creditQueue;
- delete outSrcQueue;
+ deletePointers(m_out_vc_state);
+ deletePointers(m_ni_buffers);
+ delete creditQueue;
+ delete outSrcQueue;
}
-void NetworkInterface_d::addInPort(NetworkLink_d *in_link, CreditLink_d *credit_link)
+void
+NetworkInterface_d::addInPort(NetworkLink_d *in_link,
+ CreditLink_d *credit_link)
{
- inNetLink = in_link;
- in_link->setLinkConsumer(this);
- m_ni_credit_link = credit_link;
- credit_link->setSourceQueue(creditQueue);
+ inNetLink = in_link;
+ in_link->setLinkConsumer(this);
+ m_ni_credit_link = credit_link;
+ credit_link->setSourceQueue(creditQueue);
}
-void NetworkInterface_d::addOutPort(NetworkLink_d *out_link, CreditLink_d *credit_link)
+void
+NetworkInterface_d::addOutPort(NetworkLink_d *out_link,
+ CreditLink_d *credit_link)
{
- m_credit_link = credit_link;
- credit_link->setLinkConsumer(this);
+ m_credit_link = credit_link;
+ credit_link->setLinkConsumer(this);
- outNetLink = out_link;
- outSrcQueue = new flitBuffer_d();
- out_link->setSourceQueue(outSrcQueue);
+ outNetLink = out_link;
+ outSrcQueue = new flitBuffer_d();
+ out_link->setSourceQueue(outSrcQueue);
}
-void NetworkInterface_d::addNode(vector<MessageBuffer*>& in, vector<MessageBuffer*>& out)
+void
+NetworkInterface_d::addNode(vector<MessageBuffer *>& in,
+ vector<MessageBuffer *>& out)
{
- ASSERT(in.size() == m_virtual_networks);
- inNode_ptr = in;
- outNode_ptr = out;
- for (int j = 0; j < m_virtual_networks; j++)
- {
- inNode_ptr[j]->setConsumer(this); // So that protocol injects messages into the NI
- }
+ ASSERT(in.size() == m_virtual_networks);
+ inNode_ptr = in;
+ outNode_ptr = out;
+ for (int j = 0; j < m_virtual_networks; j++) {
+
+ // the protocol injects messages into the NI
+ inNode_ptr[j]->setConsumer(this);
+ }
}
-bool NetworkInterface_d::flitisizeMessage(MsgPtr msg_ptr, int vnet)
+bool
+NetworkInterface_d::flitisizeMessage(MsgPtr msg_ptr, int vnet)
{
- NetworkMessage *net_msg_ptr =
- safe_cast<NetworkMessage *>(msg_ptr.get());
- NetDest net_msg_dest = net_msg_ptr->getInternalDestination();
- vector<NodeID> dest_nodes = net_msg_dest.getAllDest(); // gets all the destinations associated with this message.
-
- int num_flits = (int) ceil((double) m_net_ptr->MessageSizeType_to_int(net_msg_ptr->getMessageSize())/m_net_ptr->getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size
-
- for(int ctr = 0; ctr < dest_nodes.size(); ctr++) // loop because we will be converting all multicast messages into unicast messages
- {
- int vc = calculateVC(vnet); // this will return a free output virtual channel
- if(vc == -1)
- {
- return false ;
- }
- MsgPtr new_msg_ptr = msg_ptr->clone();
- NodeID destID = dest_nodes[ctr];
-
- NetworkMessage *new_net_msg_ptr =
- safe_cast<NetworkMessage *>(new_msg_ptr.get());
- if(dest_nodes.size() > 1)
- {
- NetDest personal_dest;
- for(int m = 0; m < (int) MachineType_NUM; m++)
- {
- if((destID >= MachineType_base_number((MachineType) m)) && destID < MachineType_base_number((MachineType) (m+1)))
- {
- // calculating the NetDest associated with this destination ID
- personal_dest.clear();
- personal_dest.add((MachineID) {(MachineType) m, (destID - MachineType_base_number((MachineType) m))});
- new_net_msg_ptr->getInternalDestination() = personal_dest;
- break;
- }
- }
- net_msg_dest.removeNetDest(personal_dest);
- net_msg_ptr->getInternalDestination().removeNetDest(personal_dest); // removing the destination from the original message to reflect that a message with this particular destination has been flitisized and an output vc is acquired
- }
- 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_ni_buffers[vc]->insert(fl);
+ NetworkMessage *net_msg_ptr = safe_cast<NetworkMessage *>(msg_ptr.get());
+ NetDest net_msg_dest = net_msg_ptr->getInternalDestination();
+
+ // gets all the destinations associated with this message.
+ vector<NodeID> dest_nodes = net_msg_dest.getAllDest();
+
+ // Number of flits is dependent on the link bandwidth available.
+ // This is expressed in terms of bytes/cycle or the flit size
+ int num_flits = (int) ceil((double) m_net_ptr->MessageSizeType_to_int(
+ net_msg_ptr->getMessageSize())/m_net_ptr->getFlitSize() );
+
+ // loop to convert all multicast messages into unicast messages
+ for (int ctr = 0; ctr < dest_nodes.size(); ctr++) {
+
+ // this will return a free output virtual channel
+ int vc = calculateVC(vnet);
+
+ if (vc == -1) {
+ return false ;
+ }
+ MsgPtr new_msg_ptr = msg_ptr->clone();
+ NodeID destID = dest_nodes[ctr];
+
+ NetworkMessage *new_net_msg_ptr =
+ safe_cast<NetworkMessage *>(new_msg_ptr.get());
+ if (dest_nodes.size() > 1) {
+ NetDest personal_dest;
+ for (int m = 0; m < (int) MachineType_NUM; m++) {
+ if ((destID >= MachineType_base_number((MachineType) m)) &&
+ destID < MachineType_base_number((MachineType) (m+1))) {
+ // calculating the NetDest associated with this destID
+ personal_dest.clear();
+ personal_dest.add((MachineID) {(MachineType) m, (destID -
+ MachineType_base_number((MachineType) m))});
+ new_net_msg_ptr->getInternalDestination() = personal_dest;
+ break;
}
- m_ni_enqueue_time[vc] = g_eventQueue_ptr->getTime();
- m_out_vc_state[vc]->setState(ACTIVE_, g_eventQueue_ptr->getTime());
+ }
+ net_msg_dest.removeNetDest(personal_dest);
+ // removing the destination from the original message to reflect
+ // that a message with this particular destination has been
+ // flitisized and an output vc is acquired
+ net_msg_ptr->getInternalDestination().removeNetDest(personal_dest);
+ }
+ 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_ni_buffers[vc]->insert(fl);
}
- return true ;
+ m_ni_enqueue_time[vc] = g_eventQueue_ptr->getTime();
+ m_out_vc_state[vc]->setState(ACTIVE_, g_eventQueue_ptr->getTime());
+ }
+ return true ;
}
// Looking for a free output vc
-int NetworkInterface_d::calculateVC(int vnet)
+int
+NetworkInterface_d::calculateVC(int vnet)
{
- for(int i = 0; i < m_vc_per_vnet; i++)
- {
+ for (int i = 0; i < m_vc_per_vnet; i++) {
int delta = m_vc_allocator[vnet];
m_vc_allocator[vnet]++;
if(m_vc_allocator[vnet] == m_vc_per_vnet)
m_vc_allocator[vnet] = 0;
- if(m_out_vc_state[(vnet*m_vc_per_vnet) + delta]->isInState(IDLE_, g_eventQueue_ptr->getTime()))
- {
+ if (m_out_vc_state[(vnet*m_vc_per_vnet) + delta]->isInState(
+ IDLE_, g_eventQueue_ptr->getTime())) {
return ((vnet*m_vc_per_vnet) + delta);
}
}
@@ -179,176 +193,178 @@ int NetworkInterface_d::calculateVC(int vnet)
}
/*
- * The NI wakeup checks whether there are any ready messages in the protocol buffer. If yes,
- * it picks that up, flitisizes it into a number of flits and puts it into an output buffer
- * and schedules the output link. On a wakeup it also checks whether there are flits in the
- * input link. If yes, it picks them up and if the flit is a tail, the NI inserts the
- * corresponding message into the protocol buffer. It also checks for credits being sent
- * by the downstream router.
+ * The NI wakeup checks whether there are any ready messages in the protocol
+ * buffer. If yes, it picks that up, flitisizes it into a number of flits and
+ * puts it into an output buffer and schedules the output link. On a wakeup
+ * it also checks whether there are flits in the input link. If yes, it picks
+ * them up and if the flit is a tail, the NI inserts the corresponding message
+ * into the protocol buffer. It also checks for credits being sent by the
+ * downstream router.
*/
-void NetworkInterface_d::wakeup()
+void
+NetworkInterface_d::wakeup()
{
- DEBUG_EXPR(NETWORK_COMP, MedPrio, m_id);
- DEBUG_MSG(NETWORK_COMP, MedPrio, "NI WOKE UP");
- DEBUG_EXPR(NETWORK_COMP, MedPrio, g_eventQueue_ptr->getTime());
-
- MsgPtr msg_ptr;
-
- //Checking for messages coming from the protocol
- for (int vnet = 0; vnet < m_virtual_networks; vnet++) // can pick up a message/cycle for each virtual net
- {
- while(inNode_ptr[vnet]->isReady()) // Is there a message waiting
- {
- msg_ptr = inNode_ptr[vnet]->peekMsgPtr();
- if(flitisizeMessage(msg_ptr, vnet))
- {
- inNode_ptr[vnet]->pop();
- }
- else
- {
- break;
- }
- }
+ DEBUG_EXPR(NETWORK_COMP, MedPrio, m_id);
+ DEBUG_MSG(NETWORK_COMP, MedPrio, "NI WOKE UP");
+ DEBUG_EXPR(NETWORK_COMP, MedPrio, g_eventQueue_ptr->getTime());
+
+ 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();
+ if (flitisizeMessage(msg_ptr, vnet)) {
+ inNode_ptr[vnet]->pop();
+ } else {
+ break;
+ }
}
-
- scheduleOutputLink();
- checkReschedule();
-
-/*********** Picking messages destined for this NI **********/
-
- if(inNetLink->isReady())
- {
- 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;
- if(!m_net_ptr->isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers
- {
- outNode_ptr[t_flit->get_vnet()]->enqueue(t_flit->get_msg_ptr(), 1); // enqueueing for protocol buffer. This is not required when doing network only testing
- }
- }
- flit_d *credit_flit = new flit_d(t_flit->get_vc(), free_signal); // Simply send a credit back since we are not buddering this flit in the NI
- creditQueue->insert(credit_flit);
- g_eventQueue_ptr->scheduleEvent(m_ni_credit_link, 1);
-
- m_net_ptr->increment_recieved_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);
- delete t_flit;
+ }
+
+ scheduleOutputLink();
+ checkReschedule();
+
+ /*********** Picking messages destined for this NI **********/
+
+ if (inNetLink->isReady()) {
+ 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;
+ // When we are doing network only testing, the messages do not
+ // have to be buffered into the protocol buffers
+ if (!m_net_ptr->isNetworkTesting()) {
+ outNode_ptr[t_flit->get_vnet()]->
+ enqueue(t_flit->get_msg_ptr(), 1);
+ }
}
-
- /****************** Checking for credit link *******/
-
- if(m_credit_link->isReady())
- {
- 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());
- }
- delete t_flit;
- }
+ // 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);
+ 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);
+ delete t_flit;
+ }
+
+ /****************** Checking for credit link *******/
+
+ if (m_credit_link->isReady()) {
+ 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());
+ }
+ delete t_flit;
+ }
}
-// This function look at the NI buffers and if some buffer has flits which are ready to traverse the link in the next cycle and also the downstream output vc associated with this flit has buffers left, the link is scheduled for the next cycle
+/** This function looks at the NI buffers
+ * if some buffer has flits which are ready to traverse the link in the next
+ * cycle, and the downstream output vc associated with this flit has buffers
+ * left, the link is scheduled for the next cycle
+ */
-void NetworkInterface_d::scheduleOutputLink()
+void
+NetworkInterface_d::scheduleOutputLink()
{
- int vc = m_vc_round_robin;
- m_vc_round_robin++;
- if(m_vc_round_robin == m_num_vcs)
- m_vc_round_robin = 0;
-
- for(int i = 0; i < m_num_vcs; i++)
- {
- vc++;
- if(vc == m_num_vcs)
- vc = 0;
- if(m_ni_buffers[vc]->isReady() && m_out_vc_state[vc]->has_credits()) // models buffer backpressure
- {
- bool is_candidate_vc = true;
- int t_vnet = get_vnet(vc);
- int vc_base = t_vnet * m_vc_per_vnet;
-
- if(m_net_ptr->isVNetOrdered(t_vnet))
- {
- 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_enqueue_time[t_vc] < m_ni_enqueue_time[vc])
- {
- is_candidate_vc = false;
- break;
- }
- }
- }
- }
- if(!is_candidate_vc)
- continue;
-
- m_out_vc_state[vc]->decrement_credit();
- flit_d *t_flit = m_ni_buffers[vc]->getTopFlit(); // Just removing the flit
- t_flit->set_time(g_eventQueue_ptr->getTime() + 1);
- outSrcQueue->insert(t_flit);
- g_eventQueue_ptr->scheduleEvent(outNetLink, 1); // schedule the out link
-
- if(t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_)
- {
- m_ni_enqueue_time[vc] = INFINITE_;
+ int vc = m_vc_round_robin;
+ m_vc_round_robin++;
+ if (m_vc_round_robin == m_num_vcs)
+ m_vc_round_robin = 0;
+
+ for (int i = 0; i < m_num_vcs; i++) {
+ vc++;
+ if (vc == m_num_vcs)
+ vc = 0;
+
+ // model buffer backpressure
+ if (m_ni_buffers[vc]->isReady() && 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;
+
+ if (m_net_ptr->isVNetOrdered(t_vnet)) {
+ 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_enqueue_time[t_vc] < m_ni_enqueue_time[vc]) {
+ is_candidate_vc = false;
+ break;
}
- return;
+ }
}
+ }
+ if (!is_candidate_vc)
+ continue;
+
+ 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);
+ outSrcQueue->insert(t_flit);
+ // schedule the out link
+ g_eventQueue_ptr->scheduleEvent(outNetLink, 1);
+
+ if (t_flit->get_type() == TAIL_ ||
+ t_flit->get_type() == HEAD_TAIL_) {
+ m_ni_enqueue_time[vc] = INFINITE_;
+ }
+ return;
}
+ }
}
-int NetworkInterface_d::get_vnet(int vc)
+int
+NetworkInterface_d::get_vnet(int vc)
{
- for(int i = 0; i < m_net_ptr->getNumberOfVirtualNetworks(); i++)
- {
- if(vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet))
- {
- return i;
- }
+ for (int i = 0; i < m_net_ptr->getNumberOfVirtualNetworks(); i++) {
+ if (vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) {
+ return i;
}
- ERROR_MSG("Could not determine vc");
- return -1;
+ }
+ ERROR_MSG("Could not determine vc");
+ return -1;
}
-void NetworkInterface_d::checkReschedule()
+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);
- return;
- }
+ 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);
+ return;
}
- for(int vc = 0; vc < m_num_vcs; vc++)
- {
- if(m_ni_buffers[vc]->isReadyForNext())
- {
- g_eventQueue_ptr->scheduleEvent(this, 1);
- return;
- }
+ }
+ for (int vc = 0; vc < m_num_vcs; vc++) {
+ if (m_ni_buffers[vc]->isReadyForNext()) {
+ g_eventQueue_ptr->scheduleEvent(this, 1);
+ return;
}
+ }
}
-void NetworkInterface_d::printConfig(std::ostream& out) const
+void
+NetworkInterface_d::printConfig(std::ostream& out) const
{
- out << "[Network Interface " << m_id << "] - ";
- out << "[inLink " << inNetLink->get_id() << "] - ";
- out << "[outLink " << outNetLink->get_id() << "]" << std::endl;
+ out << "[Network Interface " << m_id << "] - ";
+ out << "[inLink " << inNetLink->get_id() << "] - ";
+ out << "[outLink " << outNetLink->get_id() << "]" << std::endl;
}
-void NetworkInterface_d::print(std::ostream& out) const
+void
+NetworkInterface_d::print(std::ostream& out) const
{
- out << "[Network Interface]";
+ out << "[Network Interface]";
}