gem5  v22.1.0.0
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 }
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Tick nextCycle() const
Based on the clock of the object, determine the start tick of the first cycle that is at least one cy...
void sendTimingPacket(PacketPtr pkt)
This function send a timing request to the port's peer responsePort.
Definition: gups_gen.cc:283
bool blocked()
Return whether the port is blocked.
Definition: gups_gen.hh:100
PacketPtr blockedPacket
Pointer to the blocked packet in the port.
Definition: gups_gen.hh:85
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
void sendFunctionalPacket(PacketPtr pkt)
This function send a functional request to the port's peer responsePort.
Definition: gups_gen.cc:298
bool _blocked
Boolean value to remember if the port is previously blocked and is occupied by a previous request,...
Definition: gups_gen.hh:78
bool recvTimingResp(PacketPtr pkt) override
Receive a timing response from the peer.
Definition: gups_gen.cc:321
std::queue< PacketPtr > requestPool
A queue to store the outstanding requests whether read or write.
Definition: gups_gen.hh:213
const uint64_t memSize
Size of the memory in bytes that will be allocated for the array.
Definition: gups_gen.hh:259
int64_t tableSize
Number of elements in the allocated array.
Definition: gups_gen.hh:232
void handleResponse(PacketPtr pkt)
Handles the incoming responses from the outside.
Definition: gups_gen.cc:140
GUPSGen(const GUPSGenParams &params)
Definition: gups_gen.cc:41
EventFunctionWrapper nextSendEvent
Corresponding event to the sendNextReq function.
Definition: gups_gen.hh:191
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
virtual void startup() override
startup() is the final initialization call before simulation.
Definition: gups_gen.cc:79
gem5::GUPSGen::GUPSGenStat stats
bool doneReading
Boolean to indicate whether the generator is done creating read requests, which means number of reads...
Definition: gups_gen.hh:290
Addr startAddr
The beginning address for allocating the array.
Definition: gups_gen.hh:254
int updateLimit
The number of updates to do before creating an exit event.
Definition: gups_gen.hh:264
void sendNextReq()
Send outstanding requests from requestPool to the port.
Definition: gups_gen.cc:245
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
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
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: gups_gen.cc:68
int readRequests
The number of read requests currently created.
Definition: gups_gen.hh:302
GenPort port
An instance of GenPort to communicate with the outside.
Definition: gups_gen.hh:249
const RequestorID requestorId
Used to identify each requestor in a system object.
Definition: gups_gen.hh:244
int reqQueueSize
The maximum number of outstanding requests (i.e.
Definition: gups_gen.hh:276
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
const int elementSize
size of each element in the array (in bytes).
Definition: gups_gen.hh:270
PacketPtr getReadPacket(Addr addr, unsigned int size)
Generate a read request to be sent to the outside.
Definition: gups_gen.cc:109
Addr indexToAddr(uint64_t index)
Convert and index from array to its physical address in the memory.
Definition: gups_gen.cc:102
void createNextReq()
Create the next request and store in the requestPool.
Definition: gups_gen.cc:191
int onTheFlyRequests
The number of requests that have existed this GUPSGen and have no corresponding response (they are be...
Definition: gups_gen.hh:297
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
std::queue< PacketPtr > responsePool
A queue to store response packets from reads.
Definition: gups_gen.hh:221
bool initMemory
Boolean value to determine whether we need to initialize the array with the right values,...
Definition: gups_gen.hh:283
EventFunctionWrapper nextCreateEvent
Corresponding event to the createNextReq function.
Definition: gups_gen.hh:180
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
virtual std::string name() const
Definition: named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:1212
Addr getAddr() const
Definition: packet.hh:805
AddrRange getAddrRange() const
Get address range to which this packet belongs.
Definition: packet.cc:243
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
Definition: packet.hh:1280
bool isWrite() const
Definition: packet.hh:593
RequestPtr req
A pointer to the original request.
Definition: packet.hh:376
void allocate()
Allocate memory for the packet.
Definition: packet.hh:1354
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:495
Statistics container.
Definition: group.hh:94
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
std::string to_string() const
Get a string representation of the range.
Definition: addr_range.hh:360
Random random_mt
Definition: random.cc:99
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
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
#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
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
Contatins the description of the class GUPSGen.
Bitfield< 23, 0 > offset
Definition: types.hh:144
Bitfield< 30, 0 > index
Bitfield< 15 > system
Definition: misc.hh:1004
Bitfield< 3 > addr
Definition: types.hh:84
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:109
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:245
uint64_t Tick
Tick count type.
Definition: types.hh:58
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
statistics::Formula & simSeconds
Definition: stats.cc:45
statistics::Scalar totalWriteLat
Definition: gups_gen.hh:321
statistics::Scalar totalUpdates
Definition: gups_gen.hh:309
GUPSGenStat(GUPSGen *parent)
Definition: gups_gen.cc:327
void regStats() override
Callback to set stat parameters.
Definition: gups_gen.cc:359
statistics::Scalar totalReadLat
Definition: gups_gen.hh:315
statistics::Scalar totalReads
Definition: gups_gen.hh:312
statistics::Scalar totalBytesRead
Definition: gups_gen.hh:313
statistics::Scalar totalWrites
Definition: gups_gen.hh:318
statistics::Scalar totalBytesWritten
Definition: gups_gen.hh:319
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:32 for gem5 by doxygen 1.9.1