gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Check.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3  * Copyright (c) 2009 Advanced Micro Devices, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met: redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer;
10  * redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution;
13  * neither the name of the copyright holders nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
31 
32 #include "base/random.hh"
33 #include "base/trace.hh"
34 #include "debug/RubyTest.hh"
36 
38 
39 Check::Check(Addr address, Addr pc, int _num_writers, int _num_readers,
40  RubyTester* _tester)
41  : m_num_writers(_num_writers), m_num_readers(_num_readers),
42  m_tester_ptr(_tester)
43 {
44  m_status = TesterStatus_Idle;
45 
46  pickValue();
48  changeAddress(address);
49  m_pc = pc;
50  m_access_mode = RubyAccessMode(random_mt.random(0,
51  RubyAccessMode_NUM - 1));
52  m_store_count = 0;
53 }
54 
55 void
57 {
58  DPRINTF(RubyTest, "initiating\n");
59  debugPrint();
60 
61  // currently no protocols support prefetches
62  if (false && (random_mt.random(0, 0xf) == 0)) {
63  initiatePrefetch(); // Prefetch from random processor
64  }
65 
66  if (m_tester_ptr->getCheckFlush() && (random_mt.random(0, 0xff) == 0)) {
67  initiateFlush(); // issue a Flush request from random processor
68  }
69 
70  if (m_status == TesterStatus_Idle) {
72  } else if (m_status == TesterStatus_Ready) {
73  initiateCheck();
74  } else {
75  // Pending - do nothing
76  DPRINTF(RubyTest,
77  "initiating action/check - failed: action/check is pending\n");
78  }
79 }
80 
81 void
83 {
84  DPRINTF(RubyTest, "initiating prefetch\n");
85 
86  int index = random_mt.random(0, m_num_readers - 1);
88 
89  Request::Flags flags;
90  flags.set(Request::PREFETCH);
91 
92  Packet::Command cmd;
93 
94  // 1 in 8 chance this will be an exclusive prefetch
95  if (random_mt.random(0, 0x7) != 0) {
96  cmd = MemCmd::ReadReq;
97 
98  // if necessary, make the request an instruction fetch
99  if (m_tester_ptr->isInstOnlyCpuPort(index) ||
100  (m_tester_ptr->isInstDataCpuPort(index) &&
101  (random_mt.random(0, 0x1)))) {
102  flags.set(Request::INST_FETCH);
103  }
104  } else {
105  cmd = MemCmd::WriteReq;
106  flags.set(Request::PF_EXCLUSIVE);
107  }
108 
109  // Prefetches are assumed to be 0 sized
110  Request *req = new Request(m_address, 0, flags,
112  req->setContext(index);
113 
114  PacketPtr pkt = new Packet(req, cmd);
115  // despite the oddity of the 0 size (questionable if this should
116  // even be allowed), a prefetch is still a read and as such needs
117  // a place to store the result
118  uint8_t *data = new uint8_t[1];
119  pkt->dataDynamic(data);
120 
121  // push the subblock onto the sender state. The sequencer will
122  // update the subblock on the return
123  pkt->senderState = new SenderState(m_address, req->getSize());
124 
125  if (port->sendTimingReq(pkt)) {
126  DPRINTF(RubyTest, "successfully initiated prefetch.\n");
127  } else {
128  // If the packet did not issue, must delete
129  delete pkt->senderState;
130  delete pkt->req;
131  delete pkt;
132 
133  DPRINTF(RubyTest,
134  "prefetch initiation failed because Port was busy.\n");
135  }
136 }
137 
138 void
140 {
141 
142  DPRINTF(RubyTest, "initiating Flush\n");
143 
144  int index = random_mt.random(0, m_num_writers - 1);
146 
147  Request::Flags flags;
148 
149  Request *req = new Request(m_address, CHECK_SIZE, flags,
151 
152  Packet::Command cmd;
153 
154  cmd = MemCmd::FlushReq;
155 
156  PacketPtr pkt = new Packet(req, cmd);
157 
158  // push the subblock onto the sender state. The sequencer will
159  // update the subblock on the return
160  pkt->senderState = new SenderState(m_address, req->getSize());
161 
162  if (port->sendTimingReq(pkt)) {
163  DPRINTF(RubyTest, "initiating Flush - successful\n");
164  }
165 }
166 
167 void
169 {
170  DPRINTF(RubyTest, "initiating Action\n");
171  assert(m_status == TesterStatus_Idle);
172 
173  int index = random_mt.random(0, m_num_writers - 1);
175 
176  Request::Flags flags;
177 
178  // Create the particular address for the next byte to be written
179  Addr writeAddr(m_address + m_store_count);
180 
181  // Stores are assumed to be 1 byte-sized
182  Request *req = new Request(writeAddr, 1, flags, m_tester_ptr->masterId(),
183  curTick(), m_pc);
184 
185  req->setContext(index);
186  Packet::Command cmd;
187 
188  // 1 out of 8 chance, issue an atomic rather than a write
189  // if ((random() & 0x7) == 0) {
190  // cmd = MemCmd::SwapReq;
191  // } else {
192  cmd = MemCmd::WriteReq;
193  // }
194 
195  PacketPtr pkt = new Packet(req, cmd);
196  uint8_t *writeData = new uint8_t[1];
197  *writeData = m_value + m_store_count;
198  pkt->dataDynamic(writeData);
199 
200  DPRINTF(RubyTest, "Seq write: index %d data 0x%x check 0x%x\n", index,
201  *(pkt->getConstPtr<uint8_t>()), *writeData);
202 
203  // push the subblock onto the sender state. The sequencer will
204  // update the subblock on the return
205  pkt->senderState = new SenderState(writeAddr, req->getSize());
206 
207  if (port->sendTimingReq(pkt)) {
208  DPRINTF(RubyTest, "initiating action - successful\n");
209  DPRINTF(RubyTest, "status before action update: %s\n",
210  (TesterStatus_to_string(m_status)).c_str());
211  m_status = TesterStatus_Action_Pending;
212  DPRINTF(RubyTest, "Check %s, State=Action_Pending\n", m_address);
213  } else {
214  // If the packet did not issue, must delete
215  // Note: No need to delete the data, the packet destructor
216  // will delete it
217  delete pkt->senderState;
218  delete pkt->req;
219  delete pkt;
220 
221  DPRINTF(RubyTest, "failed to initiate action - sequencer not ready\n");
222  }
223 
224  DPRINTF(RubyTest, "status after action update: %s\n",
225  (TesterStatus_to_string(m_status)).c_str());
226 }
227 
228 void
230 {
231  DPRINTF(RubyTest, "Initiating Check\n");
232  assert(m_status == TesterStatus_Ready);
233 
234  int index = random_mt.random(0, m_num_readers - 1);
236 
237  Request::Flags flags;
238 
239  // If necessary, make the request an instruction fetch
240  if (m_tester_ptr->isInstOnlyCpuPort(index) ||
241  (m_tester_ptr->isInstDataCpuPort(index) &&
242  (random_mt.random(0, 0x1)))) {
243  flags.set(Request::INST_FETCH);
244  }
245 
246  // Checks are sized depending on the number of bytes written
247  Request *req = new Request(m_address, CHECK_SIZE, flags,
249 
250  req->setContext(index);
251  PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
252  uint8_t *dataArray = new uint8_t[CHECK_SIZE];
253  pkt->dataDynamic(dataArray);
254 
255  DPRINTF(RubyTest, "Seq read: index %d\n", index);
256 
257  // push the subblock onto the sender state. The sequencer will
258  // update the subblock on the return
259  pkt->senderState = new SenderState(m_address, req->getSize());
260 
261  if (port->sendTimingReq(pkt)) {
262  DPRINTF(RubyTest, "initiating check - successful\n");
263  DPRINTF(RubyTest, "status before check update: %s\n",
264  TesterStatus_to_string(m_status).c_str());
265  m_status = TesterStatus_Check_Pending;
266  DPRINTF(RubyTest, "Check %s, State=Check_Pending\n", m_address);
267  } else {
268  // If the packet did not issue, must delete
269  // Note: No need to delete the data, the packet destructor
270  // will delete it
271  delete pkt->senderState;
272  delete pkt->req;
273  delete pkt;
274 
275  DPRINTF(RubyTest, "failed to initiate check - cpu port not ready\n");
276  }
277 
278  DPRINTF(RubyTest, "status after check update: %s\n",
279  TesterStatus_to_string(m_status).c_str());
280 }
281 
282 void
284 {
285  Addr address = data->getAddress();
286 
287  // This isn't exactly right since we now have multi-byte checks
288  // assert(getAddress() == address);
289 
290  assert(makeLineAddress(m_address) == makeLineAddress(address));
291  assert(data != NULL);
292 
293  DPRINTF(RubyTest, "RubyTester Callback\n");
294  debugPrint();
295 
296  if (m_status == TesterStatus_Action_Pending) {
297  DPRINTF(RubyTest, "Action callback write value: %d, currently %d\n",
298  (m_value + m_store_count), data->getByte(0));
299  // Perform store one byte at a time
300  data->setByte(0, (m_value + m_store_count));
301  m_store_count++;
302  if (m_store_count == CHECK_SIZE) {
303  m_status = TesterStatus_Ready;
304  DPRINTF(RubyTest, "Check %s, State=Ready\n", m_address);
305  } else {
306  m_status = TesterStatus_Idle;
307  DPRINTF(RubyTest, "Check %s, State=Idle store_count: %d\n",
309  }
310  DPRINTF(RubyTest, "Action callback return data now %d\n",
311  data->getByte(0));
312  } else if (m_status == TesterStatus_Check_Pending) {
313  DPRINTF(RubyTest, "Check callback\n");
314  // Perform load/check
315  for (int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
316  if (uint8_t(m_value + byte_number) != data->getByte(byte_number)) {
317  panic("Action/check failure: proc: %d address: %s data: %s "
318  "byte_number: %d m_value+byte_number: %d byte: %d %s"
319  "Time: %d\n",
320  proc, address, data, byte_number,
321  (int)m_value + byte_number,
322  (int)data->getByte(byte_number), *this, curTime);
323  }
324  }
325  DPRINTF(RubyTest, "Action/check success\n");
326  debugPrint();
327 
328  // successful check complete, increment complete
330 
331  m_status = TesterStatus_Idle;
332  DPRINTF(RubyTest, "Check %s, State=Idle\n", m_address);
333  pickValue();
334 
335  } else {
336  panic("Unexpected TesterStatus: %s proc: %d data: %s m_status: %s "
337  "time: %d\n", *this, proc, data, m_status, curTime);
338  }
339 
340  DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc,
342  DPRINTF(RubyTest, "Callback done\n");
343  debugPrint();
344 }
345 
346 void
348 {
349  assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready);
350  m_status = TesterStatus_Idle;
351  m_address = address;
352  DPRINTF(RubyTest, "Check %s, State=Idle\n", m_address);
353  m_store_count = 0;
354 }
355 
356 void
358 {
359  assert(m_status == TesterStatus_Idle);
360  m_value = random_mt.random(0, 0xff); // One byte
361  m_store_count = 0;
362 }
363 
364 void
366 {
367  assert(m_status == TesterStatus_Idle || m_status == TesterStatus_Ready);
368  m_status = TesterStatus_Idle;
370  DPRINTF(RubyTest, "Check %s, State=Idle, picked initiating node %d\n",
372  m_store_count = 0;
373 }
374 
375 void
376 Check::print(std::ostream& out) const
377 {
378  out << "["
379  << m_address << ", value: "
380  << (int)m_value << ", status: "
381  << m_status << ", initiating node: "
382  << m_initiatingNode << ", store_count: "
383  << m_store_count
384  << "]" << std::flush;
385 }
386 
387 void
389 {
390  DPRINTF(RubyTest,
391  "[%#x, value: %d, status: %s, initiating node: %d, store_count: %d]\n",
392  m_address, (int)m_value, TesterStatus_to_string(m_status).c_str(),
394 }
A MasterPort is a specialisation of a BaseMasterPort, which implements the default protocol for the t...
Definition: port.hh:167
RubyTester::SenderState SenderState
Definition: Check.cc:37
#define DPRINTF(x,...)
Definition: trace.hh:212
void initiate()
Definition: Check.cc:56
int m_num_readers
Definition: Check.hh:77
Bitfield< 30, 0 > index
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
void print(std::ostream &out) const
Definition: Check.cc:376
Addr getAddress() const
Definition: SubBlock.hh:45
#define panic(...)
Definition: misc.hh:153
void pickInitiatingNode()
Definition: Check.cc:365
const int CHECK_SIZE
Definition: Check.hh:43
MasterPort * getReadableCpuPort(int idx)
Definition: RubyTester.cc:206
bool isInstOnlyCpuPort(int idx)
Definition: RubyTester.cc:193
Addr m_pc
Definition: Check.hh:74
void initiateCheck()
Definition: Check.cc:229
void performCallback(NodeID proc, SubBlock *data, Cycles curTime)
Definition: Check.cc:283
int m_store_count
Definition: Check.hh:71
void initiatePrefetch()
Definition: Check.cc:82
void setContext(ContextID context_id)
Set up Context numbers.
Definition: request.hh:449
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.cc:180
RubyTester * m_tester_ptr
Definition: Check.hh:78
uint8_t m_value
Definition: Check.hh:70
NodeID m_initiatingNode
Definition: Check.hh:72
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
TesterStatus m_status
Definition: Check.hh:69
MasterID masterId()
Definition: RubyTester.hh:119
const char data[]
Definition: circlebuf.cc:43
The request should be prefetched into the exclusive state.
Definition: request.hh:155
unsigned int NodeID
Definition: TypeDefines.hh:34
Tick curTick()
The current simulated tick.
Definition: core.hh:47
bool isInstDataCpuPort(int idx)
Definition: RubyTester.cc:199
void initiateAction()
Definition: Check.cc:168
void initiateFlush()
Definition: Check.cc:139
void debugPrint()
Definition: Check.cc:388
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
bool getCheckFlush()
Definition: RubyTester.hh:117
RubyAccessMode m_access_mode
Definition: Check.hh:75
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
int m_num_writers
Definition: Check.hh:76
Addr m_address
Definition: Check.hh:73
uint8_t getByte(int offset) const
Definition: SubBlock.hh:50
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
Addr makeLineAddress(Addr addr)
Definition: Address.cc:112
MasterPort * getWritableCpuPort(int idx)
Definition: RubyTester.cc:214
void setByte(int offset, uint8_t data)
Definition: SubBlock.hh:51
SenderState * senderState
This packet's sender state.
Definition: packet.hh:454
The request was an instruction fetch.
Definition: request.hh:104
Check(Addr address, Addr pc, int _num_writers, int _num_readers, RubyTester *_tester)
Definition: Check.cc:39
Random random_mt
Definition: random.cc:100
void changeAddress(Addr address)
Definition: Check.cc:347
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:947
IntReg pc
Definition: remote_gdb.hh:91
const T * getConstPtr() const
Definition: packet.hh:967
Command
List of all commands associated with a packet.
Definition: packet.hh:81
The request is a prefetch.
Definition: request.hh:153
unsigned getSize() const
Definition: request.hh:552
void set(Type flags)
Definition: flags.hh:70
void incrementCheckCompletions()
Definition: RubyTester.hh:110
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:102
void pickValue()
Definition: Check.cc:357

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