gem5  v22.1.0.0
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 
52 namespace gem5
53 {
54 
55 static unsigned int TESTER_ALLOCATOR = 0;
56 
57 bool
59 {
61  return true;
62 }
63 
64 void
66 {
67  memtest.recvRetry();
68 }
69 
70 bool
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 
85  : ClockedObject(p),
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  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 
119  // kick things into action
120  schedule(tickEvent, curTick());
121  schedule(noRequestEvent, clockEdge(progressCheck));
122 }
123 
124 Port &
125 MemTest::getPort(const std::string &if_name, PortID idx)
126 {
127  if (if_name == "port")
128  return port;
129  else
130  return ClockedObject::getPort(if_name, idx);
131 }
132 
133 void
134 MemTest::completeRequest(PacketPtr pkt, bool functional)
135 {
136  const RequestPtr &req = pkt->req;
137  assert(req->getSize() == 1);
138 
139  // this address is no longer outstanding
140  auto remove_addr = outstandingAddrs.find(req->getPaddr());
141  assert(remove_addr != outstandingAddrs.end());
142  outstandingAddrs.erase(remove_addr);
143 
144  DPRINTF(MemTest, "Completing %s at address %x (blk %x) %s\n",
145  pkt->isWrite() ? "write" : "read",
146  req->getPaddr(), blockAlign(req->getPaddr()),
147  pkt->isError() ? "error" : "success");
148 
149  const uint8_t *pkt_data = pkt->getConstPtr<uint8_t>();
150 
151  if (pkt->isError()) {
152  if (!functional || !suppressFuncErrors)
153  panic( "%s access failed at %#x\n",
154  pkt->isWrite() ? "Write" : "Read", req->getPaddr());
155  } else {
156  if (pkt->isRead()) {
157  uint8_t ref_data = referenceData[req->getPaddr()];
158  if (pkt_data[0] != ref_data) {
159  panic("%s: read of %x (blk %x) @ cycle %d "
160  "returns %x, expected %x\n", name(),
161  req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
162  pkt_data[0], ref_data);
163  }
164 
165  numReads++;
166  stats.numReads++;
167 
168  if (numReads == (uint64_t)nextProgressMessage) {
169  ccprintf(std::cerr,
170  "%s: completed %d read, %d write accesses @%d\n",
171  name(), numReads, numWrites, curTick());
173  }
174 
175  if (maxLoads != 0 && numReads >= maxLoads)
176  exitSimLoop("maximum number of loads reached");
177  } else {
178  assert(pkt->isWrite());
179 
180  // update the reference data
181  referenceData[req->getPaddr()] = pkt_data[0];
182  numWrites++;
183  stats.numWrites++;
184  }
185  }
186 
187  // the packet will delete the data
188  delete pkt;
189 
190  // finally shift the response timeout forward if we are still
191  // expecting responses; deschedule it otherwise
192  if (outstandingAddrs.size() != 0)
194  else if (noResponseEvent.scheduled())
196 
197  // schedule the next tick
198  if (waitResponse) {
199  waitResponse = false;
201  }
202 }
204  : statistics::Group(parent),
205  ADD_STAT(numReads, statistics::units::Count::get(),
206  "number of read accesses completed"),
207  ADD_STAT(numWrites, statistics::units::Count::get(),
208  "number of write accesses completed")
209 {
210 
211 }
212 
213 void
215 {
216  // we should never tick if we are waiting for a retry or response
217  assert(!retryPkt);
218  assert(!waitResponse);
219 
220  // create a new request
221  unsigned cmd = random_mt.random(0, 100);
222  uint8_t data = random_mt.random<uint8_t>();
223  bool uncacheable = random_mt.random(0, 100) < percentUncacheable;
224  unsigned base = random_mt.random(0, 1);
226  Addr paddr;
227 
228  // halt until we clear outstanding requests, otherwise it won't be able to
229  // find a new unique address
230  if (outstandingAddrs.size() >= sizeBlocks) {
231  waitResponse = true;
232  return;
233  }
234 
235  // generate a unique address
236  do {
237  unsigned offset = random_mt.random<unsigned>(0, size - 1);
238 
239  // use the tester id as offset within the block for false sharing
241  offset += id;
242 
243  if (uncacheable) {
245  paddr = uncacheAddr + offset;
246  } else {
247  paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
248  }
249  } while (outstandingAddrs.find(paddr) != outstandingAddrs.end());
250 
251  bool do_functional = (random_mt.random(0, 100) < percentFunctional) &&
252  !uncacheable;
253  RequestPtr req = std::make_shared<Request>(paddr, 1, flags, requestorId);
254  req->setContext(id);
255 
256  outstandingAddrs.insert(paddr);
257 
258  // sanity check
259  panic_if(outstandingAddrs.size() > 100,
260  "Tester %s has more than 100 outstanding requests\n", name());
261 
262  PacketPtr pkt = nullptr;
263  uint8_t *pkt_data = new uint8_t[1];
264 
265  if (cmd < percentReads) {
266  // start by ensuring there is a reference value if we have not
267  // seen this address before
268  [[maybe_unused]] uint8_t ref_data = 0;
269  auto ref = referenceData.find(req->getPaddr());
270  if (ref == referenceData.end()) {
271  referenceData[req->getPaddr()] = 0;
272  } else {
273  ref_data = ref->second;
274  }
275 
277  "Initiating %sread at addr %x (blk %x) expecting %x\n",
278  do_functional ? "functional " : "", req->getPaddr(),
279  blockAlign(req->getPaddr()), ref_data);
280 
281  pkt = new Packet(req, MemCmd::ReadReq);
282  pkt->dataDynamic(pkt_data);
283  } else {
284  DPRINTF(MemTest, "Initiating %swrite at addr %x (blk %x) value %x\n",
285  do_functional ? "functional " : "", req->getPaddr(),
286  blockAlign(req->getPaddr()), data);
287 
288  pkt = new Packet(req, MemCmd::WriteReq);
289  pkt->dataDynamic(pkt_data);
290  pkt_data[0] = data;
291  }
292 
293  // there is no point in ticking if we are waiting for a retry
294  bool keep_ticking = true;
295  if (do_functional) {
296  pkt->setSuppressFuncError();
297  port.sendFunctional(pkt);
298  completeRequest(pkt, true);
299  } else {
300  keep_ticking = sendPkt(pkt);
301  }
302 
303  if (keep_ticking) {
304  // schedule the next tick
306 
307  // finally shift the timeout for sending of requests forwards
308  // as we have successfully sent a packet
310  } else {
311  DPRINTF(MemTest, "Waiting for retry\n");
312  }
313 
314  // Schedule noResponseEvent now if we are expecting a response
315  if (!noResponseEvent.scheduled() && (outstandingAddrs.size() != 0))
317 }
318 
319 void
321 {
322  panic("%s did not send a request for %d cycles", name(), progressCheck);
323 }
324 
325 void
327 {
328  panic("%s did not see a response for %d cycles", name(), progressCheck);
329 }
330 
331 void
333 {
334  assert(retryPkt);
335  if (port.sendTimingReq(retryPkt)) {
336  DPRINTF(MemTest, "Proceeding after successful retry\n");
337 
338  retryPkt = nullptr;
339  // kick things into action again
342  }
343 }
344 
345 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
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:326
const bool suppressFuncErrors
Definition: memtest.hh:176
std::unordered_set< Addr > outstandingAddrs
Definition: memtest.hh:140
const uint64_t maxLoads
Definition: memtest.hh:172
void tick()
Definition: memtest.cc:214
const Addr baseAddr1
Definition: memtest.hh:162
gem5::MemTest::MemTestStats stats
const Cycles interval
Definition: memtest.hh:129
const Cycles progressCheck
Definition: memtest.hh:167
void recvRetry()
Definition: memtest.cc:332
const Addr baseAddr2
Definition: memtest.hh:163
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:125
Addr blockAlign(Addr addr) const
Get the block aligned address.
Definition: memtest.hh:157
uint64_t numWrites
Definition: memtest.hh:171
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:134
const Addr uncacheAddr
Definition: memtest.hh:164
const unsigned progressInterval
Definition: memtest.hh:166
std::unordered_map< Addr, uint8_t > referenceData
Definition: memtest.hh:143
MemTestParams Params
Definition: memtest.hh:75
unsigned int id
Definition: memtest.hh:138
PacketPtr retryPkt
Definition: memtest.hh:121
uint64_t numReads
Definition: memtest.hh:170
Tick nextProgressMessage
Definition: memtest.hh:168
const unsigned sizeBlocks
Definition: memtest.hh:149
EventFunctionWrapper noRequestEvent
Definition: memtest.hh:90
const bool atomic
Definition: memtest.hh:174
EventFunctionWrapper noResponseEvent
Definition: memtest.hh:94
RequestorID requestorId
Request id for all generated traffic.
Definition: memtest.hh:136
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:320
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:294
bool isRead() const
Definition: packet.hh:592
bool isError() const
Definition: packet.hh:621
bool isWrite() const
Definition: packet.hh:593
RequestPtr req
A pointer to the original request.
Definition: packet.hh:376
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1200
const T * getConstPtr() const
Definition: packet.hh:1221
void setSuppressFuncError()
Definition: packet.hh:755
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:464
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:495
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:485
@ UNCACHEABLE
The request is to an uncacheable address.
Definition: request.hh:125
Statistics container.
Definition: group.hh:94
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
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:1028
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1037
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Definition: sim_object.cc:126
uint8_t flags
Definition: helpers.cc:66
Bitfield< 23, 20 > atomic
Definition: misc_types.hh:100
Bitfield< 23, 0 > offset
Definition: types.hh:144
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:109
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
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:182
statistics::Scalar numReads
Definition: memtest.hh:181
MemTestStats(statistics::Group *parent)
Definition: memtest.cc:203
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:32 for gem5 by doxygen 1.9.1