gem5  v20.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 
53  : ClockedObject(p),
54  checkStartEvent([this]{ wakeup(); }, "RubyTester tick",
55  false, Event::CPU_Tick_Pri),
56  _requestorId(p->system->getRequestorId(this)),
57  m_checkTable_ptr(nullptr),
58  m_num_cpus(p->num_cpus),
59  m_checks_to_complete(p->checks_to_complete),
60  m_deadlock_threshold(p->deadlock_threshold),
61  m_num_writers(0),
62  m_num_readers(0),
63  m_wakeup_frequency(p->wakeup_frequency),
64  m_check_flush(p->check_flush),
65  m_num_inst_only_ports(p->port_cpuInstPort_connection_count),
66  m_num_inst_data_ports(p->port_cpuInstDataPort_connection_count)
67 {
68  m_checks_completed = 0;
69 
70  //
71  // Create the requested inst and data ports and place them on the
72  // appropriate read and write port lists. The reason for the subtle
73  // difference between inst and data ports vs. read and write ports is
74  // from the tester's perspective, it only needs to know whether a port
75  // supports reads (checks) or writes (actions). Meanwhile, the protocol
76  // controllers have data ports (support read and writes) or inst ports
77  // (support only reads).
78  // Note: the inst ports are the lowest elements of the readPort vector,
79  // then the data ports are added to the readPort vector
80  //
81  int idx = 0;
82  for (int i = 0; i < p->port_cpuInstPort_connection_count; ++i) {
83  readPorts.push_back(new CpuPort(csprintf("%s-instPort%d", name(), i),
84  this, i, idx));
85  idx++;
86  }
87  for (int i = 0; i < p->port_cpuInstDataPort_connection_count; ++i) {
88  CpuPort *port = new CpuPort(csprintf("%s-instDataPort%d", name(), i),
89  this, i, idx);
90  readPorts.push_back(port);
91  writePorts.push_back(port);
92  idx++;
93  }
94  for (int i = 0; i < p->port_cpuDataPort_connection_count; ++i) {
95  CpuPort *port = new CpuPort(csprintf("%s-dataPort%d", name(), i),
96  this, i, idx);
97  readPorts.push_back(port);
98  writePorts.push_back(port);
99  idx++;
100  }
101 
102  // add the check start event to the event queue
103  schedule(checkStartEvent, 1);
104 }
105 
107 {
108  delete m_checkTable_ptr;
109  // Only delete the readPorts since the writePorts are just a subset
110  for (int i = 0; i < readPorts.size(); i++)
111  delete readPorts[i];
112 }
113 
114 void
116 {
117  assert(writePorts.size() > 0 && readPorts.size() > 0);
118 
120  for (int i = 0; i < m_last_progress_vector.size(); i++) {
122  }
123 
124  m_num_writers = writePorts.size();
125  m_num_readers = readPorts.size();
126  assert(m_num_readers == m_num_cpus);
127 
129 }
130 
131 Port &
132 RubyTester::getPort(const std::string &if_name, PortID idx)
133 {
134  if (if_name != "cpuInstPort" && if_name != "cpuInstDataPort" &&
135  if_name != "cpuDataPort") {
136  // pass it along to our super class
137  return ClockedObject::getPort(if_name, idx);
138  } else {
139  if (if_name == "cpuInstPort") {
140  if (idx > m_num_inst_only_ports) {
141  panic("RubyTester::getPort: unknown inst port %d\n",
142  idx);
143  }
144  //
145  // inst ports map to the lowest readPort elements
146  //
147  return *readPorts[idx];
148  } else if (if_name == "cpuInstDataPort") {
149  if (idx > m_num_inst_data_ports) {
150  panic("RubyTester::getPort: unknown inst+data port %d\n",
151  idx);
152  }
153  int read_idx = idx + m_num_inst_only_ports;
154  //
155  // inst+data ports map to the next readPort elements
156  //
157  return *readPorts[read_idx];
158  } else {
159  assert(if_name == "cpuDataPort");
160  //
161  // data only ports map to the final readPort elements
162  //
163  if (idx > (static_cast<int>(readPorts.size()) -
165  panic("RubyTester::getPort: unknown data port %d\n",
166  idx);
167  }
168  int read_idx = idx + m_num_inst_only_ports + m_num_inst_data_ports;
169  return *readPorts[read_idx];
170  }
171  // Note: currently the Ruby Tester does not support write only ports
172  // but that could easily be added here
173  }
174 }
175 
176 bool
178 {
179  // retrieve the subblock and call hitCallback
180  RubyTester::SenderState* senderState =
181  safe_cast<RubyTester::SenderState*>(pkt->senderState);
182  SubBlock& subblock = senderState->subBlock;
183 
184  tester->hitCallback(globalIdx, &subblock);
185 
186  // Now that the tester has completed, delete the senderState
187  // (includes sublock) and the packet, then return
188  delete pkt->senderState;
189  delete pkt;
190  return true;
191 }
192 
193 bool
195 {
196  return idx < m_num_inst_only_ports;
197 }
198 
199 bool
201 {
202  return ((idx >= m_num_inst_only_ports) &&
204 }
205 
208 {
209  assert(idx >= 0 && idx < readPorts.size());
210 
211  return readPorts[idx];
212 }
213 
216 {
217  assert(idx >= 0 && idx < writePorts.size());
218 
219  return writePorts[idx];
220 }
221 
222 void
224 {
225  // Mark that we made progress
227 
228  DPRINTF(RubyTest, "completed request for proc: %d", proc);
229  DPRINTFR(RubyTest, " addr: 0x%x, size: %d, data: ",
230  data->getAddress(), data->getSize());
231  for (int byte = 0; byte < data->getSize(); byte++) {
232  DPRINTFR(RubyTest, "%d ", data->getByte(byte));
233  }
234  DPRINTFR(RubyTest, "\n");
235 
236  // This tells us our store has 'completed' or for a load gives us
237  // back the data to make the check
238  Check* check_ptr = m_checkTable_ptr->getCheck(data->getAddress());
239  assert(check_ptr != NULL);
240  check_ptr->performCallback(proc, data, curCycle());
241 }
242 
243 void
245 {
247  // Try to perform an action or check
248  Check* check_ptr = m_checkTable_ptr->getRandomCheck();
249  assert(check_ptr != NULL);
250  check_ptr->initiate();
251 
253 
255  } else {
256  exitSimLoop("Ruby Tester completed");
257  }
258 }
259 
260 void
262 {
263  int size = m_last_progress_vector.size();
264  Cycles current_time = curCycle();
265  for (int processor = 0; processor < size; processor++) {
266  if ((current_time - m_last_progress_vector[processor]) >
268  panic("Deadlock detected: current_time: %d last_progress_time: %d "
269  "difference: %d processor: %d\n",
270  current_time, m_last_progress_vector[processor],
271  current_time - m_last_progress_vector[processor], processor);
272  }
273  }
274 }
275 
276 void
277 RubyTester::print(std::ostream& out) const
278 {
279  out << "[RubyTester]" << std::endl;
280 }
281 
282 RubyTester *
283 RubyTesterParams::create()
284 {
285  return new RubyTester(this);
286 }
RubyTester::hitCallback
void hitCallback(NodeID proc, SubBlock *data)
Definition: RubyTester.cc:223
Check::initiate
void initiate()
Definition: Check.cc:56
system.hh
CheckTable
Definition: CheckTable.hh:42
EventBase::CPU_Tick_Pri
static const Priority CPU_Tick_Pri
CPU ticks must come after other associated CPU events (such as writebacks).
Definition: eventq.hh:199
data
const char data[]
Definition: circlebuf.test.cc:42
RubyTester::RubyTester
RubyTester(const Params *p)
Definition: RubyTester.cc:52
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
RubyTester::m_num_inst_only_ports
int m_num_inst_only_ports
Definition: RubyTester.hh:148
RubyTester::CpuPort::globalIdx
PortID globalIdx
Definition: RubyTester.hh:65
PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
Check::performCallback
void performCallback(NodeID proc, SubBlock *data, Cycles curTime)
Definition: Check.cc:284
CheckTable::getRandomCheck
Check * getRandomCheck()
Definition: CheckTable.cc:111
RubyTester::checkStartEvent
EventFunctionWrapper checkStartEvent
Definition: RubyTester.hh:122
sim_exit.hh
RubyTester::getWritableCpuPort
RequestPort * getWritableCpuPort(int idx)
Definition: RubyTester.cc:215
ClockedObject
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Definition: clocked_object.hh:231
RubyTester::m_checks_completed
uint64_t m_checks_completed
Definition: RubyTester.hh:139
RubyTester::isInstDataCpuPort
bool isInstDataCpuPort(int idx)
Definition: RubyTester.cc:200
Check.hh
RubyTester::~RubyTester
~RubyTester()
Definition: RubyTester.cc:106
RubyTester::checkForDeadlock
void checkForDeadlock()
Definition: RubyTester.cc:261
RubyTester::m_checkTable_ptr
CheckTable * m_checkTable_ptr
Definition: RubyTester.hh:135
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1005
RubyTester::getReadableCpuPort
RequestPort * getReadableCpuPort(int idx)
Definition: RubyTester.cc:207
RubyTester::m_num_inst_data_ports
int m_num_inst_data_ports
Definition: RubyTester.hh:149
SimObject::getPort
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Definition: sim_object.cc:123
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
RubyTester::m_num_cpus
int m_num_cpus
Definition: RubyTester.hh:138
RubyTester::m_deadlock_threshold
int m_deadlock_threshold
Definition: RubyTester.hh:143
RubyTester::CpuPort::tester
RubyTester * tester
Definition: RubyTester.hh:63
RubyTester::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: RubyTester.cc:132
RubyTester::m_num_readers
int m_num_readers
Definition: RubyTester.hh:145
RubyTester::CpuPort::recvTimingResp
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition: RubyTester.cc:177
Port
Ports are used to interface objects to each other.
Definition: port.hh:56
RubyTester.hh
Clocked::curCycle
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
Definition: clocked_object.hh:192
RubyTester::SenderState
Definition: RubyTester.hh:86
CheckTable::getCheck
Check * getCheck(Addr address)
Definition: CheckTable.cc:118
DPRINTFR
#define DPRINTFR(...)
Definition: trace.hh:236
exitSimLoop
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
RubyTester::writePorts
std::vector< RequestPort * > writePorts
Definition: RubyTester.hh:140
RequestPort
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition: port.hh:74
RubyTester::isInstOnlyCpuPort
bool isInstOnlyCpuPort(int idx)
Definition: RubyTester.cc:194
RubyTester::m_wakeup_frequency
int m_wakeup_frequency
Definition: RubyTester.hh:146
RubyTester::print
void print(std::ostream &out) const
Definition: RubyTester.cc:277
RubyTester::Params
RubyTesterParams Params
Definition: RubyTester.hh:94
name
const std::string & name()
Definition: trace.cc:50
SubBlock
Definition: SubBlock.hh:38
RubyTester::SenderState::subBlock
SubBlock subBlock
Definition: RubyTester.hh:88
Check
Definition: Check.hh:45
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
RubyTester::m_checks_to_complete
uint64_t m_checks_to_complete
Definition: RubyTester.hh:142
RubyTester::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: RubyTester.cc:115
RubyTester::readPorts
std::vector< RequestPort * > readPorts
Definition: RubyTester.hh:141
logging.hh
Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
NodeID
unsigned int NodeID
Definition: TypeDefines.hh:34
trace.hh
RubyTester
Definition: RubyTester.hh:57
Packet::senderState
SenderState * senderState
This packet's sender state.
Definition: packet.hh:508
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
RubyTester::m_num_writers
int m_num_writers
Definition: RubyTester.hh:144
RubyTester::wakeup
void wakeup()
Definition: RubyTester.cc:244
csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
SubBlock.hh
RubyTester::m_last_progress_vector
std::vector< Cycles > m_last_progress_vector
Definition: RubyTester.hh:136
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

Generated on Wed Sep 30 2020 14:02:09 for gem5 by doxygen 1.8.17