gem5  v22.1.0.0
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 
52 namespace gem5
53 {
54 
56  : ClockedObject(p),
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 
117 void
119 {
120  assert(writePorts.size() > 0 && readPorts.size() > 0);
121 
123  for (int i = 0; i < m_last_progress_vector.size(); i++) {
125  }
126 
127  m_num_writers = writePorts.size();
128  m_num_readers = readPorts.size();
129  assert(m_num_readers == m_num_cpus);
130 
132 }
133 
134 Port &
135 RubyTester::getPort(const std::string &if_name, PortID idx)
136 {
137  if (if_name != "cpuInstPort" && if_name != "cpuInstDataPort" &&
138  if_name != "cpuDataPort") {
139  // pass it along to our super class
140  return ClockedObject::getPort(if_name, idx);
141  } else {
142  if (if_name == "cpuInstPort") {
143  if (idx > m_num_inst_only_ports) {
144  panic("RubyTester::getPort: unknown inst port %d\n",
145  idx);
146  }
147  //
148  // inst ports map to the lowest readPort elements
149  //
150  return *readPorts[idx];
151  } else if (if_name == "cpuInstDataPort") {
152  if (idx > m_num_inst_data_ports) {
153  panic("RubyTester::getPort: unknown inst+data port %d\n",
154  idx);
155  }
156  int read_idx = idx + m_num_inst_only_ports;
157  //
158  // inst+data ports map to the next readPort elements
159  //
160  return *readPorts[read_idx];
161  } else {
162  assert(if_name == "cpuDataPort");
163  //
164  // data only ports map to the final readPort elements
165  //
166  if (idx > (static_cast<int>(readPorts.size()) -
168  panic("RubyTester::getPort: unknown data port %d\n",
169  idx);
170  }
171  int read_idx = idx + m_num_inst_only_ports + m_num_inst_data_ports;
172  return *readPorts[read_idx];
173  }
174  // Note: currently the Ruby Tester does not support write only ports
175  // but that could easily be added here
176  }
177 }
178 
179 bool
181 {
182  // retrieve the subblock and call hitCallback
183  RubyTester::SenderState* senderState =
184  safe_cast<RubyTester::SenderState*>(pkt->senderState);
185  ruby::SubBlock& subblock = senderState->subBlock;
186 
187  tester->hitCallback(globalIdx, &subblock);
188 
189  // Now that the tester has completed, delete the senderState
190  // (includes sublock) and the packet, then return
191  delete pkt->senderState;
192  delete pkt;
193  return true;
194 }
195 
196 bool
198 {
199  return idx < m_num_inst_only_ports;
200 }
201 
202 bool
204 {
205  return ((idx >= m_num_inst_only_ports) &&
207 }
208 
211 {
212  assert(idx >= 0 && idx < readPorts.size());
213 
214  return readPorts[idx];
215 }
216 
219 {
220  assert(idx >= 0 && idx < writePorts.size());
221 
222  return writePorts[idx];
223 }
224 
225 void
227 {
228  // Mark that we made progress
230 
231  DPRINTF(RubyTest, "completed request for proc: %d", proc);
232  DPRINTFR(RubyTest, " addr: 0x%x, size: %d, data: ",
233  data->getAddress(), data->getSize());
234  for (int byte = 0; byte < data->getSize(); byte++) {
235  DPRINTFR(RubyTest, "%d ", data->getByte(byte));
236  }
237  DPRINTFR(RubyTest, "\n");
238 
239  // This tells us our store has 'completed' or for a load gives us
240  // back the data to make the check
241  Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress());
242  assert(check_ptr != NULL);
243  check_ptr->performCallback(proc, data, curCycle());
244 }
245 
246 void
248 {
250  // Try to perform an action or check
251  Check* check_ptr = m_checkTable_ptr->getRandomCheck();
252  assert(check_ptr != NULL);
253  check_ptr->initiate();
254 
256 
258  } else {
259  exitSimLoop("Ruby Tester completed");
260  }
261 }
262 
263 void
265 {
266  int size = m_last_progress_vector.size();
267  Cycles current_time = curCycle();
268  for (int processor = 0; processor < size; processor++) {
269  if ((current_time - m_last_progress_vector[processor]) >
271  panic("Deadlock detected: current_time: %d last_progress_time: %d "
272  "difference: %d processor: %d\n",
273  current_time, m_last_progress_vector[processor],
274  current_time - m_last_progress_vector[processor], processor);
275  }
276  }
277 }
278 
279 void
280 RubyTester::print(std::ostream& out) const
281 {
282  out << "[RubyTester]" << std::endl;
283 }
284 
285 } // namespace gem5
#define DPRINTFR(x,...)
Definition: trace.hh:200
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
Check * getRandomCheck()
Definition: CheckTable.cc:114
Check * getCheck(Addr address)
Definition: CheckTable.cc:121
void initiate()
Definition: Check.cc:59
void performCallback(ruby::NodeID proc, ruby::SubBlock *data, Cycles curTime)
Definition: Check.cc:287
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
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
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
SenderState * senderState
This packet's sender state.
Definition: packet.hh:544
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:79
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition: RubyTester.cc:180
EventFunctionWrapper checkStartEvent
Definition: RubyTester.hh:125
void checkForDeadlock()
Definition: RubyTester.cc:264
std::vector< RequestPort * > readPorts
Definition: RubyTester.hh:144
bool isInstOnlyCpuPort(int idx)
Definition: RubyTester.cc:197
RequestPort * getWritableCpuPort(int idx)
Definition: RubyTester.cc:218
void hitCallback(ruby::NodeID proc, ruby::SubBlock *data)
Definition: RubyTester.cc:226
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.
Definition: RubyTester.cc:118
bool isInstDataCpuPort(int idx)
Definition: RubyTester.cc:203
std::vector< RequestPort * > writePorts
Definition: RubyTester.hh:143
RequestPort * getReadableCpuPort(int idx)
Definition: RubyTester.cc:210
uint64_t m_checks_to_complete
Definition: RubyTester.hh:145
CheckTable * m_checkTable_ptr
Definition: RubyTester.hh:138
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: RubyTester.cc:135
uint64_t m_checks_completed
Definition: RubyTester.hh:142
std::vector< Cycles > m_last_progress_vector
Definition: RubyTester.hh:139
RubyTesterParams Params
Definition: RubyTester.hh:97
void print(std::ostream &out) const
Definition: RubyTester.cc:280
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
static const Priority CPU_Tick_Pri
CPU ticks must come after other associated CPU events (such as writebacks).
Definition: eventq.hh:204
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
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
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 54 > p
Definition: pagetable.hh:70
unsigned int NodeID
Definition: TypeDefines.hh:42
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
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)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition: sim_events.cc:88
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:32 for gem5 by doxygen 1.9.1