107c107
< PerfectSwitch::wakeup()
---
> PerfectSwitch::operateVnet(int vnet)
110,115d109
<
< // Give the highest numbered link priority most of the time
< m_wakeups_wo_switch++;
< int highest_prio_vnet = m_virtual_networks-1;
< int lowest_prio_vnet = 0;
< int decrementer = 1;
118,123c112,116
< // invert priorities to avoid starvation seen in the component network
< if (m_wakeups_wo_switch > PRIORITY_SWITCH_LIMIT) {
< m_wakeups_wo_switch = 0;
< highest_prio_vnet = 0;
< lowest_prio_vnet = m_virtual_networks-1;
< decrementer = -1;
---
> // This is for round-robin scheduling
> int incoming = m_round_robin_start;
> m_round_robin_start++;
> if (m_round_robin_start >= m_in.size()) {
> m_round_robin_start = 0;
126,129c119,126
< // For all components incoming queues
< for (int vnet = highest_prio_vnet;
< (vnet * decrementer) >= (decrementer * lowest_prio_vnet);
< vnet -= decrementer) {
---
> if(m_pending_message_count[vnet] > 0) {
> // for all input ports, use round robin scheduling
> for (int counter = 0; counter < m_in.size(); counter++) {
> // Round robin scheduling
> incoming++;
> if (incoming >= m_in.size()) {
> incoming = 0;
> }
131,136c128,130
< // This is for round-robin scheduling
< int incoming = m_round_robin_start;
< m_round_robin_start++;
< if (m_round_robin_start >= m_in.size()) {
< m_round_robin_start = 0;
< }
---
> // temporary vectors to store the routing results
> vector<LinkID> output_links;
> vector<NetDest> output_link_destinations;
138,145c132,136
< if(m_pending_message_count[vnet] > 0) {
< // for all input ports, use round robin scheduling
< for (int counter = 0; counter < m_in.size(); counter++) {
< // Round robin scheduling
< incoming++;
< if (incoming >= m_in.size()) {
< incoming = 0;
< }
---
> // Is there a message waiting?
> auto it = m_in[incoming].find(vnet);
> if (it == m_in[incoming].end())
> continue;
> MessageBuffer *buffer = (*it).second;
147,149c138,139
< // temporary vectors to store the routing results
< vector<LinkID> output_links;
< vector<NetDest> output_link_destinations;
---
> while (buffer->isReady()) {
> DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
151,155c141,144
< // Is there a message waiting?
< auto it = m_in[incoming].find(vnet);
< if (it == m_in[incoming].end())
< continue;
< MessageBuffer *buffer = (*it).second;
---
> // Peek at message
> msg_ptr = buffer->peekMsgPtr();
> net_msg_ptr = safe_cast<NetworkMessage*>(msg_ptr.get());
> DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
157,158c146,148
< while (buffer->isReady()) {
< DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
---
> output_links.clear();
> output_link_destinations.clear();
> NetDest msg_dsts = net_msg_ptr->getInternalDestination();
160,163c150,152
< // Peek at message
< msg_ptr = buffer->peekMsgPtr();
< net_msg_ptr = safe_cast<NetworkMessage*>(msg_ptr.get());
< DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
---
> // Unfortunately, the token-protocol sends some
> // zero-destination messages, so this assert isn't valid
> // assert(msg_dsts.count() > 0);
165,168c154,155
< output_links.clear();
< output_link_destinations.clear();
< NetDest msg_dsts =
< net_msg_ptr->getInternalDestination();
---
> assert(m_link_order.size() == m_routing_table.size());
> assert(m_link_order.size() == m_out.size());
170,182c157,169
< // Unfortunately, the token-protocol sends some
< // zero-destination messages, so this assert isn't valid
< // assert(msg_dsts.count() > 0);
<
< assert(m_link_order.size() == m_routing_table.size());
< assert(m_link_order.size() == m_out.size());
<
< if (m_network_ptr->getAdaptiveRouting()) {
< if (m_network_ptr->isVNetOrdered(vnet)) {
< // Don't adaptively route
< for (int out = 0; out < m_out.size(); out++) {
< m_link_order[out].m_link = out;
< m_link_order[out].m_value = 0;
---
> if (m_network_ptr->getAdaptiveRouting()) {
> if (m_network_ptr->isVNetOrdered(vnet)) {
> // Don't adaptively route
> for (int out = 0; out < m_out.size(); out++) {
> m_link_order[out].m_link = out;
> m_link_order[out].m_value = 0;
> }
> } else {
> // Find how clogged each link is
> for (int out = 0; out < m_out.size(); out++) {
> int out_queue_length = 0;
> for (int v = 0; v < m_virtual_networks; v++) {
> out_queue_length += m_out[out][v]->getSize();
184,198c171,174
< } else {
< // Find how clogged each link is
< for (int out = 0; out < m_out.size(); out++) {
< int out_queue_length = 0;
< for (int v = 0; v < m_virtual_networks; v++) {
< out_queue_length += m_out[out][v]->getSize();
< }
< int value =
< (out_queue_length << 8) | (random() & 0xff);
< m_link_order[out].m_link = out;
< m_link_order[out].m_value = value;
< }
<
< // Look at the most empty link first
< sort(m_link_order.begin(), m_link_order.end());
---
> int value =
> (out_queue_length << 8) | (random() & 0xff);
> m_link_order[out].m_link = out;
> m_link_order[out].m_value = value;
199a176,178
>
> // Look at the most empty link first
> sort(m_link_order.begin(), m_link_order.end());
200a180
> }
202,206c182,186
< for (int i = 0; i < m_routing_table.size(); i++) {
< // pick the next link to look at
< int link = m_link_order[i].m_link;
< NetDest dst = m_routing_table[link];
< DPRINTF(RubyNetwork, "dst: %s\n", dst);
---
> for (int i = 0; i < m_routing_table.size(); i++) {
> // pick the next link to look at
> int link = m_link_order[i].m_link;
> NetDest dst = m_routing_table[link];
> DPRINTF(RubyNetwork, "dst: %s\n", dst);
208,209c188,189
< if (!msg_dsts.intersectionIsNotEmpty(dst))
< continue;
---
> if (!msg_dsts.intersectionIsNotEmpty(dst))
> continue;
211,212c191,192
< // Remember what link we're using
< output_links.push_back(link);
---
> // Remember what link we're using
> output_links.push_back(link);
214,219c194,198
< // Need to remember which destinations need this
< // message in another vector. This Set is the
< // intersection of the routing_table entry and the
< // current destination set. The intersection must
< // not be empty, since we are inside "if"
< output_link_destinations.push_back(msg_dsts.AND(dst));
---
> // Need to remember which destinations need this message in
> // another vector. This Set is the intersection of the
> // routing_table entry and the current destination set. The
> // intersection must not be empty, since we are inside "if"
> output_link_destinations.push_back(msg_dsts.AND(dst));
221,225c200,203
< // Next, we update the msg_destination not to
< // include those nodes that were already handled
< // by this link
< msg_dsts.removeNetDest(dst);
< }
---
> // Next, we update the msg_destination not to include
> // those nodes that were already handled by this link
> msg_dsts.removeNetDest(dst);
> }
227,228c205
< assert(msg_dsts.count() == 0);
< //assert(output_links.size() > 0);
---
> assert(msg_dsts.count() == 0);
230,239c207,210
< // Check for resources - for all outgoing queues
< bool enough = true;
< for (int i = 0; i < output_links.size(); i++) {
< int outgoing = output_links[i];
< if (!m_out[outgoing][vnet]->areNSlotsAvailable(1))
< enough = false;
< DPRINTF(RubyNetwork, "Checking if node is blocked ..."
< "outgoing: %d, vnet: %d, enough: %d\n",
< outgoing, vnet, enough);
< }
---
> // Check for resources - for all outgoing queues
> bool enough = true;
> for (int i = 0; i < output_links.size(); i++) {
> int outgoing = output_links[i];
241,248c212,213
< // There were not enough resources
< if (!enough) {
< scheduleEvent(Cycles(1));
< DPRINTF(RubyNetwork, "Can't deliver message since a node "
< "is blocked\n");
< DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
< break; // go to next incoming port
< }
---
> if (!m_out[outgoing][vnet]->areNSlotsAvailable(1))
> enough = false;
250c215,218
< MsgPtr unmodified_msg_ptr;
---
> DPRINTF(RubyNetwork, "Checking if node is blocked ..."
> "outgoing: %d, vnet: %d, enough: %d\n",
> outgoing, vnet, enough);
> }
252,258c220,227
< if (output_links.size() > 1) {
< // If we are sending this message down more than
< // one link (size>1), we need to make a copy of
< // the message so each branch can have a different
< // internal destination we need to create an
< // unmodified MsgPtr because the MessageBuffer
< // enqueue func will modify the message
---
> // There were not enough resources
> if (!enough) {
> scheduleEvent(Cycles(1));
> DPRINTF(RubyNetwork, "Can't deliver message since a node "
> "is blocked\n");
> DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
> break; // go to next incoming port
> }
260,263c229
< // This magic line creates a private copy of the
< // message
< unmodified_msg_ptr = msg_ptr->clone();
< }
---
> MsgPtr unmodified_msg_ptr;
265,267c231,236
< // Dequeue msg
< buffer->dequeue();
< m_pending_message_count[vnet]--;
---
> if (output_links.size() > 1) {
> // If we are sending this message down more than one link
> // (size>1), we need to make a copy of the message so each
> // branch can have a different internal destination we need
> // to create an unmodified MsgPtr because the MessageBuffer
> // enqueue func will modify the message
269,271c238,240
< // Enqueue it - for all outgoing queues
< for (int i=0; i<output_links.size(); i++) {
< int outgoing = output_links[i];
---
> // This magic line creates a private copy of the message
> unmodified_msg_ptr = msg_ptr->clone();
> }
273,277c242,244
< if (i > 0) {
< // create a private copy of the unmodified
< // message
< msg_ptr = unmodified_msg_ptr->clone();
< }
---
> // Dequeue msg
> buffer->dequeue();
> m_pending_message_count[vnet]--;
279,284c246,248
< // Change the internal destination set of the
< // message so it knows which destinations this
< // link is responsible for.
< net_msg_ptr = safe_cast<NetworkMessage*>(msg_ptr.get());
< net_msg_ptr->getInternalDestination() =
< output_link_destinations[i];
---
> // Enqueue it - for all outgoing queues
> for (int i=0; i<output_links.size(); i++) {
> int outgoing = output_links[i];
286,291c250,252
< // Enqeue msg
< DPRINTF(RubyNetwork, "Enqueuing net msg from "
< "inport[%d][%d] to outport [%d][%d].\n",
< incoming, vnet, outgoing, vnet);
<
< m_out[outgoing][vnet]->enqueue(msg_ptr);
---
> if (i > 0) {
> // create a private copy of the unmodified message
> msg_ptr = unmodified_msg_ptr->clone();
292a254,266
>
> // Change the internal destination set of the message so it
> // knows which destinations this link is responsible for.
> net_msg_ptr = safe_cast<NetworkMessage*>(msg_ptr.get());
> net_msg_ptr->getInternalDestination() =
> output_link_destinations[i];
>
> // Enqeue msg
> DPRINTF(RubyNetwork, "Enqueuing net msg from "
> "inport[%d][%d] to outport [%d][%d].\n",
> incoming, vnet, outgoing, vnet);
>
> m_out[outgoing][vnet]->enqueue(msg_ptr);
299a274,298
> PerfectSwitch::wakeup()
> {
> // Give the highest numbered link priority most of the time
> m_wakeups_wo_switch++;
> int highest_prio_vnet = m_virtual_networks-1;
> int lowest_prio_vnet = 0;
> int decrementer = 1;
>
> // invert priorities to avoid starvation seen in the component network
> if (m_wakeups_wo_switch > PRIORITY_SWITCH_LIMIT) {
> m_wakeups_wo_switch = 0;
> highest_prio_vnet = 0;
> lowest_prio_vnet = m_virtual_networks-1;
> decrementer = -1;
> }
>
> // For all components incoming queues
> for (int vnet = highest_prio_vnet;
> (vnet * decrementer) >= (decrementer * lowest_prio_vnet);
> vnet -= decrementer) {
> operateVnet(vnet);
> }
> }
>
> void