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

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