106,108d105
< MsgPtr msg_ptr;
< Message *net_msg_ptr = NULL;
<
125,128d121
< // temporary vectors to store the routing results
< vector<LinkID> output_links;
< vector<NetDest> output_link_destinations;
<
139,140c132,135
< while (buffer->isReady()) {
< DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
---
> operateMessageBuffer(buffer, incoming, vnet);
> }
> }
> }
142,145c137,142
< // Peek at message
< msg_ptr = buffer->peekMsgPtr();
< net_msg_ptr = msg_ptr.get();
< DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
---
> void
> PerfectSwitch::operateMessageBuffer(MessageBuffer *buffer, int incoming,
> int vnet)
> {
> MsgPtr msg_ptr;
> Message *net_msg_ptr = NULL;
147,149c144,146
< output_links.clear();
< output_link_destinations.clear();
< NetDest msg_dsts = net_msg_ptr->getDestination();
---
> // temporary vectors to store the routing results
> vector<LinkID> output_links;
> vector<NetDest> output_link_destinations;
151,153c148,149
< // Unfortunately, the token-protocol sends some
< // zero-destination messages, so this assert isn't valid
< // assert(msg_dsts.count() > 0);
---
> while (buffer->isReady()) {
> DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
155,156c151,154
< assert(m_link_order.size() == m_routing_table.size());
< assert(m_link_order.size() == m_out.size());
---
> // Peek at message
> msg_ptr = buffer->peekMsgPtr();
> net_msg_ptr = msg_ptr.get();
> DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
158,177c156,158
< 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();
< }
< int value =
< (out_queue_length << 8) |
< random_mt.random(0, 0xff);
< m_link_order[out].m_link = out;
< m_link_order[out].m_value = value;
< }
---
> output_links.clear();
> output_link_destinations.clear();
> NetDest msg_dsts = net_msg_ptr->getDestination();
179,180c160,179
< // Look at the most empty link first
< sort(m_link_order.begin(), m_link_order.end());
---
> // 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;
> }
> } 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();
181a181,185
> int value =
> (out_queue_length << 8) |
> random_mt.random(0, 0xff);
> m_link_order[out].m_link = out;
> m_link_order[out].m_value = value;
184,188c188,191
< 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);
---
> // Look at the most empty link first
> sort(m_link_order.begin(), m_link_order.end());
> }
> }
190,191c193,197
< if (!msg_dsts.intersectionIsNotEmpty(dst))
< continue;
---
> 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);
193,194c199,200
< // Remember what link we're using
< output_links.push_back(link);
---
> if (!msg_dsts.intersectionIsNotEmpty(dst))
> continue;
196,200c202,203
< // 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));
---
> // Remember what link we're using
> output_links.push_back(link);
202,205c205,209
< // Next, we update the msg_destination not to include
< // those nodes that were already handled by this link
< msg_dsts.removeNetDest(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));
207c211,214
< assert(msg_dsts.count() == 0);
---
> // Next, we update the msg_destination not to include
> // those nodes that were already handled by this link
> msg_dsts.removeNetDest(dst);
> }
209,212c216
< // Check for resources - for all outgoing queues
< bool enough = true;
< for (int i = 0; i < output_links.size(); i++) {
< int outgoing = output_links[i];
---
> assert(msg_dsts.count() == 0);
214,215c218,221
< if (!m_out[outgoing][vnet]->areNSlotsAvailable(1))
< enough = false;
---
> // Check for resources - for all outgoing queues
> bool enough = true;
> for (int i = 0; i < output_links.size(); i++) {
> int outgoing = output_links[i];
217,220c223,224
< DPRINTF(RubyNetwork, "Checking if node is blocked ..."
< "outgoing: %d, vnet: %d, enough: %d\n",
< outgoing, vnet, enough);
< }
---
> if (!m_out[outgoing][vnet]->areNSlotsAvailable(1))
> enough = false;
222,229c226,229
< // 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
< }
---
> DPRINTF(RubyNetwork, "Checking if node is blocked ..."
> "outgoing: %d, vnet: %d, enough: %d\n",
> outgoing, vnet, enough);
> }
231c231,238
< MsgPtr unmodified_msg_ptr;
---
> // 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
> }
233,238c240
< 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
---
> MsgPtr unmodified_msg_ptr;
240,242c242,247
< // This magic line creates a private copy of the message
< unmodified_msg_ptr = msg_ptr->clone();
< }
---
> 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
244,246c249,251
< // Dequeue msg
< buffer->dequeue();
< m_pending_message_count[vnet]--;
---
> // This magic line creates a private copy of the message
> unmodified_msg_ptr = msg_ptr->clone();
> }
248,250c253,255
< // Enqueue it - for all outgoing queues
< for (int i=0; i<output_links.size(); i++) {
< int outgoing = output_links[i];
---
> // Dequeue msg
> buffer->dequeue();
> m_pending_message_count[vnet]--;
252,255c257,259
< if (i > 0) {
< // create a private copy of the unmodified message
< msg_ptr = unmodified_msg_ptr->clone();
< }
---
> // Enqueue it - for all outgoing queues
> for (int i=0; i<output_links.size(); i++) {
> int outgoing = output_links[i];
257,261c261,264
< // Change the internal destination set of the message so it
< // knows which destinations this link is responsible for.
< net_msg_ptr = msg_ptr.get();
< net_msg_ptr->getDestination() =
< output_link_destinations[i];
---
> if (i > 0) {
> // create a private copy of the unmodified message
> msg_ptr = unmodified_msg_ptr->clone();
> }
263,266c266,269
< // Enqeue msg
< DPRINTF(RubyNetwork, "Enqueuing net msg from "
< "inport[%d][%d] to outport [%d][%d].\n",
< incoming, vnet, outgoing, vnet);
---
> // Change the internal destination set of the message so it
> // knows which destinations this link is responsible for.
> net_msg_ptr = msg_ptr.get();
> net_msg_ptr->getDestination() = output_link_destinations[i];
268,270c271,276
< m_out[outgoing][vnet]->enqueue(msg_ptr);
< }
< }
---
> // 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);