gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
memtest.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, 2019 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  * Authors: Erik Hallnor
41  * Steve Reinhardt
42  * Andreas Hansson
43  */
44 
46 
47 #include "base/random.hh"
48 #include "base/statistics.hh"
49 #include "base/trace.hh"
50 #include "debug/MemTest.hh"
51 #include "sim/sim_exit.hh"
52 #include "sim/stats.hh"
53 #include "sim/system.hh"
54 
55 using namespace std;
56 
57 unsigned int TESTER_ALLOCATOR = 0;
58 
59 bool
61 {
62  memtest.completeRequest(pkt);
63  return true;
64 }
65 
66 void
68 {
69  memtest.recvRetry();
70 }
71 
72 bool
74  if (atomic) {
75  port.sendAtomic(pkt);
76  completeRequest(pkt);
77  } else {
78  if (!port.sendTimingReq(pkt)) {
79  retryPkt = pkt;
80  return false;
81  }
82  }
83  return true;
84 }
85 
87  : ClockedObject(p),
88  tickEvent([this]{ tick(); }, name()),
89  noRequestEvent([this]{ noRequest(); }, name()),
90  noResponseEvent([this]{ noResponse(); }, name()),
91  port("port", *this),
92  retryPkt(nullptr),
93  size(p->size),
94  interval(p->interval),
95  percentReads(p->percent_reads),
96  percentFunctional(p->percent_functional),
97  percentUncacheable(p->percent_uncacheable),
98  masterId(p->system->getMasterId(this)),
99  blockSize(p->system->cacheLineSize()),
101  progressInterval(p->progress_interval),
102  progressCheck(p->progress_check),
103  nextProgressMessage(p->progress_interval),
104  maxLoads(p->max_loads),
105  atomic(p->system->isAtomicMode()),
106  suppressFuncWarnings(p->suppress_func_warnings)
107 {
108  id = TESTER_ALLOCATOR++;
109  fatal_if(id >= blockSize, "Too many testers, only %d allowed\n",
110  blockSize - 1);
111 
112  baseAddr1 = 0x100000;
113  baseAddr2 = 0x400000;
114  uncacheAddr = 0x800000;
115 
116  // set up counters
117  numReads = 0;
118  numWrites = 0;
119 
120  // kick things into action
123 }
124 
125 Port &
126 MemTest::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 
134 void
135 MemTest::completeRequest(PacketPtr pkt, bool functional)
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() ? "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 || !suppressFuncWarnings) {
154  warn("%s access failed at %#x\n",
155  pkt->isWrite() ? "Write" : "Read", req->getPaddr());
156  }
157  } else {
158  if (pkt->isRead()) {
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  }
166 
167  numReads++;
168  numReadsStat++;
169 
170  if (numReads == (uint64_t)nextProgressMessage) {
171  ccprintf(cerr, "%s: completed %d read, %d write accesses @%d\n",
172  name(), numReads, numWrites, curTick());
174  }
175 
176  if (maxLoads != 0 && numReads >= maxLoads)
177  exitSimLoop("maximum number of loads reached");
178  } else {
179  assert(pkt->isWrite());
180 
181  // update the reference data
182  referenceData[req->getPaddr()] = pkt_data[0];
183  numWrites++;
184  numWritesStat++;
185  }
186  }
187 
188  // the packet will delete the data
189  delete pkt;
190 
191  // finally shift the response timeout forward if we are still
192  // expecting responses; deschedule it otherwise
193  if (outstandingAddrs.size() != 0)
195  else if (noResponseEvent.scheduled())
197 }
198 
199 void
201 {
203 
204  using namespace Stats;
205 
207  .name(name() + ".num_reads")
208  .desc("number of read accesses completed")
209  ;
210 
212  .name(name() + ".num_writes")
213  .desc("number of write accesses completed")
214  ;
215 }
216 
217 void
219 {
220  // we should never tick if we are waiting for a retry
221  assert(!retryPkt);
222 
223  // create a new request
224  unsigned cmd = random_mt.random(0, 100);
225  uint8_t data = random_mt.random<uint8_t>();
226  bool uncacheable = random_mt.random(0, 100) < percentUncacheable;
227  unsigned base = random_mt.random(0, 1);
228  Request::Flags flags;
229  Addr paddr;
230 
231  // generate a unique address
232  do {
233  unsigned offset = random_mt.random<unsigned>(0, size - 1);
234 
235  // use the tester id as offset within the block for false sharing
236  offset = blockAlign(offset);
237  offset += id;
238 
239  if (uncacheable) {
240  flags.set(Request::UNCACHEABLE);
241  paddr = uncacheAddr + offset;
242  } else {
243  paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
244  }
245  } while (outstandingAddrs.find(paddr) != outstandingAddrs.end());
246 
247  bool do_functional = (random_mt.random(0, 100) < percentFunctional) &&
248  !uncacheable;
249  RequestPtr req = std::make_shared<Request>(paddr, 1, flags, masterId);
250  req->setContext(id);
251 
252  outstandingAddrs.insert(paddr);
253 
254  // sanity check
255  panic_if(outstandingAddrs.size() > 100,
256  "Tester %s has more than 100 outstanding requests\n", name());
257 
258  PacketPtr pkt = nullptr;
259  uint8_t *pkt_data = new uint8_t[1];
260 
261  if (cmd < percentReads) {
262  // start by ensuring there is a reference value if we have not
263  // seen this address before
264  uint8_t M5_VAR_USED ref_data = 0;
265  auto ref = referenceData.find(req->getPaddr());
266  if (ref == referenceData.end()) {
267  referenceData[req->getPaddr()] = 0;
268  } else {
269  ref_data = ref->second;
270  }
271 
273  "Initiating %sread at addr %x (blk %x) expecting %x\n",
274  do_functional ? "functional " : "", req->getPaddr(),
275  blockAlign(req->getPaddr()), ref_data);
276 
277  pkt = new Packet(req, MemCmd::ReadReq);
278  pkt->dataDynamic(pkt_data);
279  } else {
280  DPRINTF(MemTest, "Initiating %swrite at addr %x (blk %x) value %x\n",
281  do_functional ? "functional " : "", req->getPaddr(),
282  blockAlign(req->getPaddr()), data);
283 
284  pkt = new Packet(req, MemCmd::WriteReq);
285  pkt->dataDynamic(pkt_data);
286  pkt_data[0] = data;
287  }
288 
289  // there is no point in ticking if we are waiting for a retry
290  bool keep_ticking = true;
291  if (do_functional) {
292  pkt->setSuppressFuncError();
293  port.sendFunctional(pkt);
294  completeRequest(pkt, true);
295  } else {
296  keep_ticking = sendPkt(pkt);
297  }
298 
299  if (keep_ticking) {
300  // schedule the next tick
302 
303  // finally shift the timeout for sending of requests forwards
304  // as we have successfully sent a packet
306  } else {
307  DPRINTF(MemTest, "Waiting for retry\n");
308  }
309 
310  // Schedule noResponseEvent now if we are expecting a response
311  if (!noResponseEvent.scheduled() && (outstandingAddrs.size() != 0))
313 }
314 
315 void
317 {
318  panic("%s did not send a request for %d cycles", name(), progressCheck);
319 }
320 
321 void
323 {
324  panic("%s did not see a response for %d cycles", name(), progressCheck);
325 }
326 
327 void
329 {
330  assert(retryPkt);
331  if (port.sendTimingReq(retryPkt)) {
332  DPRINTF(MemTest, "Proceeding after successful retry\n");
333 
334  retryPkt = nullptr;
335  // kick things into action again
338  }
339 }
340 
341 MemTest *
342 MemTestParams::create()
343 {
344  return new MemTest(this);
345 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
void ccprintf(cp::Print &print)
Definition: cprintf.hh:131
#define DPRINTF(x,...)
Definition: trace.hh:229
const Cycles interval
Definition: memtest.hh:127
void recvRetry()
Definition: memtest.cc:328
bool sendPkt(PacketPtr pkt)
Definition: memtest.cc:73
The request is to an uncacheable address.
Definition: request.hh:115
Ports are used to interface objects to each other.
Definition: port.hh:60
EventFunctionWrapper noResponseEvent
Definition: memtest.hh:96
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
void noResponse()
Definition: memtest.cc:322
const unsigned size
Definition: memtest.hh:125
EventFunctionWrapper tickEvent
Definition: memtest.hh:88
Bitfield< 23, 20 > atomic
const unsigned percentFunctional
Definition: memtest.hh:130
void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Definition: memtest.cc:67
const unsigned progressInterval
Definition: memtest.hh:162
std::shared_ptr< Request > RequestPtr
Definition: request.hh:83
Addr blockAlign(Addr addr) const
Get the block aligned address.
Definition: memtest.hh:153
const Addr blockAddrMask
Definition: memtest.hh:145
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:66
std::unordered_map< Addr, uint8_t > referenceData
Definition: memtest.hh:141
Bitfield< 23, 0 > offset
Definition: types.hh:154
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:586
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.hh:445
void regStats() override
Callback to set stat parameters.
Definition: memtest.cc:200
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: memtest.cc:126
bool isWrite() const
Definition: packet.hh:529
Declaration of Statistics objects.
bool isRead() const
Definition: packet.hh:528
EventFunctionWrapper noRequestEvent
Definition: memtest.hh:92
void deschedule(Event &event)
Definition: eventq.hh:750
const bool atomic
Definition: memtest.hh:170
std::enable_if< std::is_integral< T >::value, T >::type random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:83
RequestPtr req
A pointer to the original request.
Definition: packet.hh:327
CpuPort port
Definition: memtest.hh:121
MasterID masterId
Request id for all generated traffic.
Definition: memtest.hh:134
Tick curTick()
The current simulated tick.
Definition: core.hh:47
const unsigned blockSize
Definition: memtest.hh:143
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:385
bool isError() const
Definition: packet.hh:555
void tick()
Definition: memtest.cc:218
PacketPtr retryPkt
Definition: memtest.hh:123
unsigned int id
Definition: memtest.hh:136
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Bitfield< 51, 12 > base
Definition: pagetable.hh:142
The MemTest class tests a cache coherent memory system by generating false sharing and verifying the ...
Definition: memtest.hh:71
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:203
MemTest(const Params *p)
Definition: memtest.cc:86
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition: memtest.cc:60
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
virtual const std::string name() const
Definition: sim_object.hh:120
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
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 noRequest()
Definition: memtest.cc:316
Tick nextProgressMessage
Definition: memtest.hh:164
Stats::Scalar numReadsStat
Definition: memtest.hh:174
Addr baseAddr2
Definition: memtest.hh:159
unsigned int TESTER_ALLOCATOR
Definition: memtest.cc:57
uint64_t numReads
Definition: memtest.hh:166
std::set< Addr > outstandingAddrs
Definition: memtest.hh:138
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:279
Addr uncacheAddr
Definition: memtest.hh:160
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:756
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:90
const unsigned percentUncacheable
Definition: memtest.hh:131
const bool suppressFuncWarnings
Definition: memtest.hh:172
const Cycles progressCheck
Definition: memtest.hh:163
Random random_mt
Definition: random.cc:100
const unsigned percentReads
Definition: memtest.hh:129
void schedule(Event &event, Tick when)
Definition: eventq.hh:744
const T * getConstPtr() const
Definition: packet.hh:1099
uint64_t numWrites
Definition: memtest.hh:167
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:439
Stats::Scalar numWritesStat
Definition: memtest.hh:175
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:312
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
void completeRequest(PacketPtr pkt, bool functional=false)
Complete a request by checking the response.
Definition: memtest.cc:135
#define warn(...)
Definition: logging.hh:212
const uint64_t maxLoads
Definition: memtest.hh:168
static const int NumArgumentRegs M5_VAR_USED
Definition: process.cc:84
Addr baseAddr1
Definition: memtest.hh:158
Bitfield< 0 > p
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
MemTestParams Params
Definition: memtest.hh:76
const char data[]
void set(Type flags)
Definition: flags.hh:70
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:104

Generated on Fri Feb 28 2020 16:27:00 for gem5 by doxygen 1.8.13