gem5 v24.1.0.1
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):
41 ClockedObject(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 if (initMemory) {
83 for (uint64_t start_index = 0; start_index < tableSize;
84 start_index += stride_size) {
85 uint8_t write_data[block_size];
86 for (uint64_t offset = 0; offset < stride_size; offset++) {
87 uint64_t value = start_index + offset;
88 std::memcpy(write_data + offset * elementSize,
89 &value, elementSize);
90 }
91 Addr addr = indexToAddr(start_index);
92 PacketPtr pkt = getWritePacket(addr, block_size, write_data);
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>());
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
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()) &&
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 }
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
298{
299 sendFunctional(pkt);
300}
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;
311 sendTimingPacket(blockedPacket);
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"),
330 ADD_STAT(GUPS, statistics::units::Rate<statistics::units::Count,
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"),
335 ADD_STAT(totalBytesRead, statistics::units::Byte::get(),
336 "Total number of bytes read"),
337 ADD_STAT(avgReadBW, statistics::units::Rate<statistics::units::Byte,
338 statistics::units::Second>::get(),
339 "Average read bandwidth received from memory"),
340 ADD_STAT(totalReadLat, statistics::units::Tick::get(),
341 "Total latency of read requests."),
342 ADD_STAT(avgReadLat, statistics::units::Tick::get(),
343 "Average latency for read requests"),
344 ADD_STAT(totalWrites, statistics::units::Count::get(),
345 "Total number of write requests"),
346 ADD_STAT(totalBytesWritten, statistics::units::Byte::get(),
347 "Total number of bytes written"),
348 ADD_STAT(avgWriteBW, statistics::units::Rate<statistics::units::Byte,
349 statistics::units::Second>::get(),
350 "Average write bandwidth received from memory"),
351 ADD_STAT(totalWriteLat, statistics::units::Tick::get(),
352 "Total latency of write requests."),
353 ADD_STAT(avgWriteLat, statistics::units::Tick::get(),
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
368 avgReadBW = totalBytesRead / simSeconds;
369 avgReadLat = (totalReadLat) / totalReads;
370
371 avgWriteBW = totalBytesWritten / simSeconds;
372 avgWriteLat = (totalWriteLat) / totalWrites;
373}
374
375}
#define DPRINTF(x,...)
Definition trace.hh:209
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:282
bool blocked()
Return whether the port is blocked.
Definition gups_gen.hh:101
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:47
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
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition port.hh:603
Statistics container.
Definition group.hh:93
#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.
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
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:214
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
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
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: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::Scalar totalWrites
Definition gups_gen.hh:321
statistics::Scalar totalBytesWritten
Definition gups_gen.hh:322
const std::string & name()
Definition trace.cc:48

Generated on Mon Jan 13 2025 04:28:32 for gem5 by doxygen 1.9.8