gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
process.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2018 Google, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met: redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer;
8  * redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution;
11  * neither the name of the copyright holders nor the names of its
12  * contributors may be used to endorse or promote products derived from
13  * this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * Authors: Gabe Black
28  */
29 
30 #include "systemc/core/process.hh"
31 
32 #include "systemc/core/event.hh"
33 #include "systemc/core/port.hh"
40 
41 namespace sc_gem5
42 {
43 
45 {
46  public:
48 };
49 
51 {
52  public:
54 };
55 
56 template <typename T>
58 {
59  public:
60  T t;
61  void throw_it() override { throw t; }
62 };
63 
66 
67 
68 void
69 Process::forEachKid(const std::function<void(Process *)> &work)
70 {
71  for (auto &kid: get_child_objects()) {
72  Process *p_kid = dynamic_cast<Process *>(kid);
73  if (p_kid)
74  work(p_kid);
75  }
76 }
77 
78 void
79 Process::suspend(bool inc_kids)
80 {
81  if (inc_kids)
82  forEachKid([](Process *p) { p->suspend(true); });
83 
84  if (!_suspended && !_terminated) {
85  _suspended = true;
86  _suspendedReady = scheduler.suspend(this);
87 
88  if (procKind() != ::sc_core::SC_METHOD_PROC_ &&
89  scheduler.current() == this) {
90  // This isn't in the spec, but Accellera says that a thread that
91  // self suspends should be marked ready immediately when it's
92  // resumed.
93  _suspendedReady = true;
94  scheduler.yield();
95  }
96  }
97 }
98 
99 void
100 Process::resume(bool inc_kids)
101 {
102  if (inc_kids)
103  forEachKid([](Process *p) { p->resume(true); });
104 
105  if (_suspended && !_terminated) {
106  _suspended = false;
107  if (_suspendedReady)
108  scheduler.resume(this);
109  _suspendedReady = false;
110  }
111 }
112 
113 void
114 Process::disable(bool inc_kids)
115 {
116  if (inc_kids)
117  forEachKid([](Process *p) { p->disable(true); });
118 
120  timeoutEvent.scheduled()) {
121  std::string message("attempt to disable a thread with timeout wait: ");
122  message += name();
124  message.c_str());
125  }
126 
127  if (!_terminated)
128  _disabled = true;
129 }
130 
131 void
132 Process::enable(bool inc_kids)
133 {
134 
135  if (inc_kids)
136  forEachKid([](Process *p) { p->enable(true); });
137 
138  if (!_terminated)
139  _disabled = false;
140 }
141 
142 void
143 Process::kill(bool inc_kids)
144 {
147  name());
148  }
149 
150  // Propogate the kill to our children no matter what happens to us.
151  if (inc_kids)
152  forEachKid([](Process *p) { p->kill(true); });
153 
154  // If we're unwinding or terminated, ignore the kill request.
155  if (_isUnwinding || _terminated)
156  return;
157 
158  // Update our state.
159  terminate();
160  _isUnwinding = true;
161 
162  // Make sure this process isn't marked ready
163  popListNode();
164 
165  // Inject the kill exception into this process if it's started.
166  if (!_needsStart)
167  injectException(killException);
168 }
169 
170 void
171 Process::reset(bool inc_kids)
172 {
175  name());
176  }
177 
178  // Propogate the reset to our children no matter what happens to us.
179  if (inc_kids)
180  forEachKid([](Process *p) { p->reset(true); });
181 
182  // If we're already unwinding or terminated, ignore the reset request.
183  if (_isUnwinding || _terminated)
184  return;
185 
186  // Clear suspended ready since we're about to run regardless.
187  _suspendedReady = false;
188 
189  _resetEvent.notify();
190 
191  if (_needsStart) {
192  scheduler.runNow(this);
193  } else {
194  _isUnwinding = true;
195  injectException(resetException);
196  }
197 }
198 
199 void
201 {
204 
205  if (inc_kids)
206  forEachKid([&exc](Process *p) { p->throw_it(exc, true); });
207 
208  if (_needsStart || _terminated ||
209  procKind() == ::sc_core::SC_METHOD_PROC_) {
211  return;
212  }
213 
214  injectException(exc);
215 }
216 
217 void
219 {
220  excWrapper = &exc;
221  scheduler.runNow(this);
222 };
223 
224 void
225 Process::syncResetOn(bool inc_kids)
226 {
227  if (inc_kids)
228  forEachKid([](Process *p) { p->syncResetOn(true); });
229 
230  _syncReset = true;
231 }
232 
233 void
234 Process::syncResetOff(bool inc_kids)
235 {
236  if (inc_kids)
237  forEachKid([](Process *p) { p->syncResetOff(true); });
238 
239  _syncReset = false;
240 }
241 
242 void
243 Process::signalReset(bool set, bool sync)
244 {
245  if (set) {
246  waitCount(0);
247  if (sync) {
248  syncResetCount++;
249  } else {
250  asyncResetCount++;
251  cancelTimeout();
252  clearDynamic();
253  scheduler.runNext(this);
254  }
255  } else {
256  if (sync)
257  syncResetCount--;
258  else
259  asyncResetCount--;
260  }
261 }
262 
263 void
265 {
266  bool reset;
267  do {
268  reset = false;
269  try {
270  func->call();
271  } catch(ScHalt) {
272  std::cout << "Terminating process " << name() << std::endl;
273  } catch(const ::sc_core::sc_unwind_exception &exc) {
274  reset = exc.is_reset();
275  _isUnwinding = false;
276  } catch (...) {
277  throw;
278  }
279  } while (reset);
280  needsStart(true);
281 }
282 
283 void
285 {
286  staticSensitivities.push_back(s);
287 }
288 
289 void
291 {
292  if (dynamicSensitivity) {
293  dynamicSensitivity->clear();
294  delete dynamicSensitivity;
295  }
296  dynamicSensitivity = s;
297 }
298 
299 void
301 {
302  resets.push_back(reset);
303 }
304 
305 void
307 {
308  if (timeoutEvent.scheduled())
309  scheduler.deschedule(&timeoutEvent);
310 }
311 
312 void
314 {
315  cancelTimeout();
316  scheduler.schedule(&timeoutEvent, t);
317 }
318 
319 void
321 {
322  // A process is considered timed_out only if it was also waiting for an
323  // event but got a timeout instead.
324  _timedOut = (dynamicSensitivity != nullptr);
325 
326  setDynamic(nullptr);
327  if (disabled())
328  return;
329 
330  ready();
331 }
332 
333 void
335 {
336  if (_waitCount) {
337  _waitCount--;
338  return;
339  }
340 
341  // If there's a dynamic sensitivity and this wasn't it, ignore.
342  if ((dynamicSensitivity || timeoutEvent.scheduled()) &&
343  dynamicSensitivity != s) {
344  return;
345  }
346 
347  _timedOut = false;
348  // This sensitivity should already be cleared by this point, or the event
349  // which triggered it will take care of it.
350  delete dynamicSensitivity;
351  dynamicSensitivity = nullptr;
352  cancelTimeout();
353  ready();
354 }
355 
356 void
358 {
359  if (disabled())
360  return;
361  if (suspended())
362  _suspendedReady = true;
363  else if (!scheduled())
364  scheduler.ready(this);
365 }
366 
367 void
369 {
370  if (report) {
371  _lastReport = std::unique_ptr<::sc_core::sc_report>(
372  new ::sc_core::sc_report(*report));
373  } else {
374  _lastReport = nullptr;
375  }
376 }
377 
378 ::sc_core::sc_report *Process::lastReport() const { return _lastReport.get(); }
379 
380 Process::Process(const char *name, ProcessFuncWrapper *func, bool internal) :
381  ::sc_core::sc_process_b(name), excWrapper(nullptr),
382  timeoutEvent([this]() { this->timeout(); }),
383  func(func), _internal(internal), _timedOut(false), _dontInitialize(false),
384  _needsStart(true), _isUnwinding(false), _terminated(false),
385  _scheduled(false), _suspended(false), _disabled(false),
388  dynamicSensitivity(nullptr)
389 {
390  _dynamic =
393  _newest = this;
394 }
395 
396 void
398 {
399  _terminated = true;
400  _suspendedReady = false;
401  _suspended = false;
402  _syncReset = false;
403  clearDynamic();
404  cancelTimeout();
405  for (auto s: staticSensitivities) {
406  s->clear();
407  delete s;
408  }
409  staticSensitivities.clear();
410 
412 
413  for (auto jw: joinWaiters)
414  jw->signal();
415  joinWaiters.clear();
416 }
417 
419 
420 void
422 {
423  p->throw_it(exc, inc_kids);
424 }
425 
426 void
427 newReset(const sc_core::sc_port_base *pb, Process *p, bool s, bool v)
428 {
429  Port *port = Port::fromPort(pb);
430  port->addReset(new Reset(p, s, v));
431 }
432 
433 void
435 {
436  Reset *reset = new Reset(p, s, v);
437  if (!reset->install(sig))
438  delete reset;
439 }
440 
441 } // namespace sc_gem5
const char SC_ID_THROW_IT_IGNORED_[]
Definition: messages.cc:130
bool suspend(Process *p)
Definition: scheduler.cc:238
void runNext(Process *p)
Definition: scheduler.hh:217
void addStatic(StaticSensitivity *)
Definition: process.cc:284
Bitfield< 28 > v
const std::string & name()
Definition: trace.cc:54
void setTimeout(::sc_core::sc_time t)
Definition: process.cc:313
std::vector<::sc_core::sc_join * > joinWaiters
Definition: process.hh:203
BuiltinExceptionWrapper< UnwindExceptionReset > resetException
Definition: process.cc:64
void satisfySensitivity(Sensitivity *)
Definition: process.cc:334
size_t stackSize
Definition: process.hh:195
void addReset(Reset *reset)
Definition: port.cc:87
void cancelTimeout()
Definition: process.cc:306
void forEachKid(const std::function< void(Process *)> &work)
Definition: process.cc:69
void signalReset(bool set, bool sync)
Definition: process.cc:243
void reset()
Definition: statistics.cc:570
void resume(Process *p)
Definition: scheduler.cc:219
void newReset(const sc_core::sc_port_base *pb, Process *p, bool s, bool v)
Definition: process.cc:427
#define SC_REPORT_WARNING(msg_type, msg)
DynamicSensitivity * dynamicSensitivity
Definition: process.hh:198
void enable(bool inc_kids)
Definition: process.cc:132
const char SC_ID_PROCESS_CONTROL_CORNER_CASE_[]
Definition: messages.cc:137
void kill(bool inc_kids)
Definition: process.cc:143
void addReset(Reset *)
Definition: process.cc:300
Bitfield< 4 > s
void syncResetOn(bool inc_kids)
Definition: process.cc:225
void deschedule(ScEvent *event)
Definition: scheduler.hh:265
const char SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_[]
Definition: messages.cc:160
Process * current()
Definition: scheduler.hh:172
void injectException(ExceptionWrapperBase &exc)
Definition: process.cc:218
void syncResetOff(bool inc_kids)
Definition: process.cc:234
static const size_t DefaultStackSize
Definition: fiber.hh:67
void disable(bool inc_kids)
Definition: process.cc:114
void resume(bool inc_kids)
Definition: process.cc:100
void runNow(Process *p)
Definition: scheduler.hh:200
void throw_it(ExceptionWrapperBase &exc, bool inc_kids)
Definition: process.cc:200
ProcessFuncWrapper * func
Definition: process.hh:165
void throw_it_wrapper(Process *p, ExceptionWrapperBase &exc, bool inc_kids)
Definition: process.cc:421
Scheduler scheduler
Definition: scheduler.cc:491
void suspend(bool inc_kids)
Definition: process.cc:79
InternalScEvent _terminatedEvent
Definition: process.hh:163
static Port * fromPort(const ::sc_core::sc_port_base *pb)
Definition: port.hh:123
bool _suspendedReady
Definition: process.hh:183
sc_status sc_get_status()
Definition: sc_main.cc:175
void ready(Process *p)
Definition: scheduler.cc:202
BuiltinExceptionWrapper< UnwindExceptionKill > killException
Definition: process.cc:65
void terminate()
Definition: process.cc:397
void clearDynamic()
Definition: process.hh:112
void reset(bool inc_kids)
Definition: process.cc:171
StaticSensitivities staticSensitivities
Definition: process.hh:197
#define SC_REPORT_ERROR(msg_type, msg)
static Process * _newest
Definition: process.hh:149
bool sc_allow_process_control_corners
Process(const char *name, ProcessFuncWrapper *func, bool internal=false)
Definition: process.cc:380
void setDynamic(DynamicSensitivity *)
Definition: process.cc:290
Bitfield< 5 > t
void timeout()
Definition: process.cc:320
const char SC_ID_THROW_IT_WHILE_NOT_RUNNING_[]
Definition: messages.cc:165
void schedule(ScEvent *event, const ::sc_core::sc_time &delay)
Definition: scheduler.hh:240
Bitfield< 0 > p
bool install(const sc_core::sc_signal_in_if< bool > *s)
Definition: process.hh:216
bool _dontInitialize
Definition: process.hh:172
::sc_core::sc_report * lastReport() const
Definition: process.cc:378
const char SC_ID_RESET_PROCESS_WHILE_NOT_RUNNING_[]
Definition: messages.cc:162

Generated on Fri Feb 28 2020 16:26:56 for gem5 by doxygen 1.8.13