52c52
< : Consumer(sw), m_switch_id(sid), m_switch(sw)
---
> : Consumer(sw)
53a54
> m_switch_id = sid;
105a107,109
> MsgPtr msg_ptr;
> Message *net_msg_ptr = NULL;
>
121a126,129
> // temporary vectors to store the routing results
> vector<LinkID> output_links;
> vector<NetDest> output_link_destinations;
>
132,135c140,141
< operateMessageBuffer(buffer, incoming, vnet);
< }
< }
< }
---
> while (buffer->isReady()) {
> DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
137,142c143,146
< void
< PerfectSwitch::operateMessageBuffer(MessageBuffer *buffer, int incoming,
< int vnet)
< {
< MsgPtr msg_ptr;
< Message *net_msg_ptr = NULL;
---
> // Peek at message
> msg_ptr = buffer->peekMsgPtr();
> net_msg_ptr = msg_ptr.get();
> DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
144,146c148,150
< // temporary vectors to store the routing results
< vector<LinkID> output_links;
< vector<NetDest> output_link_destinations;
---
> output_links.clear();
> output_link_destinations.clear();
> NetDest msg_dsts = net_msg_ptr->getDestination();
148,149c152,154
< while (buffer->isReady()) {
< DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
---
> // Unfortunately, the token-protocol sends some
> // zero-destination messages, so this assert isn't valid
> // assert(msg_dsts.count() > 0);
151,154c156,157
< // Peek at message
< msg_ptr = buffer->peekMsgPtr();
< net_msg_ptr = msg_ptr.get();
< DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
---
> assert(m_link_order.size() == m_routing_table.size());
> assert(m_link_order.size() == m_out.size());
156,158c159,178
< output_links.clear();
< output_link_destinations.clear();
< NetDest msg_dsts = net_msg_ptr->getDestination();
---
> 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;
> }
160,179c180,181
< // 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();
---
> // Look at the most empty link first
> sort(m_link_order.begin(), m_link_order.end());
181,185d182
< 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;
188,191c185,189
< // Look at the most empty link first
< sort(m_link_order.begin(), m_link_order.end());
< }
< }
---
> 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,197c191,192
< 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);
---
> if (!msg_dsts.intersectionIsNotEmpty(dst))
> continue;
199,200c194,195
< if (!msg_dsts.intersectionIsNotEmpty(dst))
< continue;
---
> // Remember what link we're using
> output_links.push_back(link);
202,203c197,201
< // Remember what link we're using
< output_links.push_back(link);
---
> // 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));
205,209c203,206
< // 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));
---
> // Next, we update the msg_destination not to include
> // those nodes that were already handled by this link
> msg_dsts.removeNetDest(dst);
> }
211,214c208
< // Next, we update the msg_destination not to include
< // those nodes that were already handled by this link
< msg_dsts.removeNetDest(dst);
< }
---
> assert(msg_dsts.count() == 0);
216c210,213
< assert(msg_dsts.count() == 0);
---
> // Check for resources - for all outgoing queues
> bool enough = true;
> for (int i = 0; i < output_links.size(); i++) {
> int outgoing = output_links[i];
218,221c215,216
< // 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;
223,224c218,221
< 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);
> }
226,229c223,230
< DPRINTF(RubyNetwork, "Checking if node is blocked ..."
< "outgoing: %d, vnet: %d, enough: %d\n",
< outgoing, vnet, enough);
< }
---
> // 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
> }
231,238c232
< // 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
< }
---
> MsgPtr unmodified_msg_ptr;
240c234,239
< MsgPtr unmodified_msg_ptr;
---
> 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
242,247c241,243
< 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
---
> // This magic line creates a private copy of the message
> unmodified_msg_ptr = msg_ptr->clone();
> }
249,251c245,247
< // This magic line creates a private copy of the message
< unmodified_msg_ptr = msg_ptr->clone();
< }
---
> // Dequeue msg
> buffer->dequeue();
> m_pending_message_count[vnet]--;
253,255c249,251
< // Dequeue msg
< buffer->dequeue();
< m_pending_message_count[vnet]--;
---
> // Enqueue it - for all outgoing queues
> for (int i=0; i<output_links.size(); i++) {
> int outgoing = output_links[i];
257,259c253,256
< // Enqueue it - for all outgoing queues
< for (int i=0; i<output_links.size(); i++) {
< int outgoing = output_links[i];
---
> if (i > 0) {
> // create a private copy of the unmodified message
> msg_ptr = unmodified_msg_ptr->clone();
> }
261,264c258,262
< if (i > 0) {
< // create a private copy of the unmodified message
< msg_ptr = unmodified_msg_ptr->clone();
< }
---
> // 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];
266,269c264,267
< // 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];
---
> // Enqeue msg
> DPRINTF(RubyNetwork, "Enqueuing net msg from "
> "inport[%d][%d] to outport [%d][%d].\n",
> incoming, vnet, outgoing, vnet);
271,276c269,271
< // 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);
---
> m_out[outgoing][vnet]->enqueue(msg_ptr);
> }
> }