gem5  v22.1.0.0
episode.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 <fstream>
35 #include <unordered_set>
36 
39 
40 namespace gem5
41 {
42 
43 Episode::Episode(ProtocolTester* _tester, TesterThread* _thread, int num_loads,
44  int num_stores)
45  : tester(_tester),
46  thread(_thread),
47  numLoads(num_loads),
48  numStores(num_stores),
49  nextActionIdx(0)
50 {
51  assert(tester && thread);
52 
55  assert(numLanes > 0);
56 
58  assert(addrManager);
59 
61  // generate a sequence of actions
62  initActions();
63  isActive = true;
64 
65  DPRINTFN("Episode %d\n", episodeId);
66 }
67 
69 {
70  for (Episode::Action* action : actions) {
71  assert(action);
72  delete action;
73  }
74 }
75 
76 const Episode::Action*
78 {
79  if (nextActionIdx < actions.size())
80  return actions[nextActionIdx];
81  else
82  return nullptr;
83 }
84 
85 void
87 {
88  assert(nextActionIdx < actions.size());
89  nextActionIdx++;
90 }
91 
92 void
94 {
95  // first, push Atomic & then Acquire action
98 
99  // second, push a number of LD/ST actions
100  int num_loads = numLoads;
101  int num_stores = numStores;
102  while ((num_loads + num_stores) > 0) {
103  switch (random() % 2) {
104  case 0: // Load
105  if (num_loads > 0) {
106  actions.push_back(new Action(Action::Type::LOAD,
107  numLanes));
108  num_loads--;
109  }
110  break;
111  case 1: // Store
112  if (num_stores > 0) {
113  actions.push_back(new Action(Action::Type::STORE,
114  numLanes));
115  num_stores--;
116  }
117  break;
118  default:
119  assert(false);
120  }
121  }
122 
123  // last, push an Release & then Atomic action
124  actions.push_back(new Action(Action::Type::RELEASE, numLanes));
125  actions.push_back(new Action(Action::Type::ATOMIC, numLanes));
126 
127  // for each lane, pick a list of locations
128  Location normal_loc;
129 
130  for (int lane = 0; lane < numLanes; ++lane) {
132 
133  // first, we select atomic loc for this lane
134  // atomic loc for this lane should not have been picked yet
136  // pick randomly an atomic location
138  assert(atomicLocs[lane] >= 0);
139 
140  // go through each action in this lane and set its location
141  for (Action* action : actions) {
142  assert(action);
143 
144  switch (action->getType()) {
146  action->setLocation(lane, atomicLocs[lane]);
147  break;
148  case Action::Type::LOAD:
149  // pick randomly a normal location
150  normal_loc = addrManager->
151  getLoadLoc(atomicLocs[lane]);
152  assert(normal_loc >= AddressManager::INVALID_LOCATION);
153 
154  if (normal_loc != AddressManager::INVALID_LOCATION) {
155  // check DRF
156  if (!tester->checkDRF(atomicLocs[lane],
157  normal_loc, false) ||
158  !this->checkDRF(atomicLocs[lane], normal_loc,
159  false, lane)) {
160  panic("TestTh %d - Data race detected. STOPPED!\n",
162  }
163  }
164 
165  action->setLocation(lane, normal_loc);
166  break;
167  case Action::Type::STORE:
168  // pick randomly a normal location
169  normal_loc = addrManager->
170  getStoreLoc(atomicLocs[lane]);
171  assert(normal_loc >= AddressManager::INVALID_LOCATION);
172 
173  if (normal_loc != AddressManager::INVALID_LOCATION) {
174  // check DRF
175  if (!tester->checkDRF(atomicLocs[lane],
176  normal_loc, true) ||
177  !this->checkDRF(atomicLocs[lane], normal_loc,
178  true, lane)) {
179  panic("TestTh %d - Data race detected. STOPPED!\n",
181  }
182  }
183 
184  action->setLocation(lane, normal_loc);
185  break;
188  // no op
189  break;
190  default:
191  panic("Invalid action type\n");
192  }
193  }
194 
196  }
197 }
198 
199 void
201 {
202  // release all locations this episode has picked and used
203  Location atomic_loc, normal_loc;
204  for (int lane = 0; lane < numLanes; ++lane) {
207 
208  std::unordered_set<Location> unique_loc_set;
209 
210  for (Action* action : actions) {
211  assert(action);
212 
213  if (action->isAtomicAction()) {
214  if (atomic_loc == AddressManager::INVALID_LOCATION) {
215  atomic_loc = action->getLocation(lane);
216  } else {
217  // both atomic ops in the same lane must be
218  // at the same location
219  assert(atomic_loc == action->getLocation(lane));
220  }
221  } else if (!action->isMemFenceAction()) {
222  assert(atomic_loc >= 0);
223  normal_loc = action->getLocation(lane);
224 
225  if (normal_loc >= 0)
226  unique_loc_set.insert(normal_loc);
227  }
228  }
229 
230  // each unique loc can be released only once
231  for (Location loc : unique_loc_set)
232  addrManager->releaseLocation(atomic_loc, loc);
233  }
234 
235  // this episode is no longer active
236  isActive = false;
237 }
238 
239 bool
240 Episode::checkDRF(Location atomic_loc, Location loc, bool isStore,
241  int max_lane) const
242 {
243  assert(atomic_loc != AddressManager::INVALID_LOCATION);
244  assert(loc != AddressManager::INVALID_LOCATION);
245  assert(max_lane <= numLanes);
246 
247  for (int lane = 0; lane < max_lane; ++lane) {
248  if (atomic_loc == atomicLocs[lane]) {
249  for (const Action* action : actions) {
250  if (!action->isAtomicAction() &&
251  !action->isMemFenceAction()) {
252  if (isStore && loc == action->getLocation(lane)) {
253  warn("ST at location %d races against thread %d\n",
254  loc, thread->getTesterThreadId());
255  return false;
256  } else if (!isStore &&
257  action->getType() == Action::Type::STORE &&
258  loc == action->getLocation(lane)) {
259  warn("LD at location %d races against thread %d\n",
260  loc, thread->getTesterThreadId());
261  return false;
262  }
263  }
264  }
265  }
266  }
267 
268  return true;
269 }
270 
271 // -------------------- Action class ----------------------------
273  : type(t),
274  numLanes(num_lanes)
275 {
276  assert(numLanes > 0);
277  locations.resize(numLanes);
279 }
280 
281 void
283 {
284  assert(lane >= 0 && lane < numLanes);
285  locations[lane] = loc;
286 }
287 
290 {
291  assert(lane >= 0 && lane < numLanes);
292  return locations[lane];
293 }
294 
295 bool
297 {
298  return (type == Type::ATOMIC);
299 }
300 
301 bool
303 {
304  return (type == Type::ACQUIRE || type == Type::RELEASE);
305 }
306 
307 const std::string
309 {
310  if (type == Type::ACQUIRE)
311  return "ACQUIRE";
312  else if (type == Type::RELEASE)
313  return "RELEASE";
314  else if (type == Type::ATOMIC)
315  return "ATOMIC";
316  else if (type == Type::LOAD)
317  return "LOAD";
318  else if (type == Type::STORE)
319  return "STORE";
320  else
321  panic("Invalid action type\n");
322 }
323 
324 } // namespace gem5
#define DPRINTFN(...)
Definition: trace.hh:214
static const int INVALID_LOCATION
void finishLocSelection(Location atomic_loc)
void releaseLocation(Location atomic_loc, Location loc)
Action(Type t, int num_lanes)
Definition: episode.cc:272
Location getLocation(int lane) const
Definition: episode.cc:289
const std::string printType() const
Definition: episode.cc:308
bool isMemFenceAction() const
Definition: episode.cc:302
bool isAtomicAction() const
Definition: episode.cc:296
void setLocation(int lane, Location loc)
Definition: episode.cc:282
LocationList locations
Definition: episode.hh:77
ActionList actions
Definition: episode.hh:110
void completeEpisode()
Definition: episode.cc:200
Episode(ProtocolTester *tester, TesterThread *thread, int num_loads, int num_stores)
Definition: episode.cc:43
TesterThread * thread
Definition: episode.hh:103
AddressManager::Location Location
Definition: episode.hh:48
bool checkDRF(Location atomic_loc, Location loc, bool isStore, int max_lane) const
Definition: episode.cc:240
bool isActive
Definition: episode.hh:116
void popAction()
Definition: episode.cc:86
int nextActionIdx
Definition: episode.hh:121
AddressManager * addrManager
Definition: episode.hh:104
const Action * peekCurAction() const
Definition: episode.cc:77
AtomicLocationList atomicLocs
Definition: episode.hh:113
void initActions()
Definition: episode.cc:93
ProtocolTester * tester
Definition: episode.hh:102
AddressManager * getAddressManager() const
bool checkDRF(Location atomic_loc, Location loc, bool isStore) const
int getNumLanes() const
int getTesterThreadId() const
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define warn(...)
Definition: logging.hh:246
Bitfield< 51 > t
Definition: pagetable.hh:56
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....

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