gem5  v21.0.1.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
PerfectSwitch.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
30 
31 #include <algorithm>
32 
33 #include "base/cast.hh"
34 #include "base/cprintf.hh"
35 #include "base/random.hh"
36 #include "debug/RubyNetwork.hh"
41 
42 const int PRIORITY_SWITCH_LIMIT = 128;
43 
44 // Operator for helper class
45 bool
47 {
48  return (l1.m_value < l2.m_value);
49 }
50 
51 PerfectSwitch::PerfectSwitch(SwitchID sid, Switch *sw, uint32_t virt_nets)
52  : Consumer(sw), m_switch_id(sid), m_switch(sw)
53 {
56  m_virtual_networks = virt_nets;
57 }
58 
59 void
61 {
62  m_network_ptr = network_ptr;
63 
64  for (int i = 0;i < m_virtual_networks;++i) {
65  m_pending_message_count.push_back(0);
66  }
67 }
68 
69 void
71 {
72  NodeID port = m_in.size();
73  m_in.push_back(in);
74 
75  for (int i = 0; i < in.size(); ++i) {
76  if (in[i] != nullptr) {
77  in[i]->setConsumer(this);
78  in[i]->setIncomingLink(port);
79  in[i]->setVnet(i);
80  }
81  }
82 }
83 
84 void
86  const NetDest& routing_table_entry)
87 {
88  // Setup link order
89  LinkOrder l;
90  l.m_value = 0;
91  l.m_link = m_out.size();
92  m_link_order.push_back(l);
93 
94  // Add to routing table
95  m_out.push_back(out);
96  m_routing_table.push_back(routing_table_entry);
97 }
98 
100 {
101 }
102 
103 void
105 {
106  // This is for round-robin scheduling
107  int incoming = m_round_robin_start;
109  if (m_round_robin_start >= m_in.size()) {
111  }
112 
113  if (m_pending_message_count[vnet] > 0) {
114  // for all input ports, use round robin scheduling
115  for (int counter = 0; counter < m_in.size(); counter++) {
116  // Round robin scheduling
117  incoming++;
118  if (incoming >= m_in.size()) {
119  incoming = 0;
120  }
121 
122  // Is there a message waiting?
123  if (m_in[incoming].size() <= vnet) {
124  continue;
125  }
126 
127  MessageBuffer *buffer = m_in[incoming][vnet];
128  if (buffer == nullptr) {
129  continue;
130  }
131 
132  operateMessageBuffer(buffer, incoming, vnet);
133  }
134  }
135 }
136 
137 void
139  int vnet)
140 {
141  MsgPtr msg_ptr;
142  Message *net_msg_ptr = NULL;
143 
144  // temporary vectors to store the routing results
145  std::vector<LinkID> output_links;
146  std::vector<NetDest> output_link_destinations;
147  Tick current_time = m_switch->clockEdge();
148 
149  while (buffer->isReady(current_time)) {
150  DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
151 
152  // Peek at message
153  msg_ptr = buffer->peekMsgPtr();
154  net_msg_ptr = msg_ptr.get();
155  DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
156 
157  output_links.clear();
158  output_link_destinations.clear();
159  NetDest msg_dsts = net_msg_ptr->getDestination();
160 
161  // Unfortunately, the token-protocol sends some
162  // zero-destination messages, so this assert isn't valid
163  // assert(msg_dsts.count() > 0);
164 
165  assert(m_link_order.size() == m_routing_table.size());
166  assert(m_link_order.size() == m_out.size());
167 
169  if (m_network_ptr->isVNetOrdered(vnet)) {
170  // Don't adaptively route
171  for (int out = 0; out < m_out.size(); out++) {
172  m_link_order[out].m_link = out;
173  m_link_order[out].m_value = 0;
174  }
175  } else {
176  // Find how clogged each link is
177  for (int out = 0; out < m_out.size(); out++) {
178  int out_queue_length = 0;
179  for (int v = 0; v < m_virtual_networks; v++) {
180  out_queue_length += m_out[out][v]->getSize(current_time);
181  }
182  int value =
183  (out_queue_length << 8) |
184  random_mt.random(0, 0xff);
185  m_link_order[out].m_link = out;
186  m_link_order[out].m_value = value;
187  }
188 
189  // Look at the most empty link first
190  sort(m_link_order.begin(), m_link_order.end());
191  }
192  }
193 
194  for (int i = 0; i < m_routing_table.size(); i++) {
195  // pick the next link to look at
196  int link = m_link_order[i].m_link;
197  NetDest dst = m_routing_table[link];
198  DPRINTF(RubyNetwork, "dst: %s\n", dst);
199 
200  if (!msg_dsts.intersectionIsNotEmpty(dst))
201  continue;
202 
203  // Remember what link we're using
204  output_links.push_back(link);
205 
206  // Need to remember which destinations need this message in
207  // another vector. This Set is the intersection of the
208  // routing_table entry and the current destination set. The
209  // intersection must not be empty, since we are inside "if"
210  output_link_destinations.push_back(msg_dsts.AND(dst));
211 
212  // Next, we update the msg_destination not to include
213  // those nodes that were already handled by this link
214  msg_dsts.removeNetDest(dst);
215  }
216 
217  assert(msg_dsts.count() == 0);
218 
219  // Check for resources - for all outgoing queues
220  bool enough = true;
221  for (int i = 0; i < output_links.size(); i++) {
222  int outgoing = output_links[i];
223 
224  if (!m_out[outgoing][vnet]->areNSlotsAvailable(1, current_time))
225  enough = false;
226 
227  DPRINTF(RubyNetwork, "Checking if node is blocked ..."
228  "outgoing: %d, vnet: %d, enough: %d\n",
229  outgoing, vnet, enough);
230  }
231 
232  // There were not enough resources
233  if (!enough) {
234  scheduleEvent(Cycles(1));
235  DPRINTF(RubyNetwork, "Can't deliver message since a node "
236  "is blocked\n");
237  DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
238  break; // go to next incoming port
239  }
240 
241  MsgPtr unmodified_msg_ptr;
242 
243  if (output_links.size() > 1) {
244  // If we are sending this message down more than one link
245  // (size>1), we need to make a copy of the message so each
246  // branch can have a different internal destination we need
247  // to create an unmodified MsgPtr because the MessageBuffer
248  // enqueue func will modify the message
249 
250  // This magic line creates a private copy of the message
251  unmodified_msg_ptr = msg_ptr->clone();
252  }
253 
254  // Dequeue msg
255  buffer->dequeue(current_time);
256  m_pending_message_count[vnet]--;
257 
258  // Enqueue it - for all outgoing queues
259  for (int i=0; i<output_links.size(); i++) {
260  int outgoing = output_links[i];
261 
262  if (i > 0) {
263  // create a private copy of the unmodified message
264  msg_ptr = unmodified_msg_ptr->clone();
265  }
266 
267  // Change the internal destination set of the message so it
268  // knows which destinations this link is responsible for.
269  net_msg_ptr = msg_ptr.get();
270  net_msg_ptr->getDestination() = output_link_destinations[i];
271 
272  // Enqeue msg
273  DPRINTF(RubyNetwork, "Enqueuing net msg from "
274  "inport[%d][%d] to outport [%d][%d].\n",
275  incoming, vnet, outgoing, vnet);
276 
277  m_out[outgoing][vnet]->enqueue(msg_ptr, current_time,
279  }
280  }
281 }
282 
283 void
285 {
286  // Give the highest numbered link priority most of the time
288  int highest_prio_vnet = m_virtual_networks-1;
289  int lowest_prio_vnet = 0;
290  int decrementer = 1;
291 
292  // invert priorities to avoid starvation seen in the component network
295  highest_prio_vnet = 0;
296  lowest_prio_vnet = m_virtual_networks-1;
297  decrementer = -1;
298  }
299 
300  // For all components incoming queues
301  for (int vnet = highest_prio_vnet;
302  (vnet * decrementer) >= (decrementer * lowest_prio_vnet);
303  vnet -= decrementer) {
304  operateVnet(vnet);
305  }
306 }
307 
308 void
310 {
311  m_pending_message_count[info]++;
312 }
313 
314 void
316 {
317 }
318 void
320 {
321 }
322 
323 
324 void
325 PerfectSwitch::print(std::ostream& out) const
326 {
327  out << "[PerfectSwitch " << m_switch_id << "]";
328 }
PerfectSwitch::~PerfectSwitch
~PerfectSwitch()
Definition: PerfectSwitch.cc:99
PerfectSwitch.hh
PerfectSwitch::m_network_ptr
SimpleNetwork * m_network_ptr
Definition: PerfectSwitch.hh:105
PerfectSwitch::m_link_order
std::vector< LinkOrder > m_link_order
Definition: PerfectSwitch.hh:99
MessageBuffer::dequeue
Tick dequeue(Tick current_time, bool decrement_messages=true)
Updates the delay cycles of the message at the head of the queue, removes it from the queue and retur...
Definition: MessageBuffer.cc:273
PerfectSwitch::operateMessageBuffer
void operateMessageBuffer(MessageBuffer *b, int incoming, int vnet)
Definition: PerfectSwitch.cc:138
Message::getDestination
virtual const NetDest & getDestination() const
Definition: Message.hh:108
PerfectSwitch::collateStats
void collateStats()
Definition: PerfectSwitch.cc:319
NetDest::count
int count() const
Definition: NetDest.cc:122
ArmISA::sw
Bitfield< 10 > sw
Definition: miscregs_types.hh:371
PerfectSwitch::addOutPort
void addOutPort(const std::vector< MessageBuffer * > &out, const NetDest &routing_table_entry)
Definition: PerfectSwitch.cc:85
PerfectSwitch::print
void print(std::ostream &out) const
Definition: PerfectSwitch.cc:325
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
PerfectSwitch::m_out
std::vector< std::vector< MessageBuffer * > > m_out
Definition: PerfectSwitch.hh:96
random.hh
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:59
SimpleNetwork.hh
cast.hh
PerfectSwitch::m_routing_table
std::vector< NetDest > m_routing_table
Definition: PerfectSwitch.hh:98
std::vector< MessageBuffer * >
Switch
Definition: Switch.hh:71
PerfectSwitch::clearStats
void clearStats()
Definition: PerfectSwitch.cc:315
PerfectSwitch::operateVnet
void operateVnet(int vnet)
Definition: PerfectSwitch.cc:104
Random::random
std::enable_if_t< std::is_integral< T >::value, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:86
operator<
bool operator<(const LinkOrder &l1, const LinkOrder &l2)
Definition: PerfectSwitch.cc:46
SimpleNetwork::isVNetOrdered
bool isVNetOrdered(int vnet) const
Definition: SimpleNetwork.hh:71
random_mt
Random random_mt
Definition: random.cc:96
MessageBuffer::peekMsgPtr
const MsgPtr & peekMsgPtr() const
Definition: MessageBuffer.hh:115
PerfectSwitch::m_round_robin_start
int m_round_robin_start
Definition: PerfectSwitch.hh:102
Clocked::cyclesToTicks
Tick cyclesToTicks(Cycles c) const
Definition: clocked_object.hh:224
SimpleNetwork::getAdaptiveRouting
bool getAdaptiveRouting()
Definition: SimpleNetwork.hh:66
PerfectSwitch::m_virtual_networks
uint32_t m_virtual_networks
Definition: PerfectSwitch.hh:101
PerfectSwitch::wakeup
void wakeup()
Definition: PerfectSwitch.cc:284
PerfectSwitch::m_wakeups_wo_switch
int m_wakeups_wo_switch
Definition: PerfectSwitch.hh:103
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:237
PerfectSwitch::addInPort
void addInPort(const std::vector< MessageBuffer * > &in)
Definition: PerfectSwitch.cc:70
MessageBuffer::isReady
bool isReady(Tick current_time) const
Definition: MessageBuffer.cc:482
PerfectSwitch::PerfectSwitch
PerfectSwitch(SwitchID sid, Switch *, uint32_t)
Definition: PerfectSwitch.cc:51
Consumer
Definition: Consumer.hh:55
SimpleNetwork
Definition: SimpleNetwork.hh:55
Clocked::clockEdge
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Definition: clocked_object.hh:174
X86ISA::l2
Bitfield< 4 > l2
Definition: misc.hh:660
PerfectSwitch::init
void init(SimpleNetwork *)
Definition: PerfectSwitch.cc:60
cprintf.hh
MsgPtr
std::shared_ptr< Message > MsgPtr
Definition: Message.hh:53
MessageBuffer.hh
PerfectSwitch::storeEventInfo
void storeEventInfo(int info)
Definition: PerfectSwitch.cc:309
LinkOrder
Definition: PerfectSwitch.hh:51
X86ISA::l1
Bitfield< 2 > l1
Definition: misc.hh:658
Switch.hh
PRIORITY_SWITCH_LIMIT
const int PRIORITY_SWITCH_LIMIT
Definition: PerfectSwitch.cc:42
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:79
Message
Definition: Message.hh:56
NodeID
unsigned int NodeID
Definition: TypeDefines.hh:34
NetDest::intersectionIsNotEmpty
bool intersectionIsNotEmpty(const NetDest &other_netDest) const
Definition: NetDest.cc:216
PerfectSwitch::m_switch_id
const SwitchID m_switch_id
Definition: PerfectSwitch.hh:91
PerfectSwitch::m_pending_message_count
std::vector< int > m_pending_message_count
Definition: PerfectSwitch.hh:106
MessageBuffer
Definition: MessageBuffer.hh:68
PerfectSwitch::m_switch
Switch *const m_switch
Definition: PerfectSwitch.hh:92
NetDest::AND
NetDest AND(const NetDest &andNetDest) const
Definition: NetDest.cc:204
Message.hh
MipsISA::l
Bitfield< 5 > l
Definition: pra_constants.hh:320
NetDest
Definition: NetDest.hh:39
ArmISA::v
Bitfield< 28 > v
Definition: miscregs_types.hh:51
SwitchID
unsigned int SwitchID
Definition: TypeDefines.hh:35
NetDest::removeNetDest
void removeNetDest(const NetDest &netDest)
Definition: NetDest.cc:70
Consumer::scheduleEvent
void scheduleEvent(Cycles timeDelta)
Definition: Consumer.cc:50
PerfectSwitch::m_in
std::vector< std::vector< MessageBuffer * > > m_in
Definition: PerfectSwitch.hh:95

Generated on Tue Jun 22 2021 15:28:30 for gem5 by doxygen 1.8.17