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_SENSITIVITY_HH__
31#define __SYSTEMC_CORE_SENSITIVITY_HH__
32
33#include <set>
34#include <vector>
35
36#include "sim/eventq.hh"
37#include "systemc/core/sched_event.hh"
38#include "systemc/ext/core/sc_module.hh"
39#include "systemc/ext/core/sc_port.hh"
40
41namespace sc_core
42{
43
44class sc_event;
45class sc_event_and_list;
46class sc_event_or_list;
47class sc_event_finder;
48class sc_export_base;
49class sc_interface;
50class sc_port_base;
51
52} // namespace sc_core
53
54namespace sc_gem5
55{
56
57class Process;
58class Event;
59
60/*
61 * Common sensitivity interface.
62 */
63
64class Sensitivity
65{
66  protected:
67    Process *process;
68
69    Sensitivity(Process *p) : process(p) {}
70    virtual ~Sensitivity() {}
71
72    virtual void addToEvent(const ::sc_core::sc_event *e) = 0;
73    virtual void delFromEvent(const ::sc_core::sc_event *e) = 0;
74
75  public:
76    virtual void clear() = 0;
77
78    void satisfy();
79    virtual bool notifyWork(Event *e);
80    bool notify(Event *e);
81
82    enum Category
83    {
84        Static,
85        Dynamic
86    };
87
88    virtual Category category() = 0;
89
90    bool ofMethod();
91};
92
93
94/*
95 * Dynamic vs. static sensitivity.
96 */
97
98class DynamicSensitivity : virtual public Sensitivity
99{
100  protected:
101    DynamicSensitivity(Process *p) : Sensitivity(p) {}
102
103    void addToEvent(const ::sc_core::sc_event *e) override;
104    void delFromEvent(const ::sc_core::sc_event *e) override;
105
106  public:
107    Category category() override { return Dynamic; }
108};
109
110typedef std::vector<DynamicSensitivity *> DynamicSensitivities;
111
112
113class StaticSensitivity : virtual public Sensitivity
114{
115  protected:
116    StaticSensitivity(Process *p) : Sensitivity(p) {}
117
118    void addToEvent(const ::sc_core::sc_event *e) override;
119    void delFromEvent(const ::sc_core::sc_event *e) override;
120
121  public:
122    Category category() override { return Static; }
123};
124
125typedef std::vector<StaticSensitivity *> StaticSensitivities;
126
127
128/*
129 * Sensitivity to an event or events, which can be static or dynamic.
130 */
131
132class SensitivityEvent : virtual public Sensitivity
133{
134  protected:
135    const ::sc_core::sc_event *event;
136
137    SensitivityEvent(Process *p, const ::sc_core::sc_event *e=nullptr) :
138        Sensitivity(p), event(e)
139    {}
140
141  public:
142    void clear() override { delFromEvent(event); }
143};
144
145class SensitivityEvents : virtual public Sensitivity
146{
147  protected:
148    std::set<const ::sc_core::sc_event *> events;
149
150    SensitivityEvents(Process *p) : Sensitivity(p) {}
151    SensitivityEvents(
152            Process *p, const std::set<const ::sc_core::sc_event *> &s) :
153        Sensitivity(p), events(s)
154    {}
155
156  public:
157    void
158    clear() override
159    {
160        for (auto event: events)
161            delFromEvent(event);
162    }
163
164    void
165    addEvent(const ::sc_core::sc_event *event)
166    {
167        events.insert(event);
168        addToEvent(event);
169    }
170};
171
172
173/*
174 * Static sensitivities.
175 */
176
177void newStaticSensitivityEvent(Process *p, const sc_core::sc_event *e);
178void newStaticSensitivityInterface(Process *p, const sc_core::sc_interface *i);
179void newStaticSensitivityPort(Process *p, const sc_core::sc_port_base *pb);
180void newStaticSensitivityExport(
181        Process *p, const sc_core::sc_export_base *exp);
182void newStaticSensitivityFinder(
183        Process *p, const sc_core::sc_event_finder *f);
184
185
186class StaticSensitivityEvent :
187    public StaticSensitivity, public SensitivityEvent
188{
189    friend void newStaticSensitivityEvent(
190            Process *p, const sc_core::sc_event *e);
191
192  protected:
193    StaticSensitivityEvent(Process *p, const sc_core::sc_event *e) :
194        Sensitivity(p), StaticSensitivity(p), SensitivityEvent(p, e)
195    {}
196};
197
198class StaticSensitivityInterface :
199    public StaticSensitivity, public SensitivityEvent
200{
201    friend void newStaticSensitivityInterface(
202            Process *p, const sc_core::sc_interface *i);
203  protected:
204    StaticSensitivityInterface(Process *p, const sc_core::sc_interface *i);
205};
206
207class StaticSensitivityPort :
208    public StaticSensitivity, public SensitivityEvents
209{
210    friend void newStaticSensitivityPort(
211            Process *p, const sc_core::sc_port_base *pb);
212
213  protected:
214    StaticSensitivityPort(Process *p) :
215        Sensitivity(p), StaticSensitivity(p), SensitivityEvents(p)
216    {}
217};
218
219class StaticSensitivityExport :
220    public StaticSensitivity, public SensitivityEvent
221{
222  private:
223    friend void newStaticSensitivityExport(
224            Process *p, const sc_core::sc_export_base *exp);
225
226    StaticSensitivityExport(Process *p, const sc_core::sc_export_base *exp);
227};
228
229
230class StaticSensitivityFinder :
231    public StaticSensitivity, public SensitivityEvents
232{
233  private:
234    const sc_core::sc_event_finder *finder;
235
236    friend void newStaticSensitivityFinder(
237            Process *p, const sc_core::sc_event_finder *f);
238
239    StaticSensitivityFinder(Process *p, const sc_core::sc_event_finder *f) :
240        Sensitivity(p), StaticSensitivity(p), SensitivityEvents(p), finder(f)
241    {}
242
243  public:
244    const ::sc_core::sc_event &find(::sc_core::sc_interface *i);
245};
246
247
248/*
249 * Dynamic sensitivities.
250 */
251
252void newDynamicSensitivityEvent(Process *p, const sc_core::sc_event *e);
253void newDynamicSensitivityEventOrList(
254        Process *p, const sc_core::sc_event_or_list *eol);
255void newDynamicSensitivityEventAndList(
256        Process *p, const sc_core::sc_event_and_list *eal);
257
258class DynamicSensitivityEvent :
259    public DynamicSensitivity, public SensitivityEvent
260{
261  private:
262    friend void newDynamicSensitivityEvent(
263            Process *p, const sc_core::sc_event *e);
264
265    DynamicSensitivityEvent(Process *p, const sc_core::sc_event *e) :
266        Sensitivity(p), DynamicSensitivity(p), SensitivityEvent(p, e)
267    {}
268};
269
270class DynamicSensitivityEventOrList :
271    public DynamicSensitivity, public SensitivityEvents
272{
273  private:
274    friend void newDynamicSensitivityEventOrList(
275            Process *p, const sc_core::sc_event_or_list *eol);
276
277    DynamicSensitivityEventOrList(
278            Process *p, const sc_core::sc_event_or_list *eol);
279
280    bool notifyWork(Event *e) override;
281};
282
283//XXX This sensitivity can't be reused. To reset it, it has to be deleted and
284//recreated. That works for dynamic sensitivities, but not for static.
285//Fortunately processes can't be statically sensitive to sc_event_and_lists.
286class DynamicSensitivityEventAndList :
287    public DynamicSensitivity, public SensitivityEvents
288{
289  private:
290    friend void newDynamicSensitivityEventAndList(
291            Process *p, const sc_core::sc_event_and_list *eal);
292
293    DynamicSensitivityEventAndList(
294            Process *p, const sc_core::sc_event_and_list *eal);
295
296    bool notifyWork(Event *e) override;
297};
298
299} // namespace sc_gem5
300
301#endif  //__SYSTEMC_CORE_SENSITIVITY_HH__
302