gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
RubyTester.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2013 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) 1999-2008 Mark D. Hill and David A. Wood
15 * Copyright (c) 2009 Advanced Micro Devices, Inc.
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
43
44#include "base/logging.hh"
45#include "base/trace.hh"
47#include "debug/RubyTest.hh"
49#include "sim/sim_exit.hh"
50#include "sim/system.hh"
51
52namespace gem5
53{
54
57 checkStartEvent([this]{ wakeup(); }, "RubyTester tick",
58 false, Event::CPU_Tick_Pri),
59 _requestorId(p.system->getRequestorId(this)),
60 m_checkTable_ptr(nullptr),
61 m_num_cpus(p.num_cpus),
62 m_checks_to_complete(p.checks_to_complete),
63 m_deadlock_threshold(p.deadlock_threshold),
64 m_num_writers(0),
65 m_num_readers(0),
66 m_wakeup_frequency(p.wakeup_frequency),
67 m_check_flush(p.check_flush),
68 m_num_inst_only_ports(p.port_cpuInstPort_connection_count),
69 m_num_inst_data_ports(p.port_cpuInstDataPort_connection_count)
70{
71 m_checks_completed = 0;
72
73 //
74 // Create the requested inst and data ports and place them on the
75 // appropriate read and write port lists. The reason for the subtle
76 // difference between inst and data ports vs. read and write ports is
77 // from the tester's perspective, it only needs to know whether a port
78 // supports reads (checks) or writes (actions). Meanwhile, the protocol
79 // controllers have data ports (support read and writes) or inst ports
80 // (support only reads).
81 // Note: the inst ports are the lowest elements of the readPort vector,
82 // then the data ports are added to the readPort vector
83 //
84 int idx = 0;
85 for (int i = 0; i < p.port_cpuInstPort_connection_count; ++i) {
86 readPorts.push_back(new CpuPort(csprintf("%s-instPort%d", name(), i),
87 this, i, idx));
88 idx++;
89 }
90 for (int i = 0; i < p.port_cpuInstDataPort_connection_count; ++i) {
91 CpuPort *port = new CpuPort(csprintf("%s-instDataPort%d", name(), i),
92 this, i, idx);
93 readPorts.push_back(port);
94 writePorts.push_back(port);
95 idx++;
96 }
97 for (int i = 0; i < p.port_cpuDataPort_connection_count; ++i) {
98 CpuPort *port = new CpuPort(csprintf("%s-dataPort%d", name(), i),
99 this, i, idx);
100 readPorts.push_back(port);
101 writePorts.push_back(port);
102 idx++;
103 }
104
105 // add the check start event to the event queue
106 schedule(checkStartEvent, 1);
107}
108
110{
111 delete m_checkTable_ptr;
112 // Only delete the readPorts since the writePorts are just a subset
113 for (int i = 0; i < readPorts.size(); i++)
114 delete readPorts[i];
115}
116
117void
119{
120 assert(writePorts.size() > 0 && readPorts.size() > 0);
121
123 m_num_writers = writePorts.size();
124 m_num_readers = readPorts.size();
125 assert(m_num_readers == m_num_cpus);
126
128}
129
130Port &
131RubyTester::getPort(const std::string &if_name, PortID idx)
132{
133 if (if_name != "cpuInstPort" && if_name != "cpuInstDataPort" &&
134 if_name != "cpuDataPort") {
135 // pass it along to our super class
136 return ClockedObject::getPort(if_name, idx);
137 } else {
138 if (if_name == "cpuInstPort") {
139 if (idx > m_num_inst_only_ports) {
140 panic("RubyTester::getPort: unknown inst port %d\n",
141 idx);
142 }
143 //
144 // inst ports map to the lowest readPort elements
145 //
146 return *readPorts[idx];
147 } else if (if_name == "cpuInstDataPort") {
148 if (idx > m_num_inst_data_ports) {
149 panic("RubyTester::getPort: unknown inst+data port %d\n",
150 idx);
151 }
152 int read_idx = idx + m_num_inst_only_ports;
153 //
154 // inst+data ports map to the next readPort elements
155 //
156 return *readPorts[read_idx];
157 } else {
158 assert(if_name == "cpuDataPort");
159 //
160 // data only ports map to the final readPort elements
161 //
162 if (idx > (static_cast<int>(readPorts.size()) -
164 panic("RubyTester::getPort: unknown data port %d\n",
165 idx);
166 }
167 int read_idx = idx + m_num_inst_only_ports + m_num_inst_data_ports;
168 return *readPorts[read_idx];
169 }
170 // Note: currently the Ruby Tester does not support write only ports
171 // but that could easily be added here
172 }
173}
174
175bool
177{
178 // retrieve the subblock and call hitCallback
179 RubyTester::SenderState* senderState =
181 ruby::SubBlock& subblock = senderState->subBlock;
182
183 tester->hitCallback(globalIdx, &subblock);
184
185 // Now that the tester has completed, delete the senderState
186 // (includes sublock) and the packet, then return
187 delete pkt->senderState;
188 delete pkt;
189 return true;
190}
191
192bool
194{
195 return idx < m_num_inst_only_ports;
196}
197
198bool
200{
201 return ((idx >= m_num_inst_only_ports) &&
203}
204
207{
208 assert(idx >= 0 && idx < readPorts.size());
209
210 return readPorts[idx];
211}
212
215{
216 assert(idx >= 0 && idx < writePorts.size());
217
218 return writePorts[idx];
219}
220
221void
223{
224 DPRINTF(RubyTest, "completed request for proc: %d", proc);
225 DPRINTFR(RubyTest, " addr: 0x%x, size: %d, data: ",
226 data->getAddress(), data->getSize());
227 for (int byte = 0; byte < data->getSize(); byte++) {
228 DPRINTFR(RubyTest, "%d ", data->getByte(byte));
229 }
230 DPRINTFR(RubyTest, "\n");
231
232 // This tells us our store has 'completed' or for a load gives us
233 // back the data to make the check
234 Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress());
235 assert(check_ptr != NULL);
236 check_ptr->performCallback(proc, data, curCycle());
237}
238
239void
241{
243 // Try to perform an action or check
244 Check* check_ptr = m_checkTable_ptr->getRandomCheck();
245 assert(check_ptr != NULL);
246 check_ptr->initiate(curCycle());
247
249
251 } else {
252 exitSimLoop("Ruby Tester completed");
253 }
254}
255
256void
258{
259 int size = m_last_progress_vector.size();
260 Cycles current_time = curCycle();
261 for (int processor = 0; processor < size; processor++) {
262 if (m_last_progress_vector[processor].empty()) {
263 DPRINTF(RubyTest, "Processor %d is idle now, skip\n", processor);
264 continue;
265 }
266 for (const auto& [addr, last_cycle] :
267 m_last_progress_vector[processor]) {
268 if ((current_time - last_cycle) > m_deadlock_threshold) {
269 panic("Possible deadlock detected:\n"
270 " Processor: %d\n"
271 " Addr: %#x\n"
272 " Current Time: %d\n"
273 " Last Progress Time: %d\n"
274 " Difference: %d cycles\n",
275 processor, addr, current_time,
276 last_cycle, current_time - last_cycle);
277 }
278 }
279 }
280}
281
282void
283RubyTester::updateProgress(int index, Addr address, Cycles current_time){
284 m_last_progress_vector[index].emplace(address, current_time);
285 DPRINTF(RubyTest, "Update progress: index: %d \
286 address: %#x current_time: %d\n",
287 index, address, current_time);
288}
289
290void
292 auto i = m_last_progress_vector[index].find(address);
293 assert(i != m_last_progress_vector[index].end());
295 DPRINTF(RubyTest, "Erase progress: index: %d address: %#x\n",
296 index, address);
297}
298
299void
300RubyTester::print(std::ostream& out) const
301{
302 out << "[RubyTester]" << std::endl;
303}
304
305} // namespace gem5
#define DPRINTFR(x,...)
Definition trace.hh:223
#define DPRINTF(x,...)
Definition trace.hh:209
const char data[]
void performCallback(ruby::NodeID proc, ruby::SubBlock *data, Cycles curTime)
Definition Check.cc:296
void initiate(Cycles current_time)
Definition Check.cc:58
ClockedObject(const ClockedObjectParams &p)
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
SenderState * senderState
This packet's sender state.
Definition packet.hh:545
Ports are used to interface objects to each other.
Definition port.hh:62
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition port.hh:136
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
EventFunctionWrapper checkStartEvent
void checkForDeadlock()
std::vector< RequestPort * > readPorts
void eraseProgress(int idx, Addr address)
bool isInstOnlyCpuPort(int idx)
void updateProgress(int idx, Addr address, Cycles current_time)
RequestPort * getWritableCpuPort(int idx)
void hitCallback(ruby::NodeID proc, ruby::SubBlock *data)
RubyTester(const Params &p)
Definition RubyTester.cc:55
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
bool isInstDataCpuPort(int idx)
std::vector< RequestPort * > writePorts
RequestPort * getReadableCpuPort(int idx)
std::vector< std::unordered_map< Addr, Cycles > > m_last_progress_vector
uint64_t m_checks_to_complete
CheckTable * m_checkTable_ptr
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
uint64_t m_checks_completed
RubyTesterParams Params
Definition RubyTester.hh:99
void print(std::ostream &out) const
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
static const Priority CPU_Tick_Pri
CPU ticks must come after other associated CPU events (such as writebacks).
Definition eventq.hh:207
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 30, 0 > index
Bitfield< 0 > p
Bitfield< 3 > addr
Definition types.hh:84
unsigned int NodeID
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
T safe_cast(U &&ref_or_ptr)
Definition cast.hh:74
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)
The "old style" exitSimLoop functions.
Packet * PacketPtr
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
const std::string & name()
Definition trace.cc:48

Generated on Mon May 26 2025 09:19:08 for gem5 by doxygen 1.13.2