gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
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 "debug/GUPSGen.hh"
35#include "sim/sim_exit.hh"
36
37namespace gem5
38{
39
40GUPSGen::GUPSGen(const GUPSGenParams& params):
42 nextCreateEvent([this]{ createNextReq(); }, name()),
43 nextSendEvent([this]{ sendNextReq(); }, name()),
44 system(params.system),
45 requestorId(system->getRequestorId(this)),
46 port(name() + ".port", this),
47 startAddr(params.start_addr),
48 memSize(params.mem_size),
49 updateLimit(params.update_limit),
50 elementSize(sizeof(uint64_t)), // every element in the table is a uint64_t
51 reqQueueSize(params.request_queue_size),
52 initMemory(params.init_memory),
53 stats(this)
54{}
55
56Port&
57GUPSGen::getPort(const std::string &if_name, PortID idx)
58{
59 if (if_name != "port") {
60 return ClockedObject::getPort(if_name, idx);
61 } else {
62 return port;
63 }
64}
65
66void
68{
69 doneReading = false;
71 readRequests = 0;
72
75}
76
77void
79{
80 int block_size = 64; // Write the initial values in 64 byte blocks.
81 uint64_t stride_size = block_size / elementSize;
82 auto write_data = std::make_unique<uint8_t[]>(block_size);
83 if (initMemory) {
84 for (uint64_t start_index = 0; start_index < tableSize;
85 start_index += stride_size) {
86 for (uint64_t offset = 0; offset < stride_size; offset++) {
87 uint64_t value = start_index + offset;
88 std::memcpy(write_data.get() + offset * elementSize,
89 &value, elementSize);
90 }
91 Addr addr = indexToAddr(start_index);
92 PacketPtr pkt = getWritePacket(addr, block_size, write_data.get());
93 port.sendFunctionalPacket(pkt);
94 delete pkt;
95 }
96 }
98}
99
100Addr
102{
104 return ret;
105}
106
109{
110 RequestPtr req = std::make_shared<Request>(addr, size, 0, requestorId);
111 // Dummy PC to have PC-based prefetchers latch on; get entropy into higher
112 // bits
113 req->setPC(((Addr)requestorId) << 2);
114
115 // Embed it in a packet
116 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
117 pkt->allocate();
118
119 return pkt;
120}
121
123GUPSGen::getWritePacket(Addr addr, unsigned int size, uint8_t *data)
124{
125 RequestPtr req = std::make_shared<Request>(addr, size, 0,
127 // Dummy PC to have PC-based prefetchers latch on; get entropy into higher
128 // bits
129 req->setPC(((Addr)requestorId) << 2);
130
131 PacketPtr pkt = new Packet(req, MemCmd::WriteReq);
132 pkt->allocate();
133 pkt->setData(data);
134
135 return pkt;
136}
137
138void
140{
142 DPRINTF(GUPSGen, "%s: onTheFlyRequests: %d.\n",
143 __func__, onTheFlyRequests);
144 if (pkt->isWrite()) {
145 DPRINTF(GUPSGen, "%s: received a write resp. pkt->addr_range: %s,"
146 " pkt->data: %d\n", __func__,
147 pkt->getAddrRange().to_string(),
148 *pkt->getPtr<uint64_t>());
149 stats.totalUpdates++;
150 stats.totalWrites++;
151 stats.totalBytesWritten += elementSize;
152 stats.totalWriteLat += curTick() - exitTimes[pkt->req];
153
154 exitTimes.erase(pkt->req);
155 delete pkt;
156 } else {
157 DPRINTF(GUPSGen, "%s: received a read resp. pkt->addr_range: %s\n",
158 __func__, pkt->getAddrRange().to_string());
159
160 stats.totalReads++;
161 stats.totalBytesRead += elementSize;
162 stats.totalReadLat += curTick() - exitTimes[pkt->req];
163
164 exitTimes.erase(pkt->req);
165
166 responsePool.push(pkt);
167 }
168 if (doneReading && requestPool.empty() && onTheFlyRequests == 0) {
169 exitSimLoop(name() + " is finished updating the memory.\n");
170 return;
171 }
172
173 if ((requestPool.size() < reqQueueSize) &&
174 (!doneReading || !responsePool.empty()) &&
175 !nextCreateEvent.scheduled())
176 {
178 }
179}
180
181void
183{
184 if (!nextSendEvent.scheduled() && !requestPool.empty()) {
186 }
187}
188
189void
191{
192 // Prioritize pending writes over reads
193 // Write as soon as the data is read
194 if (!responsePool.empty()) {
195 PacketPtr pkt = responsePool.front();
196 responsePool.pop();
197
198 uint64_t *updated_value = pkt->getPtr<uint64_t>();
199 DPRINTF(GUPSGen, "%s: Read value %lu from address %s", __func__,
200 *updated_value, pkt->getAddrRange().to_string());
201 *updated_value ^= updateTable[pkt->req];
202 updateTable.erase(pkt->req);
203 Addr addr = pkt->getAddr();
204 PacketPtr new_pkt = getWritePacket(addr,
205 elementSize, (uint8_t*) updated_value);
206 delete pkt;
207 requestPool.push(new_pkt);
208 } else if (!doneReading) {
209 // If no writes then read
210 // Check to make sure we're not reading more than we should.
211 assert (readRequests < numUpdates);
212
213 uint64_t value = readRequests;
214 uint64_t index = rng->random<int64_t>((int64_t) 0, tableSize);
217 updateTable[pkt->req] = value;
218 requestPool.push(pkt);
219 readRequests++;
220
221 if (readRequests >= numUpdates) {
222 DPRINTF(GUPSGen, "%s: Done creating reads.\n", __func__);
223 doneReading = true;
224 }
225 else if (readRequests == updateLimit && updateLimit != 0) {
226 DPRINTF(GUPSGen, "%s: Update limit reached.\n", __func__);
227 doneReading = true;
228 }
229 }
230
231 if (!nextCreateEvent.scheduled() &&
232 (requestPool.size() < reqQueueSize) &&
233 (!doneReading || !responsePool.empty()))
234 {
236 }
237
238 if (!nextSendEvent.scheduled() && !requestPool.empty()) {
240 }
241}
242
243void
245{
246 if (!port.blocked()) {
247 PacketPtr pkt = requestPool.front();
248
249 exitTimes[pkt->req] = curTick();
250 if (pkt->isWrite()) {
251 DPRINTF(GUPSGen, "%s: Sent write pkt, pkt->addr_range: "
252 "%s, pkt->data: %lu.\n", __func__,
253 pkt->getAddrRange().to_string(),
254 *pkt->getPtr<uint64_t>());
255 } else {
256 DPRINTF(GUPSGen, "%s: Sent read pkt, pkt->addr_range: %s.\n",
257 __func__, pkt->getAddrRange().to_string());
258 }
259 port.sendTimingPacket(pkt);
261 DPRINTF(GUPSGen, "%s: onTheFlyRequests: %d.\n",
262 __func__, onTheFlyRequests);
263 requestPool.pop();
264 }
265
266 if (!nextCreateEvent.scheduled() &&
267 (requestPool.size() < reqQueueSize) &&
268 (!doneReading || !responsePool.empty()))
269 {
271 }
272
273 if (!nextSendEvent.scheduled()) {
274 if (!requestPool.empty()) {
276 }
277 }
278}
279
280
281void
283{
284 panic_if(_blocked, "Should never try to send if blocked MemSide!");
285
286 // If we can't send the packet across the port, store it for later.
287 if (!sendTimingReq(pkt)) {
288 DPRINTF(GUPSGen, "GenPort::%s: Packet blocked\n", __func__);
289 blockedPacket = pkt;
290 _blocked = true;
291 } else {
292 DPRINTF(GUPSGen, "GenPort::%s: Packet sent\n", __func__);
293 }
294}
295
296void
301
302void
304{
305 // We should have a blocked packet if this function is called.
306 DPRINTF(GUPSGen, "GenPort::%s: Received a retry.\n", __func__);
307
308 assert(_blocked && (blockedPacket != nullptr));
309 // Try to resend it. It's possible that it fails again.
310 _blocked = false;
312 if (!_blocked){
313 blockedPacket = nullptr;
314 }
315
316 owner->wakeUp();
317}
318
319bool
321{
322 owner->handleResponse(pkt);
323 return true;
324}
325
327 statistics::Group(parent),
328 ADD_STAT(totalUpdates, statistics::units::Count::get(),
329 "Total number of updates the generator made in the memory"),
331 statistics::units::Second>::get(),
332 "Rate of billion updates per second"),
333 ADD_STAT(totalReads, statistics::units::Count::get(),
334 "Total number of read requests"),
336 "Total number of bytes read"),
338 statistics::units::Second>::get(),
339 "Average read bandwidth received from memory"),
341 "Total latency of read requests."),
343 "Average latency for read requests"),
344 ADD_STAT(totalWrites, statistics::units::Count::get(),
345 "Total number of write requests"),
347 "Total number of bytes written"),
349 statistics::units::Second>::get(),
350 "Average write bandwidth received from memory"),
352 "Total latency of write requests."),
354 "Average latency for write requests")
355{}
356
357void
359{
360 GUPS.precision(8);
361 avgReadBW.precision(2);
362 avgReadLat.precision(2);
363 avgWriteBW.precision(2);
364 avgWriteLat.precision(2);
365
366 GUPS = (totalUpdates / 1e9) / simSeconds;
367
370
373}
374
375}
#define DPRINTF(x,...)
Definition trace.hh:209
const char data[]
ClockedObject(const ClockedObjectParams &p)
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:282
GUPSGen * owner
Pointer to the GUPSGen this port belongs to.
Definition gups_gen.hh:71
PacketPtr blockedPacket
Pointer to the blocked packet in the port.
Definition gups_gen.hh:86
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:303
void sendFunctionalPacket(PacketPtr pkt)
This function send a functional request to the port's peer responsePort.
Definition gups_gen.cc:297
bool _blocked
Boolean value to remember if the port is previously blocked and is occupied by a previous request,...
Definition gups_gen.hh:79
bool recvTimingResp(PacketPtr pkt) override
Receive a timing response from the peer.
Definition gups_gen.cc:320
std::queue< PacketPtr > requestPool
A queue to store the outstanding requests whether read or write.
Definition gups_gen.hh:214
const uint64_t memSize
Size of the memory in bytes that will be allocated for the array.
Definition gups_gen.hh:260
int64_t tableSize
Number of elements in the allocated array.
Definition gups_gen.hh:233
void handleResponse(PacketPtr pkt)
Handles the incoming responses from the outside.
Definition gups_gen.cc:139
GUPSGen(const GUPSGenParams &params)
Definition gups_gen.cc:40
EventFunctionWrapper nextSendEvent
Corresponding event to the sendNextReq function.
Definition gups_gen.hh:192
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:182
virtual void startup() override
startup() is the final initialization call before simulation.
Definition gups_gen.cc:78
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:291
Addr startAddr
The beginning address for allocating the array.
Definition gups_gen.hh:255
int updateLimit
The number of updates to do before creating an exit event.
Definition gups_gen.hh:265
void sendNextReq()
Send outstanding requests from requestPool to the port.
Definition gups_gen.cc:244
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:207
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition gups_gen.cc:57
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition gups_gen.cc:67
int readRequests
The number of read requests currently created.
Definition gups_gen.hh:303
GenPort port
An instance of GenPort to communicate with the outside.
Definition gups_gen.hh:250
const RequestorID requestorId
Used to identify each requestor in a system object.
Definition gups_gen.hh:245
int reqQueueSize
The maximum number of outstanding requests (i.e.
Definition gups_gen.hh:277
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:200
const int elementSize
size of each element in the array (in bytes).
Definition gups_gen.hh:271
PacketPtr getReadPacket(Addr addr, unsigned int size)
Generate a read request to be sent to the outside.
Definition gups_gen.cc:108
Addr indexToAddr(uint64_t index)
Convert and index from array to its physical address in the memory.
Definition gups_gen.cc:101
void createNextReq()
Create the next request and store in the requestPool.
Definition gups_gen.cc:190
int onTheFlyRequests
The number of requests that have existed this GUPSGen and have no corresponding response (they are be...
Definition gups_gen.hh:298
PacketPtr getWritePacket(Addr addr, unsigned int size, uint8_t *data)
Generate a write request to be sent to the outside.
Definition gups_gen.cc:123
std::queue< PacketPtr > responsePool
A queue to store response packets from reads.
Definition gups_gen.hh:222
Random::RandomPtr rng
Definition gups_gen.hh:305
bool initMemory
Boolean value to determine whether we need to initialize the array with the right values,...
Definition gups_gen.hh:284
EventFunctionWrapper nextCreateEvent
Corresponding event to the createNextReq function.
Definition gups_gen.hh:181
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:228
virtual std::string name() const
Definition named.hh:60
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
AddrRange getAddrRange() const
Get address range to which this packet belongs.
Definition packet.cc:243
T * getPtr()
get a pointer to the data ptr.
Definition packet.hh:1225
void setData(const uint8_t *p)
Copy data into the packet from the provided pointer.
Definition packet.hh:1293
bool isWrite() const
Definition packet.hh:594
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
void allocate()
Allocate memory for the packet.
Definition packet.hh:1367
Ports are used to interface objects to each other.
Definition port.hh:62
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition port.hh:603
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition port.hh:579
#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.
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
const Params & params() const
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
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:1032
Bitfield< 3 > addr
Definition types.hh:84
Units for Stats.
Definition units.hh:113
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::shared_ptr< Request > RequestPtr
Definition request.hh:94
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
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
The "old style" exitSimLoop functions.
uint64_t Tick
Tick count type.
Definition types.hh:58
Packet * PacketPtr
statistics::Formula & simSeconds
Definition stats.cc:45
statistics::Formula avgWriteBW
Definition gups_gen.hh:323
statistics::Scalar totalWriteLat
Definition gups_gen.hh:324
statistics::Scalar totalUpdates
Definition gups_gen.hh:312
GUPSGenStat(GUPSGen *parent)
Definition gups_gen.cc:326
void regStats() override
Callback to set stat parameters.
Definition gups_gen.cc:358
statistics::Scalar totalReadLat
Definition gups_gen.hh:318
statistics::Scalar totalReads
Definition gups_gen.hh:315
statistics::Scalar totalBytesRead
Definition gups_gen.hh:316
statistics::Formula avgReadBW
Definition gups_gen.hh:317
statistics::Formula GUPS
Definition gups_gen.hh:313
statistics::Scalar totalWrites
Definition gups_gen.hh:321
statistics::Scalar totalBytesWritten
Definition gups_gen.hh:322
statistics::Formula avgReadLat
Definition gups_gen.hh:319
statistics::Formula avgWriteLat
Definition gups_gen.hh:325
const std::string & name()
Definition trace.cc:48

Generated on Mon May 26 2025 09:19:09 for gem5 by doxygen 1.13.2