process.hh revision 13072:f2b83208ab54
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#ifndef __SYSTEMC_CORE_PROCESS_HH__
31#define __SYSTEMC_CORE_PROCESS_HH__
32
33#include <functional>
34#include <memory>
35#include <vector>
36
37#include "base/fiber.hh"
38#include "sim/eventq.hh"
39#include "systemc/core/bindinfo.hh"
40#include "systemc/core/list.hh"
41#include "systemc/core/object.hh"
42#include "systemc/core/sched_event.hh"
43#include "systemc/ext/core/sc_event.hh"
44#include "systemc/ext/core/sc_export.hh"
45#include "systemc/ext/core/sc_interface.hh"
46#include "systemc/ext/core/sc_module.hh"
47#include "systemc/ext/core/sc_port.hh"
48#include "systemc/ext/core/sc_process_handle.hh"
49#include "systemc/ext/utils/sc_report.hh"
50
51namespace sc_gem5
52{
53
54class Sensitivity
55{
56  protected:
57    Process *process;
58
59  public:
60    Sensitivity(Process *p) : process(p) {}
61    virtual ~Sensitivity() {}
62
63    virtual void notifyWork(Event *e);
64    void notify(Event *e);
65    void notify() { notify(nullptr); }
66
67    const std::string name();
68};
69
70class SensitivityTimeout : virtual public Sensitivity
71{
72  private:
73    void timeout();
74    ScEvent timeoutEvent;
75
76  public:
77    SensitivityTimeout(Process *p, ::sc_core::sc_time t);
78    ~SensitivityTimeout();
79};
80
81class SensitivityEvent : virtual public Sensitivity
82{
83  private:
84    const ::sc_core::sc_event *event;
85
86  public:
87    SensitivityEvent(Process *p, const ::sc_core::sc_event *e);
88    ~SensitivityEvent();
89};
90
91//XXX This sensitivity can't be reused. To reset it, it has to be deleted and
92//recreated. That works for dynamic sensitivities, but not for static.
93//Fortunately processes can't be statically sensitive to sc_event_and_lists.
94class SensitivityEventAndList : virtual public Sensitivity
95{
96  private:
97    const ::sc_core::sc_event_and_list *list;
98    int count;
99
100  public:
101    SensitivityEventAndList(
102            Process *p, const ::sc_core::sc_event_and_list *list);
103    ~SensitivityEventAndList();
104
105    void notifyWork(Event *e) override;
106};
107
108class SensitivityEventOrList : virtual public Sensitivity
109{
110  private:
111    const ::sc_core::sc_event_or_list *list;
112
113  public:
114    SensitivityEventOrList(
115            Process *p, const ::sc_core::sc_event_or_list *list);
116    ~SensitivityEventOrList();
117};
118
119// Combined sensitivities. These trigger when any of their parts do.
120
121class SensitivityTimeoutAndEvent :
122    public SensitivityTimeout, public SensitivityEvent
123{
124  public:
125    SensitivityTimeoutAndEvent(
126            Process *p, ::sc_core::sc_time t, const ::sc_core::sc_event *e) :
127        Sensitivity(p), SensitivityTimeout(p, t), SensitivityEvent(p, e)
128    {}
129};
130
131class SensitivityTimeoutAndEventAndList :
132    public SensitivityTimeout, public SensitivityEventAndList
133{
134  public:
135    SensitivityTimeoutAndEventAndList(
136            Process *p, ::sc_core::sc_time t,
137            const ::sc_core::sc_event_and_list *eal) :
138        Sensitivity(p), SensitivityTimeout(p, t),
139        SensitivityEventAndList(p, eal)
140    {}
141};
142
143class SensitivityTimeoutAndEventOrList :
144    public SensitivityTimeout, public SensitivityEventOrList
145{
146  public:
147    SensitivityTimeoutAndEventOrList(
148            Process *p, ::sc_core::sc_time t,
149            const ::sc_core::sc_event_or_list *eol) :
150        Sensitivity(p), SensitivityTimeout(p, t),
151        SensitivityEventOrList(p, eol)
152    {}
153};
154
155typedef std::vector<Sensitivity *> Sensitivities;
156
157
158/*
159 * Pending sensitivities. These are records of sensitivities to install later,
160 * once all the information to configure them is available.
161 */
162
163class PendingSensitivity
164{
165  protected:
166    Process *process;
167
168  public:
169    virtual void finalize(Sensitivities &s) = 0;
170    PendingSensitivity(Process *p) : process(p) {}
171    virtual ~PendingSensitivity() {}
172};
173
174class PendingSensitivityEvent : public PendingSensitivity
175{
176  private:
177    const sc_core::sc_event *event;
178
179  public:
180    PendingSensitivityEvent(Process *p, const sc_core::sc_event *e) :
181        PendingSensitivity(p), event(e) {}
182
183    void
184    finalize(Sensitivities &s) override
185    {
186        s.push_back(new SensitivityEvent(process, event));
187    }
188};
189
190class PendingSensitivityInterface : public PendingSensitivity
191{
192  private:
193    const sc_core::sc_interface *interface;
194
195  public:
196    PendingSensitivityInterface(Process *p, const sc_core::sc_interface *i) :
197        PendingSensitivity(p), interface(i)
198    {}
199
200    void
201    finalize(Sensitivities &s) override
202    {
203        s.push_back(new SensitivityEvent(process,
204                                         &interface->default_event()));
205    }
206};
207
208class PendingSensitivityPort : public PendingSensitivity
209{
210  private:
211    const sc_core::sc_port_base *port;
212
213  public:
214    PendingSensitivityPort(Process *p, const sc_core::sc_port_base *pb) :
215        PendingSensitivity(p), port(pb)
216    {}
217
218    void
219    finalize(Sensitivities &s) override
220    {
221        for (int i = 0; i < port->size(); i++) {
222            const ::sc_core::sc_event *e =
223                &port->_gem5Interface(i)->default_event();
224            s.push_back(new SensitivityEvent(process, e));
225        }
226    }
227};
228
229class PendingSensitivityExport : public PendingSensitivity
230{
231  private:
232    const sc_core::sc_export_base *exp;
233
234  public:
235    PendingSensitivityExport(Process *p, const sc_core::sc_export_base *exp) :
236        PendingSensitivity(p), exp(exp)
237    {}
238
239    void
240    finalize(Sensitivities &s) override
241    {
242        s.push_back(new SensitivityEvent(process,
243                    &exp->get_interface()->default_event()));
244    }
245};
246
247class PendingSensitivityFinder : public PendingSensitivity
248{
249  private:
250    const sc_core::sc_event_finder *finder;
251
252  public:
253    PendingSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) :
254        PendingSensitivity(p), finder(f)
255    {}
256
257    void
258    finalize(Sensitivities &s) override
259    {
260        s.push_back(new SensitivityEvent(process, &finder->find_event()));
261    }
262};
263
264typedef std::vector<PendingSensitivity *> PendingSensitivities;
265
266
267class Process : public ::sc_core::sc_object, public ListNode
268{
269  public:
270    virtual ::sc_core::sc_curr_proc_kind procKind() const = 0;
271    bool needsStart() const { return _needsStart; }
272    bool dynamic() const { return _dynamic; }
273    bool isUnwinding() const { return _isUnwinding; }
274    void isUnwinding(bool v) { _isUnwinding = v; }
275    bool terminated() const { return _terminated; }
276
277    void forEachKid(const std::function<void(Process *)> &work);
278
279    bool suspended() const { return _suspended; }
280    bool disabled() const { return _disabled; }
281
282    void suspend(bool inc_kids);
283    void resume(bool inc_kids);
284    void disable(bool inc_kids);
285    void enable(bool inc_kids);
286
287    void kill(bool inc_kids);
288    void reset(bool inc_kids);
289    virtual void throw_it(ExceptionWrapperBase &exc, bool inc_kids);
290
291    void injectException(ExceptionWrapperBase &exc);
292    ExceptionWrapperBase *excWrapper;
293
294    void syncResetOn(bool inc_kids);
295    void syncResetOff(bool inc_kids);
296
297    void incref() { refCount++; }
298    void decref() { refCount--; }
299
300    const ::sc_core::sc_event &resetEvent() { return _resetEvent; }
301    const ::sc_core::sc_event &terminatedEvent() { return _terminatedEvent; }
302
303    // This should only be called before initialization.
304    void dontInitialize();
305
306    void setStackSize(size_t size) { stackSize = size; }
307
308    void finalize();
309
310    void run();
311
312    void addStatic(PendingSensitivity *);
313    void setDynamic(Sensitivity *);
314
315    void satisfySensitivity(Sensitivity *);
316
317    void ready();
318
319    virtual Fiber *fiber() { return Fiber::primaryFiber(); }
320
321    static Process *newest() { return _newest; }
322
323    void lastReport(::sc_core::sc_report *report);
324    ::sc_core::sc_report *lastReport() const;
325
326  protected:
327    Process(const char *name, ProcessFuncWrapper *func, bool _dynamic);
328
329    static Process *_newest;
330
331    virtual ~Process()
332    {
333        popListNode();
334        delete func;
335        for (auto s: staticSensitivities)
336            delete s;
337    }
338
339    ::sc_core::sc_event _resetEvent;
340    ::sc_core::sc_event _terminatedEvent;
341
342    ProcessFuncWrapper *func;
343    sc_core::sc_curr_proc_kind _procKind;
344    bool _needsStart;
345    bool _dynamic;
346    bool _isUnwinding;
347    bool _terminated;
348
349    void terminate();
350
351    bool _suspended;
352    bool _suspendedReady;
353    bool _disabled;
354
355    bool _syncReset;
356
357    int refCount;
358
359    size_t stackSize;
360
361    Sensitivities staticSensitivities;
362    PendingSensitivities pendingStaticSensitivities;
363
364    Sensitivity *dynamicSensitivity;
365
366    std::unique_ptr<::sc_core::sc_report> _lastReport;
367};
368
369inline void
370Sensitivity::notifyWork(Event *e)
371{
372    process->satisfySensitivity(this);
373}
374
375inline void
376Sensitivity::notify(Event *e)
377{
378    if (!process->disabled())
379        notifyWork(e);
380}
381
382inline const std::string
383Sensitivity::name()
384{
385    return std::string(process->name()) + ".timeout";
386}
387
388} // namespace sc_gem5
389
390#endif  //__SYSTEMC_CORE_PROCESS_HH__
391