gem5  v21.1.0.2
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 namespace gem5
43 {
44 
45 namespace ruby
46 {
47 
48 const int PRIORITY_SWITCH_LIMIT = 128;
49 
50 // Operator for helper class
51 bool
53 {
54  return (l1.m_value < l2.m_value);
55 }
56 
57 PerfectSwitch::PerfectSwitch(SwitchID sid, Switch *sw, uint32_t virt_nets)
58  : Consumer(sw), m_switch_id(sid), m_switch(sw)
59 {
62  m_virtual_networks = virt_nets;
63 }
64 
65 void
67 {
68  m_network_ptr = network_ptr;
69 
70  for (int i = 0;i < m_virtual_networks;++i) {
71  m_pending_message_count.push_back(0);
72  }
73 }
74 
75 void
77 {
78  NodeID port = m_in.size();
79  m_in.push_back(in);
80 
81  for (int i = 0; i < in.size(); ++i) {
82  if (in[i] != nullptr) {
83  in[i]->setConsumer(this);
84  in[i]->setIncomingLink(port);
85  in[i]->setVnet(i);
86  }
87  }
88 }
89 
90 void
92  const NetDest& routing_table_entry)
93 {
94  // Setup link order
95  LinkOrder l;
96  l.m_value = 0;
97  l.m_link = m_out.size();
98  m_link_order.push_back(l);
99 
100  // Add to routing table
101  m_out.push_back(out);
102  m_routing_table.push_back(routing_table_entry);
103 }
104 
106 {
107 }
108 
109 void
111 {
112  // This is for round-robin scheduling
113  int incoming = m_round_robin_start;
115  if (m_round_robin_start >= m_in.size()) {
117  }
118 
119  if (m_pending_message_count[vnet] > 0) {
120  // for all input ports, use round robin scheduling
121  for (int counter = 0; counter < m_in.size(); counter++) {
122  // Round robin scheduling
123  incoming++;
124  if (incoming >= m_in.size()) {
125  incoming = 0;
126  }
127 
128  // Is there a message waiting?
129  if (m_in[incoming].size() <= vnet) {
130  continue;
131  }
132 
133  MessageBuffer *buffer = m_in[incoming][vnet];
134  if (buffer == nullptr) {
135  continue;
136  }
137 
138  operateMessageBuffer(buffer, incoming, vnet);
139  }
140  }
141 }
142 
143 void
145  int vnet)
146 {
147  MsgPtr msg_ptr;
148  Message *net_msg_ptr = NULL;
149 
150  // temporary vectors to store the routing results
151  std::vector<LinkID> output_links;
152  std::vector<NetDest> output_link_destinations;
153  Tick current_time = m_switch->clockEdge();
154 
155  while (buffer->isReady(current_time)) {
156  DPRINTF(RubyNetwork, "incoming: %d\n", incoming);
157 
158  // Peek at message
159  msg_ptr = buffer->peekMsgPtr();
160  net_msg_ptr = msg_ptr.get();
161  DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
162 
163  output_links.clear();
164  output_link_destinations.clear();
165  NetDest msg_dsts = net_msg_ptr->getDestination();
166 
167  // Unfortunately, the token-protocol sends some
168  // zero-destination messages, so this assert isn't valid
169  // assert(msg_dsts.count() > 0);
170 
171  assert(m_link_order.size() == m_routing_table.size());
172  assert(m_link_order.size() == m_out.size());
173 
175  if (m_network_ptr->isVNetOrdered(vnet)) {
176  // Don't adaptively route
177  for (int out = 0; out < m_out.size(); out++) {
178  m_link_order[out].m_link = out;
179  m_link_order[out].m_value = 0;
180  }
181  } else {
182  // Find how clogged each link is
183  for (int out = 0; out < m_out.size(); out++) {
184  int out_queue_length = 0;
185  for (int v = 0; v < m_virtual_networks; v++) {
186  out_queue_length += m_out[out][v]->getSize(current_time);
187  }
188  int value =
189  (out_queue_length << 8) |
190  random_mt.random(0, 0xff);
191  m_link_order[out].m_link = out;
192  m_link_order[out].m_value = value;
193  }
194 
195  // Look at the most empty link first
196  sort(m_link_order.begin(), m_link_order.end());
197  }
198  }
199 
200  for (int i = 0; i < m_routing_table.size(); i++) {
201  // pick the next link to look at
202  int link = m_link_order[i].m_link;
203  NetDest dst = m_routing_table[link];
204  DPRINTF(RubyNetwork, "dst: %s\n", dst);
205 
206  if (!msg_dsts.intersectionIsNotEmpty(dst))
207  continue;
208 
209  // Remember what link we're using
210  output_links.push_back(link);
211 
212  // Need to remember which destinations need this message in
213  // another vector. This Set is the intersection of the
214  // routing_table entry and the current destination set. The
215  // intersection must not be empty, since we are inside "if"
216  output_link_destinations.push_back(msg_dsts.AND(dst));
217 
218  // Next, we update the msg_destination not to include
219  // those nodes that were already handled by this link
220  msg_dsts.removeNetDest(dst);
221  }
222 
223  assert(msg_dsts.count() == 0);
224 
225  // Check for resources - for all outgoing queues
226  bool enough = true;
227  for (int i = 0; i < output_links.size(); i++) {
228  int outgoing = output_links[i];
229 
230  if (!m_out[outgoing][vnet]->areNSlotsAvailable(1, current_time))
231  enough = false;
232 
233  DPRINTF(RubyNetwork, "Checking if node is blocked ..."
234  "outgoing: %d, vnet: %d, enough: %d\n",
235  outgoing, vnet, enough);
236  }
237 
238  // There were not enough resources
239  if (!enough) {
240  scheduleEvent(Cycles(1));
241  DPRINTF(RubyNetwork, "Can't deliver message since a node "
242  "is blocked\n");
243  DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
244  break; // go to next incoming port
245  }
246 
247  MsgPtr unmodified_msg_ptr;
248 
249  if (output_links.size() > 1) {
250  // If we are sending this message down more than one link
251  // (size>1), we need to make a copy of the message so each
252  // branch can have a different internal destination we need
253  // to create an unmodified MsgPtr because the MessageBuffer
254  // enqueue func will modify the message
255 
256  // This magic line creates a private copy of the message
257  unmodified_msg_ptr = msg_ptr->clone();
258  }
259 
260  // Dequeue msg
261  buffer->dequeue(current_time);
262  m_pending_message_count[vnet]--;
263 
264  // Enqueue it - for all outgoing queues
265  for (int i=0; i<output_links.size(); i++) {
266  int outgoing = output_links[i];
267 
268  if (i > 0) {
269  // create a private copy of the unmodified message
270  msg_ptr = unmodified_msg_ptr->clone();
271  }
272 
273  // Change the internal destination set of the message so it
274  // knows which destinations this link is responsible for.
275  net_msg_ptr = msg_ptr.get();
276  net_msg_ptr->getDestination() = output_link_destinations[i];
277 
278  // Enqeue msg
279  DPRINTF(RubyNetwork, "Enqueuing net msg from "
280  "inport[%d][%d] to outport [%d][%d].\n",
281  incoming, vnet, outgoing, vnet);
282 
283  m_out[outgoing][vnet]->enqueue(msg_ptr, current_time,
285  }
286  }
287 }
288 
289 void
291 {
292  // Give the highest numbered link priority most of the time
294  int highest_prio_vnet = m_virtual_networks-1;
295  int lowest_prio_vnet = 0;
296  int decrementer = 1;
297 
298  // invert priorities to avoid starvation seen in the component network
301  highest_prio_vnet = 0;
302  lowest_prio_vnet = m_virtual_networks-1;
303  decrementer = -1;
304  }
305 
306  // For all components incoming queues
307  for (int vnet = highest_prio_vnet;
308  (vnet * decrementer) >= (decrementer * lowest_prio_vnet);
309  vnet -= decrementer) {
310  operateVnet(vnet);
311  }
312 }
313 
314 void
316 {
317  m_pending_message_count[info]++;
318 }
319 
320 void
322 {
323 }
324 void
326 {
327 }
328 
329 
330 void
331 PerfectSwitch::print(std::ostream& out) const
332 {
333  out << "[PerfectSwitch " << m_switch_id << "]";
334 }
335 
336 } // namespace ruby
337 } // namespace gem5
gem5::ruby::PerfectSwitch::m_out
std::vector< std::vector< MessageBuffer * > > m_out
Definition: PerfectSwitch.hh:102
gem5::ruby::PerfectSwitch::m_round_robin_start
int m_round_robin_start
Definition: PerfectSwitch.hh:108
gem5::ruby::MsgPtr
std::shared_ptr< Message > MsgPtr
Definition: Message.hh:59
PerfectSwitch.hh
gem5::ruby::NetDest::AND
NetDest AND(const NetDest &andNetDest) const
Definition: NetDest.cc:210
gem5::ruby::PerfectSwitch::m_switch
Switch *const m_switch
Definition: PerfectSwitch.hh:98
gem5::ruby::PerfectSwitch::operateMessageBuffer
void operateMessageBuffer(MessageBuffer *b, int incoming, int vnet)
Definition: PerfectSwitch.cc:144
gem5::ruby::SimpleNetwork::isVNetOrdered
bool isVNetOrdered(int vnet) const
Definition: SimpleNetwork.hh:77
gem5::ruby::PerfectSwitch::clearStats
void clearStats()
Definition: PerfectSwitch.cc:321
gem5::ruby::PerfectSwitch::m_wakeups_wo_switch
int m_wakeups_wo_switch
Definition: PerfectSwitch.hh:109
gem5::ruby::SimpleNetwork
Definition: SimpleNetwork.hh:61
random.hh
SimpleNetwork.hh
cast.hh
std::vector
STL vector class.
Definition: stl.hh:37
gem5::ruby::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:279
gem5::ruby::Consumer
Definition: Consumer.hh:61
gem5::ruby::PerfectSwitch::m_routing_table
std::vector< NetDest > m_routing_table
Definition: PerfectSwitch.hh:104
gem5::ruby::PerfectSwitch::collateStats
void collateStats()
Definition: PerfectSwitch.cc:325
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
gem5::ruby::Switch
Definition: Switch.hh:77
gem5::ruby::NetDest::removeNetDest
void removeNetDest(const NetDest &netDest)
Definition: NetDest.cc:76
gem5::ruby::MessageBuffer::peekMsgPtr
const MsgPtr & peekMsgPtr() const
Definition: MessageBuffer.hh:121
gem5::Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:78
gem5::ruby::PRIORITY_SWITCH_LIMIT
const int PRIORITY_SWITCH_LIMIT
Definition: PerfectSwitch.cc:48
gem5::ruby::PerfectSwitch::addInPort
void addInPort(const std::vector< MessageBuffer * > &in)
Definition: PerfectSwitch.cc:76
gem5::ruby::SimpleNetwork::getAdaptiveRouting
bool getAdaptiveRouting()
Definition: SimpleNetwork.hh:72
gem5::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:90
gem5::Clocked::cyclesToTicks
Tick cyclesToTicks(Cycles c) const
Definition: clocked_object.hh:227
gem5::ruby::PerfectSwitch::init
void init(SimpleNetwork *)
Definition: PerfectSwitch.cc:66
gem5::ruby::Consumer::scheduleEvent
void scheduleEvent(Cycles timeDelta)
Definition: Consumer.cc:56
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::ruby::NetDest::count
int count() const
Definition: NetDest.cc:128
gem5::ruby::PerfectSwitch::m_in
std::vector< std::vector< MessageBuffer * > > m_in
Definition: PerfectSwitch.hh:101
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::ArmISA::v
Bitfield< 28 > v
Definition: misc_types.hh:54
gem5::ruby::PerfectSwitch::m_switch_id
const SwitchID m_switch_id
Definition: PerfectSwitch.hh:97
gem5::ruby::PerfectSwitch::m_pending_message_count
std::vector< int > m_pending_message_count
Definition: PerfectSwitch.hh:112
gem5::MipsISA::l
Bitfield< 5 > l
Definition: pra_constants.hh:323
cprintf.hh
gem5::ArmISA::sw
SignedBitfield< 31, 0 > sw
Definition: int.hh:62
gem5::ruby::SwitchID
unsigned int SwitchID
Definition: TypeDefines.hh:41
gem5::ruby::operator<
bool operator<(const LinkOrder &l1, const LinkOrder &l2)
Definition: PerfectSwitch.cc:52
gem5::ruby::PerfectSwitch::m_network_ptr
SimpleNetwork * m_network_ptr
Definition: PerfectSwitch.hh:111
gem5::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:177
gem5::ruby::NetDest
Definition: NetDest.hh:45
gem5::ruby::MessageBuffer::isReady
bool isReady(Tick current_time) const
Definition: MessageBuffer.cc:488
gem5::ruby::PerfectSwitch::m_virtual_networks
uint32_t m_virtual_networks
Definition: PerfectSwitch.hh:107
gem5::ruby::LinkOrder
Definition: PerfectSwitch.hh:57
gem5::ruby::PerfectSwitch::~PerfectSwitch
~PerfectSwitch()
Definition: PerfectSwitch.cc:105
MessageBuffer.hh
gem5::ruby::PerfectSwitch::print
void print(std::ostream &out) const
Definition: PerfectSwitch.cc:331
Switch.hh
gem5::ruby::PerfectSwitch::operateVnet
void operateVnet(int vnet)
Definition: PerfectSwitch.cc:110
gem5::ruby::PerfectSwitch::PerfectSwitch
PerfectSwitch(SwitchID sid, Switch *, uint32_t)
Definition: PerfectSwitch.cc:57
gem5::ruby::PerfectSwitch::wakeup
void wakeup()
Definition: PerfectSwitch.cc:290
gem5::X86ISA::l1
Bitfield< 2 > l1
Definition: misc.hh:664
gem5::ruby::NodeID
unsigned int NodeID
Definition: TypeDefines.hh:40
gem5::ruby::Message
Definition: Message.hh:62
gem5::ruby::NetDest::intersectionIsNotEmpty
bool intersectionIsNotEmpty(const NetDest &other_netDest) const
Definition: NetDest.cc:222
gem5::ruby::Message::getDestination
virtual const NetDest & getDestination() const
Definition: Message.hh:114
gem5::ruby::PerfectSwitch::storeEventInfo
void storeEventInfo(int info)
Definition: PerfectSwitch.cc:315
gem5::ruby::MessageBuffer
Definition: MessageBuffer.hh:74
gem5::ruby::PerfectSwitch::m_link_order
std::vector< LinkOrder > m_link_order
Definition: PerfectSwitch.hh:105
gem5::ruby::PerfectSwitch::addOutPort
void addOutPort(const std::vector< MessageBuffer * > &out, const NetDest &routing_table_entry)
Definition: PerfectSwitch.cc:91
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
Message.hh
gem5::random_mt
Random random_mt
Definition: random.cc:99
gem5::X86ISA::l2
Bitfield< 4 > l2
Definition: misc.hh:666

Generated on Tue Sep 21 2021 12:25:41 for gem5 by doxygen 1.8.17