gem5  v21.1.0.2
Throttle.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 <cassert>
32 
33 #include "base/cast.hh"
34 #include "base/cprintf.hh"
35 #include "debug/RubyNetwork.hh"
41 
42 namespace gem5
43 {
44 
45 namespace ruby
46 {
47 
48 const int MESSAGE_SIZE_MULTIPLIER = 1000;
49 //const int BROADCAST_SCALING = 4; // Have a 16p system act like a 64p systems
50 const int BROADCAST_SCALING = 1;
51 const int PRIORITY_SWITCH_LIMIT = 128;
52 
53 static int network_message_to_size(Message* net_msg_ptr);
54 
55 Throttle::Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency,
56  int link_bandwidth_multiplier, int endpoint_bandwidth,
57  Switch *em)
58  : Consumer(em),
59  m_switch_id(sID), m_switch(em), m_node(node),
60  m_ruby_system(rs),
61  throttleStats(em, node)
62 {
63  m_vnets = 0;
64 
65  assert(link_bandwidth_multiplier > 0);
66  m_link_bandwidth_multiplier = link_bandwidth_multiplier;
67 
68  m_link_latency = link_latency;
69  m_endpoint_bandwidth = endpoint_bandwidth;
70 
73 }
74 
75 void
77  const std::vector<MessageBuffer*>& out_vec)
78 {
79  assert(in_vec.size() == out_vec.size());
80 
81  for (int vnet = 0; vnet < in_vec.size(); ++vnet) {
82  MessageBuffer *in_ptr = in_vec[vnet];
83  MessageBuffer *out_ptr = out_vec[vnet];
84 
85  m_vnets++;
86  m_units_remaining.push_back(0);
87  m_in.push_back(in_ptr);
88  m_out.push_back(out_ptr);
89 
90  // Set consumer and description
91  in_ptr->setConsumer(this);
92  std::string desc = "[Queue to Throttle " +
94  }
95 }
96 
97 void
98 Throttle::operateVnet(int vnet, int &bw_remaining, bool &schedule_wakeup,
99  MessageBuffer *in, MessageBuffer *out)
100 {
101  if (out == nullptr || in == nullptr) {
102  return;
103  }
104 
105  assert(m_units_remaining[vnet] >= 0);
106  Tick current_time = m_switch->clockEdge();
107 
108  while (bw_remaining > 0 && (in->isReady(current_time) ||
109  m_units_remaining[vnet] > 0) &&
110  out->areNSlotsAvailable(1, current_time)) {
111  // See if we are done transferring the previous message on
112  // this virtual network
113  if (m_units_remaining[vnet] == 0 && in->isReady(current_time)) {
114  // Find the size of the message we are moving
115  MsgPtr msg_ptr = in->peekMsgPtr();
116  Message *net_msg_ptr = msg_ptr.get();
117  m_units_remaining[vnet] +=
118  network_message_to_size(net_msg_ptr);
119 
120  DPRINTF(RubyNetwork, "throttle: %d my bw %d bw spent "
121  "enqueueing net msg %d time: %lld.\n",
124 
125  // Move the message
126  in->dequeue(current_time);
127  out->enqueue(msg_ptr, current_time,
129 
130  // Count the message
131  (*(throttleStats.
132  m_msg_counts[net_msg_ptr->getMessageSize()]))[vnet]++;
133  DPRINTF(RubyNetwork, "%s\n", *out);
134  }
135 
136  // Calculate the amount of bandwidth we spent on this message
137  int diff = m_units_remaining[vnet] - bw_remaining;
138  m_units_remaining[vnet] = std::max(0, diff);
139  bw_remaining = std::max(0, -diff);
140  }
141 
142  if (bw_remaining > 0 && (in->isReady(current_time) ||
143  m_units_remaining[vnet] > 0) &&
144  !out->areNSlotsAvailable(1, current_time)) {
145  DPRINTF(RubyNetwork, "vnet: %d", vnet);
146 
147  // schedule me to wakeup again because I'm waiting for my
148  // output queue to become available
149  schedule_wakeup = true;
150  }
151 }
152 
153 void
155 {
156  // Limits the number of message sent to a limited number of bytes/cycle.
157  assert(getLinkBandwidth() > 0);
158  int bw_remaining = getLinkBandwidth();
159 
161  bool schedule_wakeup = false;
162 
163  // variable for deciding the direction in which to iterate
164  bool iteration_direction = false;
165 
166 
167  // invert priorities to avoid starvation seen in the component network
170  iteration_direction = true;
171  }
172 
173  if (iteration_direction) {
174  for (int vnet = 0; vnet < m_vnets; ++vnet) {
175  operateVnet(vnet, bw_remaining, schedule_wakeup,
176  m_in[vnet], m_out[vnet]);
177  }
178  } else {
179  for (int vnet = m_vnets-1; vnet >= 0; --vnet) {
180  operateVnet(vnet, bw_remaining, schedule_wakeup,
181  m_in[vnet], m_out[vnet]);
182  }
183  }
184 
185  // We should only wake up when we use the bandwidth
186  // This is only mostly true
187  // assert(bw_remaining != getLinkBandwidth());
188 
189  // Record that we used some or all of the link bandwidth this cycle
190  double ratio = 1.0 - (double(bw_remaining) / double(getLinkBandwidth()));
191 
192  // If ratio = 0, we used no bandwidth, if ratio = 1, we used all
193  m_link_utilization_proxy += ratio;
194 
195  if (bw_remaining > 0 && !schedule_wakeup) {
196  // We have extra bandwidth and our output buffer was
197  // available, so we must not have anything else to do until
198  // another message arrives.
199  DPRINTF(RubyNetwork, "%s not scheduled again\n", *this);
200  } else {
201  DPRINTF(RubyNetwork, "%s scheduled again\n", *this);
202 
203  // We are out of bandwidth for this cycle, so wakeup next
204  // cycle and continue
205  scheduleEvent(Cycles(1));
206  }
207 }
208 
209 void
211 {
212  for (MessageSizeType type = MessageSizeType_FIRST;
213  type < MessageSizeType_NUM; ++type) {
214  throttleStats.m_msg_counts[(unsigned int)type] =
216  csprintf("msg_count.%s", MessageSizeType_to_string(type)).c_str());
217  throttleStats.m_msg_counts[(unsigned int)type]
219  .flags(statistics::nozero)
220  ;
221 
222  throttleStats.m_msg_bytes[(unsigned int) type] =
224  csprintf("msg_bytes.%s", MessageSizeType_to_string(type)).c_str());
225  throttleStats.m_msg_bytes[(unsigned int) type]
226  ->flags(statistics::nozero)
227  ;
228 
229  *(throttleStats.m_msg_bytes[(unsigned int) type]) =
232  }
233 }
234 
235 void
237 {
239 }
240 
241 void
243 {
244  double time_delta = double(m_ruby_system->curCycle() -
246 
248  100.0 * m_link_utilization_proxy / time_delta;
249 }
250 
251 void
252 Throttle::print(std::ostream& out) const
253 {
254  ccprintf(out, "[%i bw: %i]", m_node, getLinkBandwidth());
255 }
256 
257 int
259 {
260  assert(net_msg_ptr != NULL);
261 
262  int size = Network::MessageSizeType_to_int(net_msg_ptr->getMessageSize());
263  size *= MESSAGE_SIZE_MULTIPLIER;
264 
265  // Artificially increase the size of broadcast messages
266  if (BROADCAST_SCALING > 1 && net_msg_ptr->getDestination().isBroadcast())
267  size *= BROADCAST_SCALING;
268 
269  return size;
270 }
271 
274  : statistics::Group(parent, csprintf("throttle%02i", nodeID).c_str()),
275  m_link_utilization(this, "link_utilization")
276 {
277 
278 }
279 
280 } // namespace ruby
281 } // namespace gem5
gem5::ruby::Network::getNumberOfVirtualNetworks
static uint32_t getNumberOfVirtualNetworks()
Definition: Network.hh:90
gem5::ruby::Throttle::m_link_bandwidth_multiplier
int m_link_bandwidth_multiplier
Definition: Throttle.hh:108
gem5::ruby::MsgPtr
std::shared_ptr< Message > MsgPtr
Definition: Message.hh:59
gem5::ruby::MESSAGE_SIZE_MULTIPLIER
const int MESSAGE_SIZE_MULTIPLIER
Definition: Throttle.cc:48
gem5::Clocked::curCycle
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
Definition: clocked_object.hh:195
gem5::ruby::Throttle::wakeup
void wakeup()
Definition: Throttle.cc:154
gem5::ruby::Network::MessageSizeType_to_int
static uint32_t MessageSizeType_to_int(MessageSizeType size_type)
Definition: Network.cc:164
gem5::ruby::Throttle::m_wakeups_wo_switch
int m_wakeups_wo_switch
Definition: Throttle.hh:110
gem5::statistics::nozero
const FlagsType nozero
Don't print if this is zero.
Definition: info.hh:68
sc_dt::to_string
const std::string to_string(sc_enc enc)
Definition: sc_fxdefs.cc:91
gem5::ruby::Throttle::operateVnet
void operateVnet(int vnet, int &bw_remainin, bool &schedule_wakeup, MessageBuffer *in, MessageBuffer *out)
Definition: Throttle.cc:98
gem5::ruby::Throttle::print
void print(std::ostream &out) const
Definition: Throttle.cc:252
cast.hh
gem5::ruby::MessageBuffer::enqueue
void enqueue(MsgPtr message, Tick curTime, Tick delta)
Definition: MessageBuffer.cc:197
gem5::ruby::Message::getMessageSize
virtual const MessageSizeType & getMessageSize() const
Definition: Message.hh:78
gem5::ruby::Throttle::ThrottleStats::m_msg_counts
statistics::Vector * m_msg_counts[MessageSizeType_NUM]
Definition: Throttle.hh:123
gem5::statistics::Vector
A vector of scalar stats.
Definition: statistics.hh:2003
gem5::statistics::Formula
A formula for statistics that is calculated when printed.
Definition: statistics.hh:2536
std::vector
STL vector class.
Definition: stl.hh:37
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
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::Throttle::init
void init(NodeID node, Cycles link_latency, int link_bandwidth_multiplier, int endpoint_bandwidth)
gem5::ruby::Switch
Definition: Switch.hh:77
gem5::ruby::Throttle::regStats
void regStats()
Definition: Throttle.cc:210
Throttle.hh
gem5::ccprintf
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
gem5::ruby::MessageBuffer::peekMsgPtr
const MsgPtr & peekMsgPtr() const
Definition: MessageBuffer.hh:121
gem5::ruby::network_message_to_size
static int network_message_to_size(Message *net_msg_ptr)
Definition: Throttle.cc:258
gem5::statistics::constant
Temp constant(T val)
Definition: statistics.hh:2862
gem5::Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:78
gem5::ruby::Throttle::addLinks
void addLinks(const std::vector< MessageBuffer * > &in_vec, const std::vector< MessageBuffer * > &out_vec)
Definition: Throttle.cc:76
gem5::ruby::Throttle::m_node
NodeID m_node
Definition: Throttle.hh:106
gem5::X86ISA::em
Bitfield< 2 > em
Definition: misc.hh:608
gem5::ruby::PRIORITY_SWITCH_LIMIT
const int PRIORITY_SWITCH_LIMIT
Definition: PerfectSwitch.cc:48
gem5::ruby::Throttle::m_in
std::vector< MessageBuffer * > m_in
Definition: Throttle.hh:99
gem5::ruby::Throttle::clearStats
void clearStats()
Definition: Throttle.cc:236
gem5::Clocked::cyclesToTicks
Tick cyclesToTicks(Cycles c) const
Definition: clocked_object.hh:227
gem5::ruby::RubySystem::getStartCycle
Cycles getStartCycle()
Definition: RubySystem.hh:79
gem5::ruby::Throttle::collateStats
void collateStats()
Definition: Throttle.cc:242
gem5::ruby::Consumer::scheduleEvent
void scheduleEvent(Cycles timeDelta)
Definition: Consumer.cc:56
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::X86ISA::type
type
Definition: misc.hh:733
gem5::ruby::Throttle::m_out
std::vector< MessageBuffer * > m_out
Definition: Throttle.hh:100
gem5::ruby::Throttle::m_switch_id
const int m_switch_id
Definition: Throttle.hh:104
cprintf.hh
RubySystem.hh
gem5::ruby::Throttle::throttleStats
gem5::ruby::Throttle::ThrottleStats throttleStats
gem5::ruby::Throttle::m_link_utilization_proxy
double m_link_utilization_proxy
Definition: Throttle.hh:114
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::MessageBuffer::setConsumer
void setConsumer(Consumer *consumer)
Definition: MessageBuffer.hh:102
gem5::ruby::MessageBuffer::isReady
bool isReady(Tick current_time) const
Definition: MessageBuffer.cc:488
MessageBuffer.hh
Network.hh
gem5::ruby::RubySystem
Definition: RubySystem.hh:63
gem5::ruby::Throttle::m_vnets
unsigned int m_vnets
Definition: Throttle.hh:101
gem5::ruby::Throttle::m_endpoint_bandwidth
int m_endpoint_bandwidth
Definition: Throttle.hh:111
Switch.hh
gem5::ruby::Throttle::ThrottleStats::m_link_utilization
statistics::Scalar m_link_utilization
Definition: Throttle.hh:122
gem5::ruby::MessageBuffer::areNSlotsAvailable
bool areNSlotsAvailable(unsigned int n, Tick curTime)
Definition: MessageBuffer.cc:127
gem5::ruby::Throttle::getLinkBandwidth
int getLinkBandwidth() const
Definition: Throttle.hh:79
gem5::statistics::Group
Statistics container.
Definition: group.hh:93
gem5::ruby::NodeID
unsigned int NodeID
Definition: TypeDefines.hh:40
gem5::ruby::Message
Definition: Message.hh:62
gem5::ruby::Throttle::m_link_latency
Cycles m_link_latency
Definition: Throttle.hh:109
gem5::ruby::Throttle::m_units_remaining
std::vector< int > m_units_remaining
Definition: Throttle.hh:102
gem5::ruby::Message::getDestination
virtual const NetDest & getDestination() const
Definition: Message.hh:114
gem5::ruby::Throttle::Throttle
Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency, int link_bandwidth_multiplier, int endpoint_bandwidth, Switch *em)
Definition: Throttle.cc:55
gem5::ruby::BROADCAST_SCALING
const int BROADCAST_SCALING
Definition: Throttle.cc:50
gem5::ruby::MessageBuffer
Definition: MessageBuffer.hh:74
gem5::ruby::NetDest::isBroadcast
bool isBroadcast() const
Definition: NetDest.cc:174
gem5::ruby::Throttle::m_switch
Switch * m_switch
Definition: Throttle.hh:105
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
Message.hh
gem5::ruby::Throttle::ThrottleStats::m_msg_bytes
statistics::Formula * m_msg_bytes[MessageSizeType_NUM]
Definition: Throttle.hh:124
gem5::ArmISA::rs
Bitfield< 9, 8 > rs
Definition: misc_types.hh:376
gem5::ruby::Throttle::ThrottleStats::ThrottleStats
ThrottleStats(statistics::Group *parent, const NodeID &nodeID)
Definition: Throttle.cc:273
gem5::ruby::Throttle::m_ruby_system
RubySystem * m_ruby_system
Definition: Throttle.hh:112

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