gem5 v24.0.0.0
Loading...
Searching...
No Matches
PerfectSwitch.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020-2021 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
42
43#include <algorithm>
44
45#include "base/cast.hh"
46#include "base/cprintf.hh"
47#include "base/random.hh"
48#include "debug/RubyNetwork.hh"
53
54namespace gem5
55{
56
57namespace ruby
58{
59
60const int PRIORITY_SWITCH_LIMIT = 128;
61
63 : Consumer(sw, Switch::PERFECTSWITCH_EV_PRI),
64 m_switch_id(sid), m_switch(sw)
65{
67 m_virtual_networks = virt_nets;
68}
69
70void
72{
73 m_network_ptr = network_ptr;
74
75 for (int i = 0;i < m_virtual_networks;++i) {
76 m_pending_message_count.push_back(0);
77 }
78}
79
80void
82{
83 NodeID port = m_in.size();
84 m_in.push_back(in);
85
86 for (int i = 0; i < in.size(); ++i) {
87 if (in[i] != nullptr) {
88 in[i]->setConsumer(this);
89 in[i]->setIncomingLink(port);
90 in[i]->setVnet(i);
92 }
93 }
94}
95
96void
98{
99 while (m_in_prio.size() <= vnet) {
100 m_in_prio.emplace_back();
101 m_in_prio_groups.emplace_back();
102 }
103
104 m_in_prio[vnet].push_back(in_buf);
105
106 std::sort(m_in_prio[vnet].begin(), m_in_prio[vnet].end(),
107 [](const MessageBuffer* i, const MessageBuffer* j)
108 { return i->routingPriority() < j->routingPriority(); });
109
110 // reset groups
111 m_in_prio_groups[vnet].clear();
112 int cur_prio = m_in_prio[vnet].front()->routingPriority();
113 m_in_prio_groups[vnet].emplace_back();
114 for (auto buf : m_in_prio[vnet]) {
115 if (buf->routingPriority() != cur_prio)
116 m_in_prio_groups[vnet].emplace_back();
117 m_in_prio_groups[vnet].back().push_back(buf);
118 }
119}
120
121void
123 const NetDest& routing_table_entry,
124 const PortDirection &dst_inport,
125 Tick routing_latency,
126 int link_weight)
127{
128 // Add to routing unit
130 out,
131 routing_table_entry,
132 dst_inport,
133 link_weight);
134 m_out.push_back({routing_latency, out});
135}
136
140
142PerfectSwitch::inBuffer(int in_port, int vnet) const
143{
144 if (m_in[in_port].size() <= vnet) {
145 return nullptr;
146 }
147 else {
148 return m_in[in_port][vnet];
149 }
150}
151
152void
154{
155 if (m_pending_message_count[vnet] == 0)
156 return;
157
158 for (auto &in : m_in_prio_groups[vnet]) {
159 // first check the port with the oldest message
160 unsigned start_in_port = 0;
161 Tick lowest_tick = MaxTick;
162 for (int i = 0; i < in.size(); ++i) {
163 MessageBuffer *buffer = in[i];
164 if (buffer) {
165 Tick ready_time = buffer->readyTime();
166 if (ready_time < lowest_tick){
167 lowest_tick = ready_time;
168 start_in_port = i;
169 }
170 }
171 }
172 DPRINTF(RubyNetwork, "vnet %d: %d pending msgs. "
173 "Checking port %d first\n",
174 vnet, m_pending_message_count[vnet], start_in_port);
175 // check all ports starting with the one with the oldest message
176 for (int i = 0; i < in.size(); ++i) {
177 int in_port = (i + start_in_port) % in.size();
178 MessageBuffer *buffer = in[in_port];
179 if (buffer)
180 operateMessageBuffer(buffer, vnet);
181 }
182 }
183}
184
185void
187{
188 MsgPtr msg_ptr;
189 Message *net_msg_ptr = NULL;
190
191 // temporary vectors to store the routing results
192 static thread_local std::vector<BaseRoutingUnit::RouteInfo> output_links;
193
194 Tick current_time = m_switch->clockEdge();
195
196 while (buffer->isReady(current_time)) {
197 DPRINTF(RubyNetwork, "incoming: %d\n", buffer->getIncomingLink());
198
199 // Peek at message
200 msg_ptr = buffer->peekMsgPtr();
201 net_msg_ptr = msg_ptr.get();
202 DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
203
204
205 output_links.clear();
206 m_switch->getRoutingUnit().route(*net_msg_ptr, vnet,
208 output_links);
209
210 // Check for resources - for all outgoing queues
211 bool enough = true;
212 for (int i = 0; i < output_links.size(); i++) {
213 int outgoing = output_links[i].m_link_id;
214 OutputPort &out_port = m_out[outgoing];
215
216 if (!out_port.buffers[vnet]->areNSlotsAvailable(1, current_time))
217 enough = false;
218
219 DPRINTF(RubyNetwork, "Checking if node is blocked ..."
220 "outgoing: %d, vnet: %d, enough: %d\n",
221 outgoing, vnet, enough);
222 }
223
224 // There were not enough resources
225 if (!enough) {
227 DPRINTF(RubyNetwork, "Can't deliver message since a node "
228 "is blocked\n");
229 DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr));
230 break; // go to next incoming port
231 }
232
233 MsgPtr unmodified_msg_ptr;
234
235 if (output_links.size() > 1) {
236 // If we are sending this message down more than one link
237 // (size>1), we need to make a copy of the message so each
238 // branch can have a different internal destination we need
239 // to create an unmodified MsgPtr because the MessageBuffer
240 // enqueue func will modify the message
241
242 // This magic line creates a private copy of the message
243 unmodified_msg_ptr = msg_ptr->clone();
244 }
245
246 // Dequeue msg
247 buffer->dequeue(current_time);
249
250 // Enqueue it - for all outgoing queues
251 for (int i=0; i<output_links.size(); i++) {
252 int outgoing = output_links[i].m_link_id;
253 OutputPort &out_port = m_out[outgoing];
254
255 if (i > 0) {
256 // create a private copy of the unmodified message
257 msg_ptr = unmodified_msg_ptr->clone();
258 }
259
260 // Change the internal destination set of the message so it
261 // knows which destinations this link is responsible for.
262 net_msg_ptr = msg_ptr.get();
263 net_msg_ptr->getDestination() = output_links[i].m_destinations;
264
265 // Enqeue msg
266 DPRINTF(RubyNetwork, "Enqueuing net msg from "
267 "inport[%d][%d] to outport [%d][%d].\n",
268 buffer->getIncomingLink(), vnet, outgoing, vnet);
269
270 out_port.buffers[vnet]->enqueue(msg_ptr, current_time,
271 out_port.latency);
272 }
273 }
274}
275
276void
278{
279 // Give the highest numbered link priority most of the time
281 int highest_prio_vnet = m_virtual_networks-1;
282 int lowest_prio_vnet = 0;
283 int decrementer = 1;
284
285 // invert priorities to avoid starvation seen in the component network
288 highest_prio_vnet = 0;
289 lowest_prio_vnet = m_virtual_networks-1;
290 decrementer = -1;
291 }
292
293 // For all components incoming queues
294 for (int vnet = highest_prio_vnet;
295 (vnet * decrementer) >= (decrementer * lowest_prio_vnet);
296 vnet -= decrementer) {
297 operateVnet(vnet);
298 }
299}
300
301void
306
307void
311void
315
316
317void
318PerfectSwitch::print(std::ostream& out) const
319{
320 out << "[PerfectSwitch " << m_switch_id << "]";
321}
322
323} // namespace ruby
324} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
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...
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
virtual void addOutPort(LinkID link_id, const std::vector< MessageBuffer * > &m_out_buffer, const NetDest &routing_table_entry, const PortDirection &direction, int link_weight)=0
virtual void route(const Message &msg, int vnet, bool deterministic, std::vector< RouteInfo > &out_links)=0
void scheduleEvent(Cycles timeDelta)
Definition Consumer.cc:56
bool isReady(Tick current_time) const
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...
const MsgPtr & peekMsgPtr() const
virtual const NetDest & getDestination() const
Definition Message.hh:114
void init(SimpleNetwork *)
void addOutPort(const std::vector< MessageBuffer * > &out, const NetDest &routing_table_entry, const PortDirection &dst_inport, Tick routing_latency, int link_weight)
std::vector< std::vector< MessageBuffer * > > m_in_prio
std::vector< std::vector< MessageBuffer * > > m_in
std::vector< int > m_pending_message_count
std::vector< OutputPort > m_out
std::vector< std::vector< std::vector< MessageBuffer * > > > m_in_prio_groups
SimpleNetwork * m_network_ptr
PerfectSwitch(SwitchID sid, Switch *, uint32_t)
void print(std::ostream &out) const
MessageBuffer * inBuffer(int in_port, int vnet) const
void updatePriorityGroups(int vnet, MessageBuffer *buf)
void addInPort(const std::vector< MessageBuffer * > &in)
void operateMessageBuffer(MessageBuffer *b, int vnet)
bool isVNetOrdered(int vnet) const
BaseRoutingUnit & getRoutingUnit()
Definition Switch.hh:112
STL vector class.
Definition stl.hh:37
SignedBitfield< 31, 0 > sw
Definition int.hh:64
Bitfield< 7 > i
Definition misc_types.hh:67
std::shared_ptr< Message > MsgPtr
Definition Message.hh:60
unsigned int SwitchID
std::string PortDirection
unsigned int NodeID
const int PRIORITY_SWITCH_LIMIT
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t Tick
Tick count type.
Definition types.hh:58
const Tick MaxTick
Definition types.hh:60
std::vector< MessageBuffer * > buffers

Generated on Tue Jun 18 2024 16:24:05 for gem5 by doxygen 1.11.0