gem5 v24.1.0.1
Loading...
Searching...
No Matches
memtest.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, 2019, 2021 Arm Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2002-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
42
43#include "base/compiler.hh"
44#include "base/statistics.hh"
45#include "base/trace.hh"
46#include "debug/MemTest.hh"
47#include "sim/sim_exit.hh"
48#include "sim/stats.hh"
49#include "sim/system.hh"
50
51namespace gem5
52{
53
54static unsigned int TESTER_ALLOCATOR = 0;
55
56bool
62
63void
65{
66 memtest.recvRetry();
67}
68
69bool
71 if (atomic) {
72 port.sendAtomic(pkt);
73 completeRequest(pkt);
74 } else {
75 if (!port.sendTimingReq(pkt)) {
76 retryPkt = pkt;
77 return false;
78 }
79 }
80 return true;
81}
82
85 tickEvent([this]{ tick(); }, name()),
86 noRequestEvent([this]{ noRequest(); }, name()),
87 noResponseEvent([this]{ noResponse(); }, name()),
88 port("port", *this),
89 retryPkt(nullptr),
90 waitResponse(false),
91 size(p.size),
92 interval(p.interval),
93 percentReads(p.percent_reads),
94 percentFunctional(p.percent_functional),
95 percentUncacheable(p.percent_uncacheable),
96 percentAtomic(p.percent_atomic),
97 requestorId(p.system->getRequestorId(this)),
98 blockSize(p.system->cacheLineSize()),
99 blockAddrMask(blockSize - 1),
100 sizeBlocks(size / blockSize),
101 baseAddr1(p.base_addr_1),
102 baseAddr2(p.base_addr_2),
103 uncacheAddr(p.uncacheable_base_addr),
104 progressInterval(p.progress_interval),
105 progressCheck(p.progress_check),
106 nextProgressMessage(p.progress_interval),
107 maxLoads(p.max_loads),
108 atomic(p.system->isAtomicMode()),
109 suppressFuncErrors(p.suppress_func_errors), stats(this)
110{
111 id = TESTER_ALLOCATOR++;
112 fatal_if(id >= blockSize, "Too many testers, only %d allowed\n",
113 blockSize - 1);
114
115 // set up counters
116 numReads = 0;
117 numWrites = 0;
118 numAtomics = 0;
119
120 // kick things into action
121 schedule(tickEvent, curTick());
122 schedule(noRequestEvent, clockEdge(progressCheck));
123}
124
125Port &
126MemTest::getPort(const std::string &if_name, PortID idx)
127{
128 if (if_name == "port")
129 return port;
130 else
131 return ClockedObject::getPort(if_name, idx);
132}
133
134void
136{
137 const RequestPtr &req = pkt->req;
138 assert(req->getSize() == 1);
139
140 // this address is no longer outstanding
141 auto remove_addr = outstandingAddrs.find(req->getPaddr());
142 assert(remove_addr != outstandingAddrs.end());
143 outstandingAddrs.erase(remove_addr);
144
145 DPRINTF(MemTest, "Completing %s at address %x (blk %x) %s\n",
146 pkt->isWrite() ? pkt->isAtomicOp() ? "atomic" : "write" : "read",
147 req->getPaddr(), blockAlign(req->getPaddr()),
148 pkt->isError() ? "error" : "success");
149
150 const uint8_t *pkt_data = pkt->getConstPtr<uint8_t>();
151
152 if (pkt->isError()) {
153 if (!functional || !pkt->suppressFuncError() || !suppressFuncErrors)
154 panic( "%s access failed at %#x\n",
155 pkt->isWrite() ? "Write" : "Read", req->getPaddr());
156 } else {
157 if (pkt->isAtomicOp()) {
158 uint8_t ref_data = referenceData[req->getPaddr()];
159 if (pkt_data[0] != ref_data) {
160 panic("%s: read of %x (blk %x) @ cycle %d "
161 "returns %x, expected %x\n", name(),
162 req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
163 pkt_data[0], ref_data);
164 }
166 "Completing atomic at address %x (blk %x) value %x\n",
167 req->getPaddr(), blockAlign(req->getPaddr()),
168 pkt_data[0]);
169
170 referenceData[req->getPaddr()] =
171 atomicPendingData[req->getPaddr()];
172
173 numAtomics++;
175 } else if (pkt->isRead()) {
176 uint8_t ref_data = referenceData[req->getPaddr()];
177 if (pkt_data[0] != ref_data) {
178 panic("%s: read of %x (blk %x) @ cycle %d "
179 "returns %x, expected %x\n", name(),
180 req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
181 pkt_data[0], ref_data);
182 }
183
184 numReads++;
185 stats.numReads++;
186
187 if (numReads == (uint64_t)nextProgressMessage) {
188 ccprintf(std::cerr,
189 "%s: completed %d read, %d write, "
190 "%d atomic accesses @%d\n",
193 }
194
195 if (maxLoads != 0 && numReads >= maxLoads)
196 exitSimLoop("maximum number of loads reached");
197 } else {
198 assert(pkt->isWrite());
199
200 // update the reference data
201 referenceData[req->getPaddr()] = pkt_data[0];
202 numWrites++;
204 }
205 }
206
207 // the packet will delete the data
208 delete pkt;
209
210 // finally shift the response timeout forward if we are still
211 // expecting responses; deschedule it otherwise
212 if (outstandingAddrs.size() != 0)
214 else if (noResponseEvent.scheduled())
216
217 // schedule the next tick
218 if (waitResponse) {
219 waitResponse = false;
221 }
222}
224 : statistics::Group(parent),
225 ADD_STAT(numReads, statistics::units::Count::get(),
226 "number of read accesses completed"),
227 ADD_STAT(numWrites, statistics::units::Count::get(),
228 "number of write accesses completed"),
229 ADD_STAT(numAtomics, statistics::units::Count::get(),
230 "number of atomic accesses completed")
231{
232
233}
234
235void
237{
238 // we should never tick if we are waiting for a retry or response
239 assert(!retryPkt);
240 assert(!waitResponse);
241
242 // create a new request
243 unsigned cmd = rng->random(0, 100);
244 uint8_t data = rng->random<uint8_t>();
245 bool uncacheable = rng->random(0, 100) < percentUncacheable;
246 bool do_atomic = (rng->random(0, 100) < percentAtomic) &&
247 !uncacheable;
248 unsigned base = rng->random(0, 1);
250 Addr paddr;
251
252 // halt until we clear outstanding requests, otherwise it won't be able to
253 // find a new unique address
254 if (outstandingAddrs.size() >= sizeBlocks) {
255 waitResponse = true;
256 return;
257 }
258
259 // generate a unique address
260 do {
261 unsigned offset = rng->random<unsigned>(0, size - 1);
262
263 // use the tester id as offset within the block for false sharing
265 offset += id;
266
267 if (uncacheable) {
269 paddr = uncacheAddr + offset;
270 } else {
271 paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
272 }
273 } while (outstandingAddrs.find(paddr) != outstandingAddrs.end());
274
275 bool do_functional = (rng->random(0, 100) < percentFunctional) &&
276 !uncacheable;
277 RequestPtr req = std::make_shared<Request>(paddr, 1, flags, requestorId);
278 req->setContext(id);
279
280 outstandingAddrs.insert(paddr);
281
282 // sanity check
283 panic_if(outstandingAddrs.size() > 100,
284 "Tester %s has more than 100 outstanding requests\n", name());
285
286 PacketPtr pkt = nullptr;
287 uint8_t *pkt_data = new uint8_t[1];
288
289 if (cmd < percentReads) {
290 // start by ensuring there is a reference value if we have not
291 // seen this address before
292 [[maybe_unused]] uint8_t ref_data = 0;
293 auto ref = referenceData.find(req->getPaddr());
294 if (ref == referenceData.end()) {
295 referenceData[req->getPaddr()] = 0;
296 } else {
297 ref_data = ref->second;
298 }
299
301 "Initiating %sread at addr %x (blk %x) expecting %x\n",
302 do_functional ? "functional " : "", req->getPaddr(),
303 blockAlign(req->getPaddr()), ref_data);
304
305 pkt = new Packet(req, MemCmd::ReadReq);
306 pkt->dataDynamic(pkt_data);
307 } else {
308 if (do_atomic) {
310 "Initiating atomic at addr %x (blk %x) value %x\n",
311 req->getPaddr(), blockAlign(req->getPaddr()), data);
312
315 data, data,
316 [](uint8_t* b, uint8_t a, uint8_t c){
317 *b = c;
318 });
319 assert(_amo_op);
320 AtomicOpFunctorPtr amo_op = AtomicOpFunctorPtr(_amo_op);
321 req->setAtomicOpFunctor(std::move(amo_op));
322 req->setFlags(Request::ATOMIC_RETURN_OP);
323
324 pkt = new Packet(req, MemCmd::WriteReq);
325 pkt->dataDynamic(pkt_data);
326 pkt_data[0] = data;
327 atomicPendingData[req->getPaddr()] = data;
328 } else {
330 "Initiating %swrite at addr %x (blk %x) value %x\n",
331 do_functional ? "functional " : "", req->getPaddr(),
332 blockAlign(req->getPaddr()), data);
333
334 pkt = new Packet(req, MemCmd::WriteReq);
335 pkt->dataDynamic(pkt_data);
336 pkt_data[0] = data;
337 }
338 }
339
340 // there is no point in ticking if we are waiting for a retry
341 bool keep_ticking = true;
342 if (do_functional) {
344 port.sendFunctional(pkt);
345 completeRequest(pkt, true);
346 } else {
347 keep_ticking = sendPkt(pkt);
348 }
349
350 if (keep_ticking) {
351 // schedule the next tick
353
354 // finally shift the timeout for sending of requests forwards
355 // as we have successfully sent a packet
357 } else {
358 DPRINTF(MemTest, "Waiting for retry\n");
359 }
360
361 // Schedule noResponseEvent now if we are expecting a response
362 if (!noResponseEvent.scheduled() && (outstandingAddrs.size() != 0))
364}
365
366void
368{
369 panic("%s did not send a request for %d cycles", name(), progressCheck);
370}
371
372void
374{
375 panic("%s did not see a response for %d cycles", name(), progressCheck);
376}
377
378void
380{
381 assert(retryPkt);
383 DPRINTF(MemTest, "Proceeding after successful retry\n");
384
385 retryPkt = nullptr;
386 // kick things into action again
389 }
390}
391
392} // namespace gem5
#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 clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Definition memtest.cc:64
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition memtest.cc:57
The MemTest class tests a cache coherent memory system by generating false sharing and verifying the ...
Definition memtest.hh:72
EventFunctionWrapper tickEvent
Definition memtest.hh:87
MemTest(const Params &p)
Definition memtest.cc:83
void noResponse()
Definition memtest.cc:373
const bool suppressFuncErrors
Definition memtest.hh:180
std::unordered_set< Addr > outstandingAddrs
Definition memtest.hh:142
const uint64_t maxLoads
Definition memtest.hh:176
void tick()
Definition memtest.cc:236
const Addr baseAddr1
Definition memtest.hh:165
gem5::MemTest::MemTestStats stats
const Cycles interval
Definition memtest.hh:130
std::unordered_map< Addr, uint8_t > atomicPendingData
Definition memtest.hh:143
const Cycles progressCheck
Definition memtest.hh:170
void recvRetry()
Definition memtest.cc:379
Random::RandomPtr rng
Definition memtest.hh:203
const Addr baseAddr2
Definition memtest.hh:166
const unsigned percentFunctional
Definition memtest.hh:133
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition memtest.cc:126
Addr blockAlign(Addr addr) const
Get the block aligned address.
Definition memtest.hh:160
const unsigned percentAtomic
Definition memtest.hh:135
uint64_t numWrites
Definition memtest.hh:174
const unsigned size
Definition memtest.hh:128
const unsigned percentReads
Definition memtest.hh:132
void completeRequest(PacketPtr pkt, bool functional=false)
Complete a request by checking the response.
Definition memtest.cc:135
const Addr uncacheAddr
Definition memtest.hh:167
const unsigned progressInterval
Definition memtest.hh:169
std::unordered_map< Addr, uint8_t > referenceData
Definition memtest.hh:146
MemTestParams Params
Definition memtest.hh:76
unsigned int id
Definition memtest.hh:140
PacketPtr retryPkt
Definition memtest.hh:122
uint64_t numReads
Definition memtest.hh:173
Tick nextProgressMessage
Definition memtest.hh:171
const unsigned sizeBlocks
Definition memtest.hh:152
EventFunctionWrapper noRequestEvent
Definition memtest.hh:91
uint64_t numAtomics
Definition memtest.hh:175
const bool atomic
Definition memtest.hh:178
EventFunctionWrapper noResponseEvent
Definition memtest.hh:95
RequestorID requestorId
Request id for all generated traffic.
Definition memtest.hh:138
bool sendPkt(PacketPtr pkt)
Definition memtest.cc:70
bool waitResponse
Definition memtest.hh:126
const unsigned percentUncacheable
Definition memtest.hh:134
CpuPort port
Definition memtest.hh:120
void noRequest()
Definition memtest.cc:367
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
bool isRead() const
Definition packet.hh:593
bool isError() const
Definition packet.hh:622
bool isAtomicOp() const
Definition packet.hh:846
bool isWrite() const
Definition packet.hh:594
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
const T * getConstPtr() const
Definition packet.hh:1234
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition packet.hh:1213
bool suppressFuncError() const
Definition packet.hh:758
void setSuppressFuncError()
Definition packet.hh:757
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
Definition port.hh:552
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
@ ATOMIC_RETURN_OP
The request is an atomic that returns data.
Definition request.hh:175
@ UNCACHEABLE
The request is to an uncacheable address.
Definition request.hh:125
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::unique_ptr< AtomicOpFunctor > AtomicOpFunctorPtr
Definition amo.hh:269
void deschedule(Event &event)
Definition eventq.hh:1021
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
void reschedule(Event &event, Tick when, bool always=false)
Definition eventq.hh:1030
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
#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.
uint8_t flags
Definition helpers.cc:87
Bitfield< 23, 20 > atomic
Bitfield< 7 > b
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 29 > c
Definition misc_types.hh:53
Bitfield< 8 > a
Definition misc_types.hh:66
Bitfield< 0 > p
Bitfield< 51, 12 > base
Definition pagetable.hh:141
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)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition sim_events.cc:88
static unsigned int TESTER_ALLOCATOR
Definition memtest.cc:54
void ccprintf(cp::Print &print)
Definition cprintf.hh:130
Declaration of Statistics objects.
statistics::Scalar numWrites
Definition memtest.hh:186
statistics::Scalar numReads
Definition memtest.hh:185
statistics::Scalar numAtomics
Definition memtest.hh:187
MemTestStats(statistics::Group *parent)
Definition memtest.cc:223
const std::string & name()
Definition trace.cc:48

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