gem5  v21.2.1.1
gups_gen.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 The Regents of the University of California.
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 <cstring>
32 #include <string>
33 
34 #include "base/random.hh"
35 #include "debug/GUPSGen.hh"
36 #include "sim/sim_exit.hh"
37 
38 namespace gem5
39 {
40 
41 GUPSGen::GUPSGen(const GUPSGenParams& params):
42  ClockedObject(params),
43  nextCreateEvent([this]{ createNextReq(); }, name()),
44  nextSendEvent([this]{ sendNextReq(); }, name()),
45  system(params.system),
46  requestorId(system->getRequestorId(this)),
47  port(name() + ".port", this),
48  startAddr(params.start_addr),
49  memSize(params.mem_size),
50  updateLimit(params.update_limit),
51  elementSize(sizeof(uint64_t)), // every element in the table is a uint64_t
52  reqQueueSize(params.request_queue_size),
53  initMemory(params.init_memory),
54  stats(this)
55 {}
56 
57 Port&
58 GUPSGen::getPort(const std::string &if_name, PortID idx)
59 {
60  if (if_name != "port") {
61  return ClockedObject::getPort(if_name, idx);
62  } else {
63  return port;
64  }
65 }
66 
67 void
69 {
70  doneReading = false;
71  onTheFlyRequests = 0;
72  readRequests = 0;
73 
75  numUpdates = 4 * tableSize;
76 }
77 
78 void
80 {
81  int block_size = 64; // Write the initial values in 64 byte blocks.
82  uint64_t stride_size = block_size / elementSize;
83  if (initMemory) {
84  for (uint64_t start_index = 0; start_index < tableSize;
85  start_index += stride_size) {
86  uint8_t write_data[block_size];
87  for (uint64_t offset = 0; offset < stride_size; offset++) {
88  uint64_t value = start_index + offset;
89  std::memcpy(write_data + offset * elementSize,
90  &value, elementSize);
91  }
92  Addr addr = indexToAddr(start_index);
93  PacketPtr pkt = getWritePacket(addr, block_size, write_data);
95  delete pkt;
96  }
97  }
99 }
100 
101 Addr
103 {
104  Addr ret = index * elementSize + startAddr;
105  return ret;
106 }
107 
108 PacketPtr
109 GUPSGen::getReadPacket(Addr addr, unsigned int size)
110 {
111  RequestPtr req = std::make_shared<Request>(addr, size, 0, requestorId);
112  // Dummy PC to have PC-based prefetchers latch on; get entropy into higher
113  // bits
114  req->setPC(((Addr)requestorId) << 2);
115 
116  // Embed it in a packet
117  PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
118  pkt->allocate();
119 
120  return pkt;
121 }
122 
123 PacketPtr
124 GUPSGen::getWritePacket(Addr addr, unsigned int size, uint8_t *data)
125 {
126  RequestPtr req = std::make_shared<Request>(addr, size, 0,
127  requestorId);
128  // Dummy PC to have PC-based prefetchers latch on; get entropy into higher
129  // bits
130  req->setPC(((Addr)requestorId) << 2);
131 
132  PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
133  pkt->allocate();
134  pkt->setData(data);
135 
136  return pkt;
137 }
138 
139 void
141 {
143  DPRINTF(GUPSGen, "%s: onTheFlyRequests: %d.\n",
144  __func__, onTheFlyRequests);
145  if (pkt->isWrite()) {
146  DPRINTF(GUPSGen, "%s: received a write resp. pkt->addr_range: %s,"
147  " pkt->data: %d\n", __func__,
148  pkt->getAddrRange().to_string(),
149  *pkt->getPtr<uint64_t>());
151  stats.totalWrites++;
153  stats.totalWriteLat += curTick() - exitTimes[pkt->req];
154 
155  exitTimes.erase(pkt->req);
156  delete pkt;
157  } else {
158  DPRINTF(GUPSGen, "%s: received a read resp. pkt->addr_range: %s\n",
159  __func__, pkt->getAddrRange().to_string());
160 
161  stats.totalReads++;
163  stats.totalReadLat += curTick() - exitTimes[pkt->req];
164 
165  exitTimes.erase(pkt->req);
166 
167  responsePool.push(pkt);
168  }
169  if (doneReading && requestPool.empty() && onTheFlyRequests == 0) {
170  exitSimLoop(name() + " is finished updating the memory.\n");
171  return;
172  }
173 
174  if ((requestPool.size() < reqQueueSize) &&
175  (!doneReading || !responsePool.empty()) &&
177  {
179  }
180 }
181 
182 void
184 {
185  if (!nextSendEvent.scheduled() && !requestPool.empty()) {
187  }
188 }
189 
190 void
192 {
193  // Prioritize pending writes over reads
194  // Write as soon as the data is read
195  if (!responsePool.empty()) {
196  PacketPtr pkt = responsePool.front();
197  responsePool.pop();
198 
199  uint64_t *updated_value = pkt->getPtr<uint64_t>();
200  DPRINTF(GUPSGen, "%s: Read value %lu from address %s", __func__,
201  *updated_value, pkt->getAddrRange().to_string());
202  *updated_value ^= updateTable[pkt->req];
203  updateTable.erase(pkt->req);
204  Addr addr = pkt->getAddr();
205  PacketPtr new_pkt = getWritePacket(addr,
206  elementSize, (uint8_t*) updated_value);
207  delete pkt;
208  requestPool.push(new_pkt);
209  } else if (!doneReading) {
210  // If no writes then read
211  // Check to make sure we're not reading more than we should.
212  assert (readRequests < numUpdates);
213 
214  uint64_t value = readRequests;
215  uint64_t index = random_mt.random((int64_t) 0, tableSize);
218  updateTable[pkt->req] = value;
219  requestPool.push(pkt);
220  readRequests++;
221 
222  if (readRequests >= numUpdates) {
223  DPRINTF(GUPSGen, "%s: Done creating reads.\n", __func__);
224  doneReading = true;
225  }
226  else if (readRequests == updateLimit && updateLimit != 0) {
227  DPRINTF(GUPSGen, "%s: Update limit reached.\n", __func__);
228  doneReading = true;
229  }
230  }
231 
232  if (!nextCreateEvent.scheduled() &&
233  (requestPool.size() < reqQueueSize) &&
234  (!doneReading || !responsePool.empty()))
235  {
237  }
238 
239  if (!nextSendEvent.scheduled() && !requestPool.empty()) {
241  }
242 }
243 
244 void
246 {
247  if (!port.blocked()) {
248  PacketPtr pkt = requestPool.front();
249 
250  exitTimes[pkt->req] = curTick();
251  if (pkt->isWrite()) {
252  DPRINTF(GUPSGen, "%s: Sent write pkt, pkt->addr_range: "
253  "%s, pkt->data: %lu.\n", __func__,
254  pkt->getAddrRange().to_string(),
255  *pkt->getPtr<uint64_t>());
256  } else {
257  DPRINTF(GUPSGen, "%s: Sent read pkt, pkt->addr_range: %s.\n",
258  __func__, pkt->getAddrRange().to_string());
259  }
260  port.sendTimingPacket(pkt);
262  DPRINTF(GUPSGen, "%s: onTheFlyRequests: %d.\n",
263  __func__, onTheFlyRequests);
264  requestPool.pop();
265  }
266 
267  if (!nextCreateEvent.scheduled() &&
268  (requestPool.size() < reqQueueSize) &&
269  (!doneReading || !responsePool.empty()))
270  {
272  }
273 
274  if (!nextSendEvent.scheduled()) {
275  if (!requestPool.empty()) {
277  }
278  }
279 }
280 
281 
282 void
284 {
285  panic_if(_blocked, "Should never try to send if blocked MemSide!");
286 
287  // If we can't send the packet across the port, store it for later.
288  if (!sendTimingReq(pkt)) {
289  DPRINTF(GUPSGen, "GenPort::%s: Packet blocked\n", __func__);
290  blockedPacket = pkt;
291  _blocked = true;
292  } else {
293  DPRINTF(GUPSGen, "GenPort::%s: Packet sent\n", __func__);
294  }
295 }
296 
297 void
299 {
300  sendFunctional(pkt);
301 }
302 
303 void
305 {
306  // We should have a blocked packet if this function is called.
307  DPRINTF(GUPSGen, "GenPort::%s: Received a retry.\n", __func__);
308 
309  assert(_blocked && (blockedPacket != nullptr));
310  // Try to resend it. It's possible that it fails again.
311  _blocked = false;
312  sendTimingPacket(blockedPacket);
313  if (!_blocked){
314  blockedPacket = nullptr;
315  }
316 
317  owner->wakeUp();
318 }
319 
320 bool
322 {
323  owner->handleResponse(pkt);
324  return true;
325 }
326 
328  statistics::Group(parent),
329  ADD_STAT(totalUpdates, statistics::units::Count::get(),
330  "Total number of updates the generator made in the memory"),
331  ADD_STAT(GUPS, statistics::units::Rate<statistics::units::Count,
332  statistics::units::Second>::get(),
333  "Rate of billion updates per second"),
334  ADD_STAT(totalReads, statistics::units::Count::get(),
335  "Total number of read requests"),
336  ADD_STAT(totalBytesRead, statistics::units::Byte::get(),
337  "Total number of bytes read"),
338  ADD_STAT(avgReadBW, statistics::units::Rate<statistics::units::Byte,
339  statistics::units::Second>::get(),
340  "Average read bandwidth received from memory"),
341  ADD_STAT(totalReadLat, statistics::units::Tick::get(),
342  "Total latency of read requests."),
343  ADD_STAT(avgReadLat, statistics::units::Tick::get(),
344  "Average latency for read requests"),
345  ADD_STAT(totalWrites, statistics::units::Count::get(),
346  "Total number of write requests"),
347  ADD_STAT(totalBytesWritten, statistics::units::Byte::get(),
348  "Total number of bytes written"),
349  ADD_STAT(avgWriteBW, statistics::units::Rate<statistics::units::Byte,
350  statistics::units::Second>::get(),
351  "Average write bandwidth received from memory"),
352  ADD_STAT(totalWriteLat, statistics::units::Tick::get(),
353  "Total latency of write requests."),
354  ADD_STAT(avgWriteLat, statistics::units::Tick::get(),
355  "Average latency for write requests")
356 {}
357 
358 void
360 {
361  GUPS.precision(8);
362  avgReadBW.precision(2);
363  avgReadLat.precision(2);
364  avgWriteBW.precision(2);
365  avgWriteLat.precision(2);
366 
367  GUPS = (totalUpdates / 1e9) / simSeconds;
368 
369  avgReadBW = totalBytesRead / simSeconds;
370  avgReadLat = (totalReadLat) / totalReads;
371 
372  avgWriteBW = totalBytesWritten / simSeconds;
373  avgWriteLat = (totalWriteLat) / totalWrites;
374 }
375 
376 }
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:252
gem5::SimObject::getPort
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Definition: sim_object.cc:126
gem5::GUPSGen::port
GenPort port
An instance of GenPort to communicate with the outside.
Definition: gups_gen.hh:249
gem5::AddrRange::to_string
std::string to_string() const
Get a string representation of the range.
Definition: addr_range.hh:360
gem5::RequestPort::sendTimingReq
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:495
gem5::GUPSGen::GUPSGen
GUPSGen(const GUPSGenParams &params)
Definition: gups_gen.cc:41
gem5::GUPSGen::GUPSGenStat::totalUpdates
statistics::Scalar totalUpdates
Definition: gups_gen.hh:309
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:47
gem5::Packet::setData
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
Definition: packet.hh:1252
gem5::GUPSGen::nextSendEvent
EventFunctionWrapper nextSendEvent
Corresponding event to the sendNextReq function.
Definition: gups_gen.hh:191
gem5::Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:366
gem5::GUPSGen::stats
gem5::GUPSGen::GUPSGenStat stats
gem5::GUPSGen::GUPSGenStat::totalWriteLat
statistics::Scalar totalWriteLat
Definition: gups_gen.hh:321
gem5::GUPSGen::GUPSGenStat::GUPSGenStat
GUPSGenStat(GUPSGen *parent)
Definition: gups_gen.cc:327
random.hh
gem5::GUPSGen::GenPort::blocked
bool blocked()
Return whether the port is blocked.
Definition: gups_gen.hh:100
gem5::GUPSGen::GenPort::recvTimingResp
bool recvTimingResp(PacketPtr pkt) override
Receive a timing response from the peer.
Definition: gups_gen.cc:321
gem5::GUPSGen::getWritePacket
PacketPtr getWritePacket(Addr addr, unsigned int size, uint8_t *data)
Generate a write request to be sent to the outside.
Definition: gups_gen.cc:124
gem5::GUPSGen::GenPort::recvReqRetry
void recvReqRetry() override
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Definition: gups_gen.cc:304
gem5::GUPSGen::sendNextReq
void sendNextReq()
Send outstanding requests from requestPool to the port.
Definition: gups_gen.cc:245
gem5::GUPSGen::memSize
const uint64_t memSize
Size of the memory in bytes that will be allocated for the array.
Definition: gups_gen.hh:259
gem5::Packet::isWrite
bool isWrite() const
Definition: packet.hh:583
gem5::GUPSGen::reqQueueSize
int reqQueueSize
The maximum number of outstanding requests (i.e.
Definition: gups_gen.hh:276
gem5::GUPSGen::GUPSGenStat::totalBytesRead
statistics::Scalar totalBytesRead
Definition: gups_gen.hh:313
gem5::GUPSGen::startup
virtual void startup() override
startup() is the final initialization call before simulation.
Definition: gups_gen.cc:79
gem5::GUPSGen::createNextReq
void createNextReq()
Create the next request and store in the requestPool.
Definition: gups_gen.cc:191
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:1003
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
gem5::GUPSGen::onTheFlyRequests
int onTheFlyRequests
The number of requests that have existed this GUPSGen and have no corresponding response (they are be...
Definition: gups_gen.hh:297
sim_exit.hh
gem5::GUPSGen::initMemory
bool initMemory
Boolean value to determine whether we need to initialize the array with the right values,...
Definition: gups_gen.hh:283
gem5::GUPSGen::handleResponse
void handleResponse(PacketPtr pkt)
Handles the incoming responses from the outside.
Definition: gups_gen.cc:140
gem5::exitSimLoop
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition: sim_events.cc:88
gem5::Random::random
std::enable_if_t< std::is_integral_v< T >, 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::GUPSGen::startAddr
Addr startAddr
The beginning address for allocating the array.
Definition: gups_gen.hh:254
gem5::GUPSGen::wakeUp
void wakeUp()
This function allows the port to wake its owner GUPSGen object in case it has stopped working due to ...
Definition: gups_gen.cc:183
gem5::GUPSGen::indexToAddr
Addr indexToAddr(uint64_t index)
Convert and index from array to its physical address in the memory.
Definition: gups_gen.cc:102
gem5::GUPSGen::nextCreateEvent
EventFunctionWrapper nextCreateEvent
Corresponding event to the createNextReq function.
Definition: gups_gen.hh:180
gem5::GUPSGen::responsePool
std::queue< PacketPtr > responsePool
A queue to store response packets from reads.
Definition: gups_gen.hh:221
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::probing::Packet
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:109
gem5::GUPSGen::GenPort::blockedPacket
PacketPtr blockedPacket
Pointer to the blocked packet in the port.
Definition: gups_gen.hh:85
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
gem5::MemCmd::ReadReq
@ ReadReq
Definition: packet.hh:86
gem5::GUPSGen::init
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: gups_gen.cc:68
gem5::GUPSGen::elementSize
const int elementSize
size of each element in the array (in bytes).
Definition: gups_gen.hh:270
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::GUPSGen::GenPort::_blocked
bool _blocked
Boolean value to remember if the port is previously blocked and is occupied by a previous request,...
Definition: gups_gen.hh:78
gem5::GUPSGen::GUPSGenStat::totalReadLat
statistics::Scalar totalReadLat
Definition: gups_gen.hh:315
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
name
const std::string & name()
Definition: trace.cc:49
gups_gen.hh
gem5::ClockedObject
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Definition: clocked_object.hh:234
gem5::Clocked::nextCycle
Tick nextCycle() const
Based on the clock of the object, determine the start tick of the first cycle that is at least one cy...
Definition: clocked_object.hh:213
gem5::GUPSGen::numUpdates
int64_t numUpdates
The total number of updates (one read and one write) to do for running the benchmark to completion.
Definition: gups_gen.hh:227
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
gem5::GUPSGen::updateLimit
int updateLimit
The number of updates to do before creating an exit event.
Definition: gups_gen.hh:264
gem5::GUPSGen
Definition: gups_gen.hh:53
gem5::Packet::allocate
void allocate()
Allocate memory for the packet.
Definition: packet.hh:1326
gem5::GUPSGen::updateTable
std::unordered_map< RequestPtr, uint64_t > updateTable
Use an unordered map to store future updates on current reads as the updated value depends on the ind...
Definition: gups_gen.hh:199
gem5::GUPSGen::getReadPacket
PacketPtr getReadPacket(Addr addr, unsigned int size)
Generate a read request to be sent to the outside.
Definition: gups_gen.cc:109
gem5::GUPSGen::requestorId
const RequestorID requestorId
Used to identify each requestor in a system object.
Definition: gups_gen.hh:244
gem5::simSeconds
statistics::Formula & simSeconds
Definition: stats.cc:45
gem5::MemCmd::WriteReq
@ WriteReq
Definition: packet.hh:89
gem5::GUPSGen::GUPSGenStat::totalBytesWritten
statistics::Scalar totalBytesWritten
Definition: gups_gen.hh:319
gem5::GUPSGen::requestPool
std::queue< PacketPtr > requestPool
A queue to store the outstanding requests whether read or write.
Definition: gups_gen.hh:213
gem5::statistics::Group
Statistics container.
Definition: group.hh:93
gem5::GUPSGen::GUPSGenStat::regStats
void regStats() override
Callback to set stat parameters.
Definition: gups_gen.cc:359
gem5::GUPSGen::GenPort::sendTimingPacket
void sendTimingPacket(PacketPtr pkt)
This function send a timing request to the port's peer responsePort.
Definition: gups_gen.cc:283
gem5::GUPSGen::doneReading
bool doneReading
Boolean to indicate whether the generator is done creating read requests, which means number of reads...
Definition: gups_gen.hh:290
gem5::GUPSGen::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: gups_gen.cc:58
gem5::GUPSGen::GUPSGenStat::totalWrites
statistics::Scalar totalWrites
Definition: gups_gen.hh:318
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:781
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: tlb.cc:60
gem5::GUPSGen::readRequests
int readRequests
The number of read requests currently created.
Definition: gups_gen.hh:302
gem5::Packet::getAddrRange
AddrRange getAddrRange() const
Get address range to which this packet belongs.
Definition: packet.cc:225
gem5::random_mt
Random random_mt
Definition: random.cc:99
gem5::GUPSGen::exitTimes
std::unordered_map< RequestPtr, Tick > exitTimes
Use an unordered map to track the time at which each request exits the GUPSGen.
Definition: gups_gen.hh:206
gem5::GUPSGen::tableSize
int64_t tableSize
Number of elements in the allocated array.
Definition: gups_gen.hh:232
gem5::GUPSGen::GUPSGenStat::totalReads
statistics::Scalar totalReads
Definition: gups_gen.hh:312
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::Packet::getPtr
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1184
gem5::GUPSGen::GenPort::sendFunctionalPacket
void sendFunctionalPacket(PacketPtr pkt)
This function send a functional request to the port's peer responsePort.
Definition: gups_gen.cc:298

Generated on Wed May 4 2022 12:13:55 for gem5 by doxygen 1.8.17