gem5  v21.1.0.2
protocol_tester.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2021 Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * For use for simulation and test purposes only
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
35 
36 #include <algorithm>
37 #include <ctime>
38 #include <fstream>
39 #include <random>
40 
45 #include "debug/ProtocolTest.hh"
46 #include "mem/request.hh"
47 #include "sim/sim_exit.hh"
48 #include "sim/system.hh"
49 
50 namespace gem5
51 {
52 
54  : ClockedObject(p),
55  _requestorId(p.system->getRequestorId(this)),
56  numCpuPorts(p.port_cpu_ports_connection_count),
57  numDmaPorts(p.port_dma_ports_connection_count),
58  numVectorPorts(p.port_cu_vector_ports_connection_count),
59  numSqcPorts(p.port_cu_sqc_ports_connection_count),
60  numScalarPorts(p.port_cu_scalar_ports_connection_count),
61  numTokenPorts(p.port_cu_token_ports_connection_count),
62  numCusPerSqc(p.cus_per_sqc),
63  numCusPerScalar(p.cus_per_scalar),
64  numWfsPerCu(p.wavefronts_per_cu),
65  numWisPerWf(p.workitems_per_wavefront),
66  numCuTokens(p.max_cu_tokens),
67  numAtomicLocs(p.num_atomic_locations),
68  numNormalLocsPerAtomic(p.num_normal_locs_per_atomic),
69  episodeLength(p.episode_length),
70  maxNumEpisodes(p.max_num_episodes),
71  debugTester(p.debug_tester),
72  cpuThreads(p.cpu_threads),
73  dmaThreads(p.dma_threads),
74  wfs(p.wavefronts)
75 {
76  int idx = 0; // global port index
77 
78  numCpus = numCpuPorts; // 1 cpu port per CPU
79  numDmas = numDmaPorts; // 1 dma port per DMA
80  numCus = numVectorPorts; // 1 vector port per CU
81 
82  // create all physical cpu's data ports
83  for (int i = 0; i < numCpuPorts; ++i) {
84  DPRINTF(ProtocolTest, "Creating %s\n",
85  csprintf("%s-cpuPort%d", name(), i));
86  cpuPorts.push_back(new SeqPort(csprintf("%s-cpuPort%d", name(), i),
87  this, i, idx));
88  idx++;
89  }
90 
91  // create all physical DMA data ports
92  for (int i = 0; i < numDmaPorts; ++i) {
93  DPRINTF(ProtocolTest, "Creating %s\n",
94  csprintf("%s-dmaPort%d", name(), i));
95  dmaPorts.push_back(new SeqPort(csprintf("%s-dmaPort%d", name(), i),
96  this, i, idx));
97  idx++;
98  }
99 
100  // create all physical gpu's data ports
101  for (int i = 0; i < numVectorPorts; ++i) {
102  DPRINTF(ProtocolTest, "Creating %s\n",
103  csprintf("%s-cuVectorPort%d", name(), i));
104  cuVectorPorts.push_back(new SeqPort(csprintf("%s-cuVectorPort%d",
105  name(), i),
106  this, i, idx));
107  idx++;
108  }
109 
110  for (int i = 0; i < numScalarPorts; ++i) {
111  DPRINTF(ProtocolTest, "Creating %s\n",
112  csprintf("%s-cuScalarPort%d", name(), i));
113  cuScalarPorts.push_back(new SeqPort(csprintf("%s-cuScalarPort%d",
114  name(), i),
115  this, i, idx));
116  idx++;
117  }
118 
119  for (int i = 0; i < numSqcPorts; ++i) {
120  DPRINTF(ProtocolTest, "Creating %s\n",
121  csprintf("%s-cuSqcPort%d", name(), i));
122  cuSqcPorts.push_back(new SeqPort(csprintf("%s-cuSqcPort%d",
123  name(), i),
124  this, i, idx));
125  idx++;
126  }
127 
128  for (int i = 0; i < numTokenPorts; ++i) {
129  cuTokenPorts.push_back(new GMTokenPort(csprintf("%s-cuTokenPort%d",
130  name(), i),
131  this, i));
132  cuTokenManagers.push_back(new TokenManager(numCuTokens));
133  cuTokenPorts[i]->setTokenManager(cuTokenManagers[i]);
134  }
135 
136  // create an address manager
139  nextEpisodeId = 0;
140 
141  if (!debugTester)
142  warn("Data race check is not enabled\n");
143 
144  sentExitSignal = false;
145 
146  // set random seed number
147  if (p.random_seed != 0) {
148  srand(p.random_seed);
149  } else {
150  srand(time(NULL));
151  }
152 
153  actionCount = 0;
154 
155  // create a new log file
156  logFile = simout.create(p.log_file);
157  assert(logFile);
158 
159  // print test configs
160  std::stringstream ss;
161  ss << "GPU Ruby test's configurations" << std::endl
162  << "\tNumber of CPUs: " << numCpus << std::endl
163  << "\tNumber of DMAs: " << numDmas << std::endl
164  << "\tNumber of CUs: " << numCus << std::endl
165  << "\tNumber of wavefronts per CU: " << numWfsPerCu << std::endl
166  << "\tWavefront size: " << numWisPerWf << std::endl
167  << "\tNumber of atomic locations: " << numAtomicLocs << std::endl
168  << "\tNumber of non-atomic locations: "
169  << numNormalLocsPerAtomic * numAtomicLocs << std::endl
170  << "\tEpisode length: " << episodeLength << std::endl
171  << "\tTest length (max number of episodes): " << maxNumEpisodes
172  << std::endl
173  << "\tRandom seed: " << p.random_seed
174  << std::endl;
175 
176  ccprintf(*(logFile->stream()), "%s", ss.str());
177  logFile->stream()->flush();
178 }
179 
181 {
182  for (int i = 0; i < cpuPorts.size(); ++i)
183  delete cpuPorts[i];
184  for (int i = 0; i < dmaPorts.size(); ++i)
185  delete dmaPorts[i];
186  for (int i = 0; i < cuVectorPorts.size(); ++i)
187  delete cuVectorPorts[i];
188  for (int i = 0; i < cuScalarPorts.size(); ++i)
189  delete cuScalarPorts[i];
190  for (int i = 0; i < cuSqcPorts.size(); ++i)
191  delete cuSqcPorts[i];
192  delete addrManager;
193 
194  // close the log file
196 }
197 
198 void
200 {
201  DPRINTF(ProtocolTest, "Attach threads to ports\n");
202 
203  // connect cpu threads to cpu's ports
204  for (int cpu_id = 0; cpu_id < numCpus; ++cpu_id) {
205  cpuThreads[cpu_id]->attachTesterThreadToPorts(this,
206  static_cast<SeqPort*>(cpuPorts[cpu_id]));
207  cpuThreads[cpu_id]->scheduleWakeup();
208  cpuThreads[cpu_id]->scheduleDeadlockCheckEvent();
209  }
210 
211  // connect dma threads to dma's ports
212  for (int dma_id = 0; dma_id < numDmas; ++dma_id) {
213  dmaThreads[dma_id]->attachTesterThreadToPorts(this,
214  static_cast<SeqPort*>(dmaPorts[dma_id]));
215  dmaThreads[dma_id]->scheduleWakeup();
216  dmaThreads[dma_id]->scheduleDeadlockCheckEvent();
217  }
218 
219  // connect gpu wavefronts to gpu's ports
220  int wfId = 0;
221  int vectorPortId = 0;
222  int sqcPortId = 0;
223  int scalarPortId = 0;
224 
225  for (int cu_id = 0; cu_id < numCus; ++cu_id) {
226  vectorPortId = cu_id;
227  sqcPortId = cu_id/numCusPerSqc;
228  scalarPortId = cu_id/numCusPerScalar;
229 
230  for (int i = 0; i < numWfsPerCu; ++i) {
231  wfId = cu_id * numWfsPerCu + i;
232  wfs[wfId]->attachTesterThreadToPorts(this,
233  static_cast<SeqPort*>(cuVectorPorts[vectorPortId]),
234  cuTokenPorts[vectorPortId],
235  static_cast<SeqPort*>(cuSqcPorts[sqcPortId]),
236  static_cast<SeqPort*>(cuScalarPorts[scalarPortId]));
237  wfs[wfId]->scheduleWakeup();
238  wfs[wfId]->scheduleDeadlockCheckEvent();
239  }
240  }
241 }
242 
243 Port&
244 ProtocolTester::getPort(const std::string &if_name, PortID idx)
245 {
246  if (if_name != "cpu_ports" && if_name != "dma_ports" &&
247  if_name != "cu_vector_ports" && if_name != "cu_sqc_ports" &&
248  if_name != "cu_scalar_ports" && if_name != "cu_token_ports") {
249  // pass along to super class
250  return ClockedObject::getPort(if_name, idx);
251  } else {
252  if (if_name == "cpu_ports") {
253  if (idx > numCpuPorts)
254  panic("ProtocolTester: unknown cpu port %d\n", idx);
255  return *cpuPorts[idx];
256  } else if (if_name == "dma_ports") {
257  if (idx > numDmaPorts)
258  panic("ProtocolTester: unknown dma port %d\n", idx);
259  return *dmaPorts[idx];
260  } else if (if_name == "cu_vector_ports") {
261  if (idx > numVectorPorts)
262  panic("ProtocolTester: unknown cu vect port %d\n", idx);
263  return *cuVectorPorts[idx];
264  } else if (if_name == "cu_sqc_ports") {
265  if (idx > numSqcPorts)
266  panic("ProtocolTester: unknown cu sqc port %d\n", idx);
267  return *cuSqcPorts[idx];
268  } else if (if_name == "cu_token_ports") {
269  if (idx > numTokenPorts)
270  panic("ProtocolTester: unknown cu token port %d\n", idx);
271  return *cuTokenPorts[idx];
272  } else {
273  assert(if_name == "cu_scalar_ports");
274  if (idx > numScalarPorts)
275  panic("ProtocolTester: unknown cu scal port %d\n", idx);
276  return *cuScalarPorts[idx];
277  }
278  }
279 
280  assert(false);
281 }
282 
283 bool
285 {
287  if (!sentExitSignal) {
288  // all done
289  inform("Total completed episodes: %d\n", nextEpisodeId - 1);
290  exitSimLoop("GPU Ruby Tester: Passed!");
291  sentExitSignal = true;
292  }
293  return true;
294  }
295  return false;
296 }
297 
298 bool
300  Location loc, bool isStore) const
301 {
302  if (debugTester) {
303  // go through all active episodes in all threads
304  for (const TesterThread* th : wfs) {
305  if (!th->checkDRF(atomic_loc, loc, isStore))
306  return false;
307  }
308 
309  for (const TesterThread* th : cpuThreads) {
310  if (!th->checkDRF(atomic_loc, loc, isStore))
311  return false;
312  }
313 
314  for (const TesterThread* th : dmaThreads) {
315  if (!th->checkDRF(atomic_loc, loc, isStore))
316  return false;
317  }
318  }
319 
320  return true;
321 }
322 
323 void
324 ProtocolTester::dumpErrorLog(std::stringstream& ss)
325 {
326  if (!sentExitSignal) {
327  // go through all threads and dump their outstanding requests
328  for (auto t : cpuThreads) {
329  t->printAllOutstandingReqs(ss);
330  }
331 
332  for (auto t : dmaThreads) {
333  t->printAllOutstandingReqs(ss);
334  }
335 
336  for (auto t : wfs) {
337  t->printAllOutstandingReqs(ss);
338  }
339 
340  // dump error log into a file
341  assert(logFile);
342  ccprintf(*(logFile->stream()), "%s", ss.str());
343  logFile->stream()->flush();
344 
345  sentExitSignal = true;
346  // terminate the simulation
347  panic("GPU Ruby Tester: Failed!\n");
348  }
349 }
350 
351 bool
353 {
354  // get the requesting thread from the original sender state
355  ProtocolTester::SenderState* senderState =
356  safe_cast<ProtocolTester::SenderState*>(pkt->senderState);
357  TesterThread *th = senderState->th;
358 
359  th->hitCallback(pkt);
360 
361  return true;
362 }
363 
364 } // namespace gem5
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:252
gem5::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:126
gem5::ProtocolTester::dmaThreads
std::vector< DmaThread * > dmaThreads
Definition: protocol_tester.hh:179
gem5::ProtocolTester::sentExitSignal
bool sentExitSignal
Definition: protocol_tester.hh:199
warn
#define warn(...)
Definition: logging.hh:245
system.hh
gem5::ProtocolTester::numCusPerScalar
int numCusPerScalar
Definition: protocol_tester.hh:155
gem5::ProtocolTester::nextEpisodeId
int nextEpisodeId
Definition: protocol_tester.hh:192
gem5::ProtocolTester::ProtocolTester
ProtocolTester(const Params &p)
Definition: protocol_tester.cc:53
gem5::TesterThread::hitCallback
virtual void hitCallback(PacketPtr pkt)=0
gem5::ProtocolTester::cuTokenPorts
std::vector< GMTokenPort * > cuTokenPorts
Definition: protocol_tester.hh:176
gem5::ProtocolTester::numAtomicLocs
int numAtomicLocs
Definition: protocol_tester.hh:160
gem5::AddressManager
Definition: address_manager.hh:122
gem5::ProtocolTester::debugTester
bool debugTester
Definition: protocol_tester.hh:167
gem5::ProtocolTester::cuTokenManagers
std::vector< TokenManager * > cuTokenManagers
Definition: protocol_tester.hh:175
gem5::TokenManager
Definition: token_port.hh:132
gem5::ProtocolTester::numCus
int numCus
Definition: protocol_tester.hh:190
gem5::ProtocolTester::dmaPorts
std::vector< RequestPort * > dmaPorts
Definition: protocol_tester.hh:171
gem5::ProtocolTester::cpuPorts
std::vector< RequestPort * > cpuPorts
Definition: protocol_tester.hh:170
gem5::simout
OutputDirectory simout
Definition: output.cc:62
gem5::ProtocolTester::cuSqcPorts
std::vector< RequestPort * > cuSqcPorts
Definition: protocol_tester.hh:173
gem5::ProtocolTester::numScalarPorts
int numScalarPorts
Definition: protocol_tester.hh:152
gem5::ProtocolTester::numCpuPorts
int numCpuPorts
Definition: protocol_tester.hh:148
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:1003
gem5::ProtocolTester::numCusPerSqc
int numCusPerSqc
Definition: protocol_tester.hh:154
gem5::OutputDirectory::create
OutputStream * create(const std::string &name, bool binary=false, bool no_gz=false)
Creates a file in this directory (optionally compressed).
Definition: output.cc:210
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::ProtocolTester::maxNumEpisodes
int maxNumEpisodes
Definition: protocol_tester.hh:165
gem5::ProtocolTester::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: protocol_tester.cc:199
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
gem5::TesterThread
Definition: tester_thread.hh:51
gem5::ProtocolTester::SeqPort
Definition: protocol_tester.hh:74
gem5::ProtocolTester::numDmas
int numDmas
Definition: protocol_tester.hh:189
sim_exit.hh
request.hh
gem5::ccprintf
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
gem5::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
dma_thread.hh
gem5::ProtocolTester::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: protocol_tester.cc:244
gem5::ProtocolTester::logFile
OutputStream * logFile
Definition: protocol_tester.hh:201
gem5::OutputStream::stream
std::ostream * stream() const
Get the output underlying output stream.
Definition: output.hh:62
gem5::OutputDirectory::close
void close(OutputStream *file)
Closes an output file and free the corresponding OutputFile.
Definition: output.cc:147
gem5::ProtocolTester::cpuThreads
std::vector< CpuThread * > cpuThreads
Definition: protocol_tester.hh:178
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
gem5::ProtocolTester::numTokenPorts
int numTokenPorts
Definition: protocol_tester.hh:153
gem5::ProtocolTester::SenderState
Definition: protocol_tester.hh:102
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::ProtocolTester::numSqcPorts
int numSqcPorts
Definition: protocol_tester.hh:151
gem5::ProtocolTester::cuScalarPorts
std::vector< RequestPort * > cuScalarPorts
Definition: protocol_tester.hh:174
tester_thread.hh
gem5::ProtocolTester::numDmaPorts
int numDmaPorts
Definition: protocol_tester.hh:149
gem5::ProtocolTester::numWisPerWf
int numWisPerWf
Definition: protocol_tester.hh:157
gem5::ProtocolTester::SenderState::th
TesterThread * th
Definition: protocol_tester.hh:104
gem5::ProtocolTester::checkExit
bool checkExit()
Definition: protocol_tester.cc:284
gem5::ProtocolTester::numCuTokens
int numCuTokens
Definition: protocol_tester.hh:158
ss
std::stringstream ss
Definition: trace.test.cc:45
cpu_thread.hh
gem5::ProtocolTester::dumpErrorLog
void dumpErrorLog(std::stringstream &ss)
Definition: protocol_tester.cc:324
gem5::ArmISA::t
Bitfield< 5 > t
Definition: misc_types.hh:70
gpu_wavefront.hh
gem5::ProtocolTester::checkDRF
bool checkDRF(Location atomic_loc, Location loc, bool isStore) const
Definition: protocol_tester.cc:299
gem5::ProtocolTester::numWfsPerCu
int numWfsPerCu
Definition: protocol_tester.hh:156
gem5::Packet::senderState
SenderState * senderState
This packet's sender state.
Definition: packet.hh:534
gem5::ClockedObject
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Definition: clocked_object.hh:234
gem5::ProtocolTester::numNormalLocsPerAtomic
int numNormalLocsPerAtomic
Definition: protocol_tester.hh:161
gem5::ProtocolTester::GMTokenPort
Definition: protocol_tester.hh:88
gem5::ProtocolTester::Params
ProtocolTesterParams Params
Definition: protocol_tester.hh:116
inform
#define inform(...)
Definition: logging.hh:246
gem5::Port
Ports are used to interface objects to each other.
Definition: port.hh:61
protocol_tester.hh
gem5::ProtocolTester::numVectorPorts
int numVectorPorts
Definition: protocol_tester.hh:150
gem5::ProtocolTester::SeqPort::recvTimingResp
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition: protocol_tester.cc:352
gem5::ProtocolTester::Location
AddressManager::Location Location
Definition: protocol_tester.hh:120
gem5::ProtocolTester::numCpus
int numCpus
Definition: protocol_tester.hh:188
gem5::ProtocolTester::episodeLength
int episodeLength
Definition: protocol_tester.hh:163
gem5::ProtocolTester::~ProtocolTester
~ProtocolTester()
Definition: protocol_tester.cc:180
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::ProtocolTester::actionCount
int actionCount
Definition: protocol_tester.hh:196
gem5::ProtocolTester::addrManager
AddressManager * addrManager
Definition: protocol_tester.hh:185
gem5::ProtocolTester::cuVectorPorts
std::vector< RequestPort * > cuVectorPorts
Definition: protocol_tester.hh:172
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
gem5::ProtocolTester::wfs
std::vector< GpuWavefront * > wfs
Definition: protocol_tester.hh:180

Generated on Tue Sep 21 2021 12:25:09 for gem5 by doxygen 1.8.17