gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
memtest.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 "mem/mem_object.hh"
52 #include "sim/sim_exit.hh"
53 #include "sim/stats.hh"
54 #include "sim/system.hh"
55 
56 using namespace std;
57 
58 unsigned int TESTER_ALLOCATOR = 0;
59 
60 bool
62 {
63  memtest.completeRequest(pkt);
64  return true;
65 }
66 
67 void
69 {
70  memtest.recvRetry();
71 }
72 
73 bool
75  if (atomic) {
76  port.sendAtomic(pkt);
77  completeRequest(pkt);
78  } else {
79  if (!port.sendTimingReq(pkt)) {
80  retryPkt = pkt;
81  return false;
82  }
83  }
84  return true;
85 }
86 
88  : MemObject(p),
89  tickEvent(this),
90  noRequestEvent(this),
91  noResponseEvent(this),
92  port("port", *this),
93  retryPkt(nullptr),
94  size(p->size),
95  interval(p->interval),
96  percentReads(p->percent_reads),
97  percentFunctional(p->percent_functional),
98  percentUncacheable(p->percent_uncacheable),
99  masterId(p->system->getMasterId(name())),
100  blockSize(p->system->cacheLineSize()),
101  blockAddrMask(blockSize - 1),
102  progressInterval(p->progress_interval),
103  progressCheck(p->progress_check),
104  nextProgressMessage(p->progress_interval),
105  maxLoads(p->max_loads),
106  atomic(p->system->isAtomicMode()),
107  suppressFuncWarnings(p->suppress_func_warnings)
108 {
109  id = TESTER_ALLOCATOR++;
110  fatal_if(id >= blockSize, "Too many testers, only %d allowed\n",
111  blockSize - 1);
112 
113  baseAddr1 = 0x100000;
114  baseAddr2 = 0x400000;
115  uncacheAddr = 0x800000;
116 
117  // set up counters
118  numReads = 0;
119  numWrites = 0;
120 
121  // kick things into action
125 }
126 
128 MemTest::getMasterPort(const std::string &if_name, PortID idx)
129 {
130  if (if_name == "port")
131  return port;
132  else
133  return MemObject::getMasterPort(if_name, idx);
134 }
135 
136 void
137 MemTest::completeRequest(PacketPtr pkt, bool functional)
138 {
139  Request *req = pkt->req;
140  assert(req->getSize() == 1);
141 
142  // this address is no longer outstanding
143  auto remove_addr = outstandingAddrs.find(req->getPaddr());
144  assert(remove_addr != outstandingAddrs.end());
145  outstandingAddrs.erase(remove_addr);
146 
147  DPRINTF(MemTest, "Completing %s at address %x (blk %x) %s\n",
148  pkt->isWrite() ? "write" : "read",
149  req->getPaddr(), blockAlign(req->getPaddr()),
150  pkt->isError() ? "error" : "success");
151 
152  const uint8_t *pkt_data = pkt->getConstPtr<uint8_t>();
153 
154  if (pkt->isError()) {
155  if (!functional || !suppressFuncWarnings) {
156  warn("%s access failed at %#x\n",
157  pkt->isWrite() ? "Write" : "Read", req->getPaddr());
158  }
159  } else {
160  if (pkt->isRead()) {
161  uint8_t ref_data = referenceData[req->getPaddr()];
162  if (pkt_data[0] != ref_data) {
163  panic("%s: read of %x (blk %x) @ cycle %d "
164  "returns %x, expected %x\n", name(),
165  req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
166  pkt_data[0], ref_data);
167  }
168 
169  numReads++;
170  numReadsStat++;
171 
172  if (numReads == (uint64_t)nextProgressMessage) {
173  ccprintf(cerr, "%s: completed %d read, %d write accesses @%d\n",
174  name(), numReads, numWrites, curTick());
176  }
177 
178  if (maxLoads != 0 && numReads >= maxLoads)
179  exitSimLoop("maximum number of loads reached");
180  } else {
181  assert(pkt->isWrite());
182 
183  // update the reference data
184  referenceData[req->getPaddr()] = pkt_data[0];
185  numWrites++;
186  numWritesStat++;
187  }
188  }
189 
190  delete pkt->req;
191 
192  // the packet will delete the data
193  delete pkt;
194 
195  // finally shift the response timeout forward
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>();
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  Request *req = new 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 
311 void
313 {
314  panic("%s did not send a request for %d cycles", name(), progressCheck);
315 }
316 
317 void
319 {
320  panic("%s did not see a response for %d cycles", name(), progressCheck);
321 }
322 
323 void
325 {
326  assert(retryPkt);
327  if (port.sendTimingReq(retryPkt)) {
328  DPRINTF(MemTest, "Proceeding after successful retry\n");
329 
330  retryPkt = nullptr;
331  // kick things into action again
333  }
334 }
335 
336 MemTest *
337 MemTestParams::create()
338 {
339  return new MemTest(this);
340 }
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
#define DPRINTF(x,...)
Definition: trace.hh:212
EventWrapper< MemTest,&MemTest::tick > tickEvent
Definition: memtest.hh:87
const Cycles interval
Definition: memtest.hh:126
void recvRetry()
Definition: memtest.cc:324
bool sendPkt(PacketPtr pkt)
Definition: memtest.cc:74
void noResponse()
Definition: memtest.cc:318
const unsigned size
Definition: memtest.hh:124
const std::string & name()
Definition: trace.cc:49
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
Definition: memtest.cc:128
#define panic(...)
Definition: misc.hh:153
const unsigned percentFunctional
Definition: memtest.hh:129
void recvReqRetry()
Called by the slave port if sendTimingReq was called on this master port (causing recvTimingReq to be...
Definition: memtest.cc:68
const unsigned progressInterval
Definition: memtest.hh:161
MemObject declaration.
bool isWrite() const
Definition: packet.hh:503
panic_if(!root,"Invalid expression\n")
void setContext(ContextID context_id)
Set up Context numbers.
Definition: request.hh:449
std::unordered_map< Addr, uint8_t > referenceData
Definition: memtest.hh:140
Bitfield< 23, 0 > offset
Definition: types.hh:149
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.cc:180
bool uncacheable
Definition: pagetable.hh:118
EventWrapper< MemTest,&MemTest::noResponse > noResponseEvent
Definition: memtest.hh:95
Declaration of Statistics objects.
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
const char data[]
Definition: circlebuf.cc:43
Addr blockAlign(Addr addr) const
Get the block aligned address.
Definition: memtest.hh:152
CpuPort port
Definition: memtest.hh:120
#define warn(...)
Definition: misc.hh:219
MasterID masterId
Request id for all generated traffic.
Definition: memtest.hh:133
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...
system
Definition: isa.cc:226
Tick curTick()
The current simulated tick.
Definition: core.hh:47
const unsigned blockSize
Definition: memtest.hh:142
void tick()
Definition: memtest.cc:218
PacketPtr retryPkt
Definition: memtest.hh:122
unsigned int id
Definition: memtest.hh:135
The request is to an uncacheable address.
Definition: request.hh:114
Bitfield< 51, 12 > base
Definition: pagetable.hh:85
The MemTest class tests a cache coherent memory system by generating false sharing and verifying the ...
Definition: memtest.hh:70
Addr getPaddr() const
Definition: request.hh:519
EventWrapper< MemTest,&MemTest::noRequest > noRequestEvent
Definition: memtest.hh:91
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
MemTest(const Params *p)
Definition: memtest.cc:87
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the slave port.
Definition: memtest.cc:61
bool isRead() const
Definition: packet.hh:502
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
void noRequest()
Definition: memtest.cc:312
Tick nextProgressMessage
Definition: memtest.hh:163
Stats::Scalar numReadsStat
Definition: memtest.hh:173
Addr baseAddr2
Definition: memtest.hh:158
unsigned int TESTER_ALLOCATOR
Definition: memtest.cc:58
uint64_t numReads
Definition: memtest.hh:165
std::set< Addr > outstandingAddrs
Definition: memtest.hh:137
static const int NumArgumentRegs M5_VAR_USED
Definition: process.cc:83
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:254
Addr uncacheAddr
Definition: memtest.hh:159
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:740
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:83
int size()
Definition: pagetable.hh:146
virtual const std::string name() const
Definition: sim_object.hh:117
const unsigned percentUncacheable
Definition: memtest.hh:130
const bool suppressFuncWarnings
Definition: memtest.hh:171
bool isError() const
Definition: packet.hh:528
const Cycles progressCheck
Definition: memtest.hh:162
The MemObject class extends the ClockedObject with accessor functions to get its master and slave por...
Definition: mem_object.hh:60
A BaseMasterPort is a protocol-agnostic master port, responsible only for the structural connection t...
Definition: port.hh:115
Random random_mt
Definition: random.cc:100
const unsigned percentReads
Definition: memtest.hh:128
void schedule(Event &event, Tick when)
Definition: eventq.hh:728
uint64_t numWrites
Definition: memtest.hh:166
virtual void regStats()
Register statistics for this object.
Definition: memtest.cc:200
Stats::Scalar numWritesStat
Definition: memtest.hh:174
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:287
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:181
void completeRequest(PacketPtr pkt, bool functional=false)
Complete a request by checking the response.
Definition: memtest.cc:137
const T * getConstPtr() const
Definition: packet.hh:967
const uint64_t maxLoads
Definition: memtest.hh:167
fatal_if(p->js_features.size() > 16,"Too many job slot feature registers specified (%i)\n", p->js_features.size())
unsigned getSize() const
Definition: request.hh:552
Addr baseAddr1
Definition: memtest.hh:157
Bitfield< 0 > p
MemTestParams Params
Definition: memtest.hh:75
void set(Type flags)
Definition: flags.hh:70
void regStats() override
Register statistics for this object.
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
Definition: mem_object.cc:52
void sendFunctional(PacketPtr pkt)
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.cc:173
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:102

Generated on Fri Jun 9 2017 13:03:44 for gem5 by doxygen 1.8.6