gem5 v24.0.0.0
Loading...
Searching...
No Matches
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
37namespace gem5
38{
39
41
42Check::Check(Addr address, Addr pc, int _num_writers, int _num_readers,
43 RubyTester* _tester)
44 : m_num_writers(_num_writers), m_num_readers(_num_readers),
45 m_tester_ptr(_tester)
46{
47 m_status = ruby::TesterStatus_Idle;
48
49 pickValue();
51 changeAddress(address);
52 m_pc = pc;
53 m_access_mode = ruby::RubyAccessMode(
54 random_mt.random(0, ruby::RubyAccessMode_NUM - 1));
55 m_store_count = 0;
56}
57
58void
60{
61 DPRINTF(RubyTest, "initiating\n");
62 debugPrint();
63
64 // currently no protocols support prefetches
65 if (false && (random_mt.random(0, 0xf) == 0)) {
66 initiatePrefetch(); // Prefetch from random processor
67 }
68
69 if (m_tester_ptr->getCheckFlush() && (random_mt.random(0, 0xff) == 0)) {
70 initiateFlush(); // issue a Flush request from random processor
71 }
72
73 if (m_status == ruby::TesterStatus_Idle) {
75 } else if (m_status == ruby::TesterStatus_Ready) {
77 } else {
78 // Pending - do nothing
79 DPRINTF(RubyTest,
80 "initiating action/check - failed: action/check is pending\n");
81 }
82}
83
84void
86{
87 DPRINTF(RubyTest, "initiating prefetch\n");
88
89 int index = random_mt.random(0, m_num_readers - 1);
91
94
96
97 // 1 in 8 chance this will be an exclusive prefetch
98 if (random_mt.random(0, 0x7) != 0) {
99 cmd = MemCmd::ReadReq;
100
101 // if necessary, make the request an instruction fetch
104 (random_mt.random(0, 0x1)))) {
106 }
107 } else {
108 cmd = MemCmd::WriteReq;
110 }
111
112 // Prefetches are assumed to be 0 sized
113 RequestPtr req = std::make_shared<Request>(
115 req->setPC(m_pc);
116 req->setContext(index);
117
118 PacketPtr pkt = new Packet(req, cmd);
119 // despite the oddity of the 0 size (questionable if this should
120 // even be allowed), a prefetch is still a read and as such needs
121 // a place to store the result
122 uint8_t *data = new uint8_t[1];
123 pkt->dataDynamic(data);
124
125 // push the subblock onto the sender state. The sequencer will
126 // update the subblock on the return
127 pkt->senderState = new SenderState(m_address, req->getSize());
128
129 if (port->sendTimingReq(pkt)) {
130 DPRINTF(RubyTest, "successfully initiated prefetch.\n");
131 } else {
132 // If the packet did not issue, must delete
133 delete pkt->senderState;
134 delete pkt;
135
136 DPRINTF(RubyTest,
137 "prefetch initiation failed because Port was busy.\n");
138 }
139}
140
141void
143{
144
145 DPRINTF(RubyTest, "initiating Flush\n");
146
147 int index = random_mt.random(0, m_num_writers - 1);
149
151
152 RequestPtr req = std::make_shared<Request>(
154 req->setPC(m_pc);
155
156 Packet::Command cmd;
157
158 cmd = MemCmd::FlushReq;
159
160 PacketPtr pkt = new Packet(req, cmd);
161
162 // push the subblock onto the sender state. The sequencer will
163 // update the subblock on the return
164 pkt->senderState = new SenderState(m_address, req->getSize());
165
166 if (port->sendTimingReq(pkt)) {
167 DPRINTF(RubyTest, "initiating Flush - successful\n");
168 }
169}
170
171void
173{
174 DPRINTF(RubyTest, "initiating Action\n");
175 assert(m_status == ruby::TesterStatus_Idle);
176
177 int index = random_mt.random(0, m_num_writers - 1);
179
181
182 // Create the particular address for the next byte to be written
183 Addr writeAddr(m_address + m_store_count);
184
185 // Stores are assumed to be 1 byte-sized
186 RequestPtr req = std::make_shared<Request>(
187 writeAddr, 1, flags, m_tester_ptr->requestorId());
188 req->setPC(m_pc);
189
190 req->setContext(index);
191 Packet::Command cmd;
192
193 // 1 out of 8 chance, issue an atomic rather than a write
194 // if ((random() & 0x7) == 0) {
195 // cmd = MemCmd::SwapReq;
196 // } else {
197 cmd = MemCmd::WriteReq;
198 // }
199
200 PacketPtr pkt = new Packet(req, cmd);
201 uint8_t *writeData = new uint8_t[1];
202 *writeData = m_value + m_store_count;
203 pkt->dataDynamic(writeData);
204
205 DPRINTF(RubyTest, "Seq write: index %d data 0x%x check 0x%x\n", index,
206 *(pkt->getConstPtr<uint8_t>()), *writeData);
207
208 // push the subblock onto the sender state. The sequencer will
209 // update the subblock on the return
210 pkt->senderState = new SenderState(writeAddr, req->getSize());
211
212 if (port->sendTimingReq(pkt)) {
213 DPRINTF(RubyTest, "initiating action - successful\n");
214 DPRINTF(RubyTest, "status before action update: %s\n",
215 (ruby::TesterStatus_to_string(m_status)).c_str());
216 m_status = ruby::TesterStatus_Action_Pending;
217 DPRINTF(RubyTest, "Check %#x, State=Action_Pending\n", m_address);
218 } else {
219 // If the packet did not issue, must delete
220 // Note: No need to delete the data, the packet destructor
221 // will delete it
222 delete pkt->senderState;
223 delete pkt;
224
225 DPRINTF(RubyTest, "failed to initiate action - sequencer not ready\n");
226 }
227
228 DPRINTF(RubyTest, "status after action update: %s\n",
229 (ruby::TesterStatus_to_string(m_status)).c_str());
230}
231
232void
234{
235 DPRINTF(RubyTest, "Initiating Check\n");
236 assert(m_status == ruby::TesterStatus_Ready);
237
238 int index = random_mt.random(0, m_num_readers - 1);
240
242
243 // If necessary, make the request an instruction fetch
246 (random_mt.random(0, 0x1)))) {
248 }
249
250 // Checks are sized depending on the number of bytes written
251 RequestPtr req = std::make_shared<Request>(
253 req->setPC(m_pc);
254
255 req->setContext(index);
256 PacketPtr pkt = new Packet(req, MemCmd::ReadReq);
257 uint8_t *dataArray = new uint8_t[CHECK_SIZE];
258 pkt->dataDynamic(dataArray);
259
260 DPRINTF(RubyTest, "Seq read: index %d\n", index);
261
262 // push the subblock onto the sender state. The sequencer will
263 // update the subblock on the return
264 pkt->senderState = new SenderState(m_address, req->getSize());
265
266 if (port->sendTimingReq(pkt)) {
267 DPRINTF(RubyTest, "initiating check - successful\n");
268 DPRINTF(RubyTest, "status before check update: %s\n",
269 ruby::TesterStatus_to_string(m_status).c_str());
270 m_status = ruby::TesterStatus_Check_Pending;
271 DPRINTF(RubyTest, "Check %#x, State=Check_Pending\n", m_address);
272 } else {
273 // If the packet did not issue, must delete
274 // Note: No need to delete the data, the packet destructor
275 // will delete it
276 delete pkt->senderState;
277 delete pkt;
278
279 DPRINTF(RubyTest, "failed to initiate check - cpu port not ready\n");
280 }
281
282 DPRINTF(RubyTest, "status after check update: %s\n",
283 ruby::TesterStatus_to_string(m_status).c_str());
284}
285
286void
288{
289 Addr address = data->getAddress();
290
291 // This isn't exactly right since we now have multi-byte checks
292 // assert(getAddress() == address);
293
295 assert(data != NULL);
296
297 DPRINTF(RubyTest, "RubyTester Callback\n");
298 debugPrint();
299
300 if (m_status == ruby::TesterStatus_Action_Pending) {
301 DPRINTF(RubyTest, "Action callback write value: %d, currently %d\n",
302 (m_value + m_store_count), data->getByte(0));
303 // Perform store one byte at a time
304 data->setByte(0, (m_value + m_store_count));
306 if (m_store_count == CHECK_SIZE) {
307 m_status = ruby::TesterStatus_Ready;
308 DPRINTF(RubyTest, "Check %#x, State=Ready\n", m_address);
309 } else {
310 m_status = ruby::TesterStatus_Idle;
311 DPRINTF(RubyTest, "Check %#x, State=Idle store_count: %d\n",
313 }
314 DPRINTF(RubyTest, "Action callback return data now %d\n",
315 data->getByte(0));
316 } else if (m_status == ruby::TesterStatus_Check_Pending) {
317 DPRINTF(RubyTest, "Check callback\n");
318 // Perform load/check
319 for (int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
320 if (uint8_t(m_value + byte_number) != data->getByte(byte_number)) {
321 panic("Action/check failure: proc: %d address: %#x data: %s "
322 "byte_number: %d m_value+byte_number: %d byte: %d %s"
323 "Time: %d\n",
324 proc, address, data, byte_number,
325 (int)m_value + byte_number,
326 (int)data->getByte(byte_number), *this, curTime);
327 }
328 }
329 DPRINTF(RubyTest, "Action/check success\n");
330 debugPrint();
331
332 // successful check complete, increment complete
334
335 m_status = ruby::TesterStatus_Idle;
336 DPRINTF(RubyTest, "Check %#x, State=Idle\n", m_address);
337 pickValue();
338
339 } else {
340 panic("Unexpected TesterStatus: %s proc: %d data: %s m_status: %s "
341 "time: %d\n", *this, proc, data, m_status, curTime);
342 }
343
344 DPRINTF(RubyTest, "proc: %d, Address: 0x%x\n", proc,
346 DPRINTF(RubyTest, "Callback done\n");
347 debugPrint();
348}
349
350void
352{
353 assert(m_status == ruby::TesterStatus_Idle ||
354 m_status == ruby::TesterStatus_Ready);
355 m_status = ruby::TesterStatus_Idle;
356 m_address = address;
357 DPRINTF(RubyTest, "Check %#x, State=Idle\n", m_address);
358 m_store_count = 0;
359}
360
361void
363{
364 assert(m_status == ruby::TesterStatus_Idle);
365 m_value = random_mt.random(0, 0xff); // One byte
366 m_store_count = 0;
367}
368
369void
371{
372 assert(m_status == ruby::TesterStatus_Idle ||
373 m_status == ruby::TesterStatus_Ready);
374 m_status = ruby::TesterStatus_Idle;
376 DPRINTF(RubyTest, "Check %#x, State=Idle, picked initiating node %d\n",
378 m_store_count = 0;
379}
380
381void
382Check::print(std::ostream& out) const
383{
384 out << "["
385 << m_address << ", value: "
386 << (int)m_value << ", status: "
387 << m_status << ", initiating node: "
388 << m_initiatingNode << ", store_count: "
390 << "]" << std::flush;
391}
392
393void
395{
396 DPRINTF(RubyTest,
397 "[%#x, value: %d, status: %s, initiating node: %d, store_count: %d]\n",
398 m_address, (int)m_value,
399 ruby::TesterStatus_to_string(m_status).c_str(),
401}
402
403} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
void changeAddress(Addr address)
Definition Check.cc:351
Addr m_pc
Definition Check.hh:81
void initiateCheck()
Definition Check.cc:233
void initiate()
Definition Check.cc:59
ruby::RubyAccessMode m_access_mode
Definition Check.hh:82
void initiateAction()
Definition Check.cc:172
void pickInitiatingNode()
Definition Check.cc:370
void print(std::ostream &out) const
Definition Check.cc:382
int m_store_count
Definition Check.hh:78
void performCallback(ruby::NodeID proc, ruby::SubBlock *data, Cycles curTime)
Definition Check.cc:287
void pickValue()
Definition Check.cc:362
Addr m_address
Definition Check.hh:80
void initiateFlush()
Definition Check.cc:142
void initiatePrefetch()
Definition Check.cc:85
RubyTester * m_tester_ptr
Definition Check.hh:85
ruby::NodeID m_initiatingNode
Definition Check.hh:79
void debugPrint()
Definition Check.cc:394
ruby::TesterStatus m_status
Definition Check.hh:76
uint8_t m_value
Definition Check.hh:77
Check(Addr address, Addr pc, int _num_writers, int _num_readers, RubyTester *_tester)
Definition Check.cc:42
int m_num_writers
Definition Check.hh:83
int m_num_readers
Definition Check.hh:84
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
Command
List of all commands associated with a packet.
Definition packet.hh:85
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
SenderState * senderState
This packet's sender state.
Definition packet.hh:545
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
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition port.hh:136
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition port.hh:603
@ PF_EXCLUSIVE
The request should be prefetched into the exclusive state.
Definition request.hh:166
@ INST_FETCH
The request was an instruction fetch.
Definition request.hh:115
@ PREFETCH
The request is a prefetch.
Definition request.hh:164
bool isInstOnlyCpuPort(int idx)
void incrementCheckCompletions()
RequestPort * getWritableCpuPort(int idx)
RequestorID requestorId()
bool isInstDataCpuPort(int idx)
RequestPort * getReadableCpuPort(int idx)
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 set(Type mask)
Set all flag's bits matching the given mask.
Definition flags.hh:116
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
uint8_t flags
Definition helpers.cc:87
Bitfield< 4 > pc
Bitfield< 30, 0 > index
unsigned int NodeID
Addr makeLineAddress(Addr addr)
Definition Address.cc:60
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
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
const int CHECK_SIZE
Definition Check.hh:49
RubyTester::SenderState SenderState
Definition Check.cc:40

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