gem5 v24.0.0.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 "base/random.hh"
35#include "debug/GUPSGen.hh"
36#include "sim/sim_exit.hh"
37
38namespace gem5
39{
40
41GUPSGen::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
57Port&
58GUPSGen::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
67void
69{
70 doneReading = false;
72 readRequests = 0;
73
76}
77
78void
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
101Addr
103{
105 return ret;
106}
107
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
124GUPSGen::getWritePacket(Addr addr, unsigned int size, uint8_t *data)
125{
126 RequestPtr req = std::make_shared<Request>(addr, size, 0,
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
139void
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>());
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
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
182void
184{
185 if (!nextSendEvent.scheduled() && !requestPool.empty()) {
187 }
188}
189
190void
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
244void
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 }
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
282void
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
297void
299{
300 sendFunctional(pkt);
301}
302
303void
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
320bool
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
358void
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:210
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: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.
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: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 - Pranith Kumar Copyright (c) 2020 Inria 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: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:48

Generated on Tue Jun 18 2024 16:24:02 for gem5 by doxygen 1.11.0