gem5 v24.0.0.0
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/random.hh"
45#include "base/statistics.hh"
46#include "base/trace.hh"
47#include "debug/MemTest.hh"
48#include "sim/sim_exit.hh"
49#include "sim/stats.hh"
50#include "sim/system.hh"
51
52namespace gem5
53{
54
55static unsigned int TESTER_ALLOCATOR = 0;
56
57bool
63
64void
66{
67 memtest.recvRetry();
68}
69
70bool
72 if (atomic) {
73 port.sendAtomic(pkt);
74 completeRequest(pkt);
75 } else {
76 if (!port.sendTimingReq(pkt)) {
77 retryPkt = pkt;
78 return false;
79 }
80 }
81 return true;
82}
83
86 tickEvent([this]{ tick(); }, name()),
87 noRequestEvent([this]{ noRequest(); }, name()),
88 noResponseEvent([this]{ noResponse(); }, name()),
89 port("port", *this),
90 retryPkt(nullptr),
91 waitResponse(false),
92 size(p.size),
93 interval(p.interval),
94 percentReads(p.percent_reads),
95 percentFunctional(p.percent_functional),
96 percentUncacheable(p.percent_uncacheable),
97 percentAtomic(p.percent_atomic),
98 requestorId(p.system->getRequestorId(this)),
99 blockSize(p.system->cacheLineSize()),
100 blockAddrMask(blockSize - 1),
101 sizeBlocks(size / blockSize),
102 baseAddr1(p.base_addr_1),
103 baseAddr2(p.base_addr_2),
104 uncacheAddr(p.uncacheable_base_addr),
105 progressInterval(p.progress_interval),
106 progressCheck(p.progress_check),
107 nextProgressMessage(p.progress_interval),
108 maxLoads(p.max_loads),
109 atomic(p.system->isAtomicMode()),
110 suppressFuncErrors(p.suppress_func_errors), stats(this)
111{
112 id = TESTER_ALLOCATOR++;
113 fatal_if(id >= blockSize, "Too many testers, only %d allowed\n",
114 blockSize - 1);
115
116 // set up counters
117 numReads = 0;
118 numWrites = 0;
119 numAtomics = 0;
120
121 // kick things into action
122 schedule(tickEvent, curTick());
123 schedule(noRequestEvent, clockEdge(progressCheck));
124}
125
126Port &
127MemTest::getPort(const std::string &if_name, PortID idx)
128{
129 if (if_name == "port")
130 return port;
131 else
132 return ClockedObject::getPort(if_name, idx);
133}
134
135void
137{
138 const RequestPtr &req = pkt->req;
139 assert(req->getSize() == 1);
140
141 // this address is no longer outstanding
142 auto remove_addr = outstandingAddrs.find(req->getPaddr());
143 assert(remove_addr != outstandingAddrs.end());
144 outstandingAddrs.erase(remove_addr);
145
146 DPRINTF(MemTest, "Completing %s at address %x (blk %x) %s\n",
147 pkt->isWrite() ? pkt->isAtomicOp() ? "atomic" : "write" : "read",
148 req->getPaddr(), blockAlign(req->getPaddr()),
149 pkt->isError() ? "error" : "success");
150
151 const uint8_t *pkt_data = pkt->getConstPtr<uint8_t>();
152
153 if (pkt->isError()) {
154 if (!functional || !pkt->suppressFuncError() || !suppressFuncErrors)
155 panic( "%s access failed at %#x\n",
156 pkt->isWrite() ? "Write" : "Read", req->getPaddr());
157 } else {
158 if (pkt->isAtomicOp()) {
159 uint8_t ref_data = referenceData[req->getPaddr()];
160 if (pkt_data[0] != ref_data) {
161 panic("%s: read of %x (blk %x) @ cycle %d "
162 "returns %x, expected %x\n", name(),
163 req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
164 pkt_data[0], ref_data);
165 }
167 "Completing atomic at address %x (blk %x) value %x\n",
168 req->getPaddr(), blockAlign(req->getPaddr()),
169 pkt_data[0]);
170
171 referenceData[req->getPaddr()] =
172 atomicPendingData[req->getPaddr()];
173
174 numAtomics++;
176 } else if (pkt->isRead()) {
177 uint8_t ref_data = referenceData[req->getPaddr()];
178 if (pkt_data[0] != ref_data) {
179 panic("%s: read of %x (blk %x) @ cycle %d "
180 "returns %x, expected %x\n", name(),
181 req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
182 pkt_data[0], ref_data);
183 }
184
185 numReads++;
186 stats.numReads++;
187
188 if (numReads == (uint64_t)nextProgressMessage) {
189 ccprintf(std::cerr,
190 "%s: completed %d read, %d write, "
191 "%d atomic accesses @%d\n",
194 }
195
196 if (maxLoads != 0 && numReads >= maxLoads)
197 exitSimLoop("maximum number of loads reached");
198 } else {
199 assert(pkt->isWrite());
200
201 // update the reference data
202 referenceData[req->getPaddr()] = pkt_data[0];
203 numWrites++;
205 }
206 }
207
208 // the packet will delete the data
209 delete pkt;
210
211 // finally shift the response timeout forward if we are still
212 // expecting responses; deschedule it otherwise
213 if (outstandingAddrs.size() != 0)
215 else if (noResponseEvent.scheduled())
217
218 // schedule the next tick
219 if (waitResponse) {
220 waitResponse = false;
222 }
223}
225 : statistics::Group(parent),
226 ADD_STAT(numReads, statistics::units::Count::get(),
227 "number of read accesses completed"),
228 ADD_STAT(numWrites, statistics::units::Count::get(),
229 "number of write accesses completed"),
230 ADD_STAT(numAtomics, statistics::units::Count::get(),
231 "number of atomic accesses completed")
232{
233
234}
235
236void
238{
239 // we should never tick if we are waiting for a retry or response
240 assert(!retryPkt);
241 assert(!waitResponse);
242
243 // create a new request
244 unsigned cmd = random_mt.random(0, 100);
245 uint8_t data = random_mt.random<uint8_t>();
246 bool uncacheable = random_mt.random(0, 100) < percentUncacheable;
247 bool do_atomic = (random_mt.random(0, 100) < percentAtomic) &&
248 !uncacheable;
249 unsigned base = random_mt.random(0, 1);
251 Addr paddr;
252
253 // halt until we clear outstanding requests, otherwise it won't be able to
254 // find a new unique address
255 if (outstandingAddrs.size() >= sizeBlocks) {
256 waitResponse = true;
257 return;
258 }
259
260 // generate a unique address
261 do {
262 unsigned offset = random_mt.random<unsigned>(0, size - 1);
263
264 // use the tester id as offset within the block for false sharing
266 offset += id;
267
268 if (uncacheable) {
270 paddr = uncacheAddr + offset;
271 } else {
272 paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
273 }
274 } while (outstandingAddrs.find(paddr) != outstandingAddrs.end());
275
276 bool do_functional = (random_mt.random(0, 100) < percentFunctional) &&
277 !uncacheable;
278 RequestPtr req = std::make_shared<Request>(paddr, 1, flags, requestorId);
279 req->setContext(id);
280
281 outstandingAddrs.insert(paddr);
282
283 // sanity check
284 panic_if(outstandingAddrs.size() > 100,
285 "Tester %s has more than 100 outstanding requests\n", name());
286
287 PacketPtr pkt = nullptr;
288 uint8_t *pkt_data = new uint8_t[1];
289
290 if (cmd < percentReads) {
291 // start by ensuring there is a reference value if we have not
292 // seen this address before
293 [[maybe_unused]] uint8_t ref_data = 0;
294 auto ref = referenceData.find(req->getPaddr());
295 if (ref == referenceData.end()) {
296 referenceData[req->getPaddr()] = 0;
297 } else {
298 ref_data = ref->second;
299 }
300
302 "Initiating %sread at addr %x (blk %x) expecting %x\n",
303 do_functional ? "functional " : "", req->getPaddr(),
304 blockAlign(req->getPaddr()), ref_data);
305
306 pkt = new Packet(req, MemCmd::ReadReq);
307 pkt->dataDynamic(pkt_data);
308 } else {
309 if (do_atomic) {
311 "Initiating atomic at addr %x (blk %x) value %x\n",
312 req->getPaddr(), blockAlign(req->getPaddr()), data);
313
316 data, data,
317 [](uint8_t* b, uint8_t a, uint8_t c){
318 *b = c;
319 });
320 assert(_amo_op);
321 AtomicOpFunctorPtr amo_op = AtomicOpFunctorPtr(_amo_op);
322 req->setAtomicOpFunctor(std::move(amo_op));
323 req->setFlags(Request::ATOMIC_RETURN_OP);
324
325 pkt = new Packet(req, MemCmd::WriteReq);
326 pkt->dataDynamic(pkt_data);
327 pkt_data[0] = data;
328 atomicPendingData[req->getPaddr()] = data;
329 } else {
331 "Initiating %swrite at addr %x (blk %x) value %x\n",
332 do_functional ? "functional " : "", req->getPaddr(),
333 blockAlign(req->getPaddr()), data);
334
335 pkt = new Packet(req, MemCmd::WriteReq);
336 pkt->dataDynamic(pkt_data);
337 pkt_data[0] = data;
338 }
339 }
340
341 // there is no point in ticking if we are waiting for a retry
342 bool keep_ticking = true;
343 if (do_functional) {
345 port.sendFunctional(pkt);
346 completeRequest(pkt, true);
347 } else {
348 keep_ticking = sendPkt(pkt);
349 }
350
351 if (keep_ticking) {
352 // schedule the next tick
354
355 // finally shift the timeout for sending of requests forwards
356 // as we have successfully sent a packet
358 } else {
359 DPRINTF(MemTest, "Waiting for retry\n");
360 }
361
362 // Schedule noResponseEvent now if we are expecting a response
363 if (!noResponseEvent.scheduled() && (outstandingAddrs.size() != 0))
365}
366
367void
369{
370 panic("%s did not send a request for %d cycles", name(), progressCheck);
371}
372
373void
375{
376 panic("%s did not see a response for %d cycles", name(), progressCheck);
377}
378
379void
381{
382 assert(retryPkt);
384 DPRINTF(MemTest, "Proceeding after successful retry\n");
385
386 retryPkt = nullptr;
387 // kick things into action again
390 }
391}
392
393} // namespace gem5
#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 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:65
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition memtest.cc:58
The MemTest class tests a cache coherent memory system by generating false sharing and verifying the ...
Definition memtest.hh:71
EventFunctionWrapper tickEvent
Definition memtest.hh:86
MemTest(const Params &p)
Definition memtest.cc:84
void noResponse()
Definition memtest.cc:374
const bool suppressFuncErrors
Definition memtest.hh:179
std::unordered_set< Addr > outstandingAddrs
Definition memtest.hh:141
const uint64_t maxLoads
Definition memtest.hh:175
void tick()
Definition memtest.cc:237
const Addr baseAddr1
Definition memtest.hh:164
gem5::MemTest::MemTestStats stats
const Cycles interval
Definition memtest.hh:129
std::unordered_map< Addr, uint8_t > atomicPendingData
Definition memtest.hh:142
const Cycles progressCheck
Definition memtest.hh:169
void recvRetry()
Definition memtest.cc:380
const Addr baseAddr2
Definition memtest.hh:165
const unsigned percentFunctional
Definition memtest.hh:132
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition memtest.cc:127
Addr blockAlign(Addr addr) const
Get the block aligned address.
Definition memtest.hh:159
const unsigned percentAtomic
Definition memtest.hh:134
uint64_t numWrites
Definition memtest.hh:173
const unsigned size
Definition memtest.hh:127
const unsigned percentReads
Definition memtest.hh:131
void completeRequest(PacketPtr pkt, bool functional=false)
Complete a request by checking the response.
Definition memtest.cc:136
const Addr uncacheAddr
Definition memtest.hh:166
const unsigned progressInterval
Definition memtest.hh:168
std::unordered_map< Addr, uint8_t > referenceData
Definition memtest.hh:145
MemTestParams Params
Definition memtest.hh:75
unsigned int id
Definition memtest.hh:139
PacketPtr retryPkt
Definition memtest.hh:121
uint64_t numReads
Definition memtest.hh:172
Tick nextProgressMessage
Definition memtest.hh:170
const unsigned sizeBlocks
Definition memtest.hh:151
EventFunctionWrapper noRequestEvent
Definition memtest.hh:90
uint64_t numAtomics
Definition memtest.hh:174
const bool atomic
Definition memtest.hh:177
EventFunctionWrapper noResponseEvent
Definition memtest.hh:94
RequestorID requestorId
Request id for all generated traffic.
Definition memtest.hh:137
bool sendPkt(PacketPtr pkt)
Definition memtest.cc:71
bool waitResponse
Definition memtest.hh:125
const unsigned percentUncacheable
Definition memtest.hh:133
CpuPort port
Definition memtest.hh:119
void noRequest()
Definition memtest.cc:368
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
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
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 - 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
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:55
void ccprintf(cp::Print &print)
Definition cprintf.hh:130
Declaration of Statistics objects.
statistics::Scalar numWrites
Definition memtest.hh:185
statistics::Scalar numReads
Definition memtest.hh:184
statistics::Scalar numAtomics
Definition memtest.hh:186
MemTestStats(statistics::Group *parent)
Definition memtest.cc:224
const std::string & name()
Definition trace.cc:48

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