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_EXT_CORE_SC_EVENT_HH__
31#define __SYSTEMC_EXT_CORE_SC_EVENT_HH__
32
33#include <cassert>
34#include <set>
35#include <sstream>
36#include <vector>
37
38#include "../channel/messages.hh"
39#include "../utils/sc_report_handler.hh"
40#include "sc_port.hh"
41#include "sc_time.hh"
42
43namespace sc_gem5
44{
45
46class Event;
47class DynamicSensitivityEventAndList;
48class DynamicSensitivityEventOrList;
49class InternalScEvent;
50
51}
52
53namespace sc_core
54{
55
56class sc_event;
57class sc_event_and_expr;
58class sc_event_or_expr;
59class sc_interface;
60class sc_object;
61class sc_port_base;
62
63class sc_event_and_list
64{
65  public:
66    sc_event_and_list();
67    sc_event_and_list(const sc_event_and_list &);
68    sc_event_and_list(const sc_event &);
69    sc_event_and_list &operator = (const sc_event_and_list &);
70    ~sc_event_and_list();
71
72    int size() const;
73    void swap(sc_event_and_list &);
74
75    sc_event_and_list &operator &= (const sc_event &);
76    sc_event_and_list &operator &= (const sc_event_and_list &);
77
78    sc_event_and_expr operator & (const sc_event &) const;
79    sc_event_and_expr operator & (const sc_event_and_list &) const;
80
81  private:
82    friend class sc_event_and_expr;
83    friend class sc_gem5::DynamicSensitivityEventAndList;
84
85    explicit sc_event_and_list(bool auto_delete);
86
87    void insert(sc_event const &e);
88    void insert(sc_event_and_list const &eal);
89
90    std::set<const sc_event *> events;
91    bool autoDelete;
92    mutable unsigned busy;
93};
94
95class sc_event_or_list
96{
97  public:
98    sc_event_or_list();
99    sc_event_or_list(const sc_event_or_list &);
100    sc_event_or_list(const sc_event &);
101    sc_event_or_list& operator = (const sc_event_or_list &);
102    ~sc_event_or_list();
103
104    int size() const;
105    void swap(sc_event_or_list &);
106
107    sc_event_or_list &operator |= (const sc_event &);
108    sc_event_or_list &operator |= (const sc_event_or_list &);
109
110    sc_event_or_expr operator | (const sc_event &) const;
111    sc_event_or_expr operator | (const sc_event_or_list &) const;
112
113  private:
114    friend class sc_event_or_expr;
115    friend class sc_gem5::DynamicSensitivityEventOrList;
116
117    explicit sc_event_or_list(bool auto_delete);
118
119    void insert(sc_event const &e);
120    void insert(sc_event_or_list const &eol);
121
122    std::set<const sc_event *> events;
123    bool autoDelete;
124    mutable unsigned busy;
125};
126
127class sc_event_and_expr
128{
129  public:
130    sc_event_and_expr(sc_event_and_expr const &e);
131    operator const sc_event_and_list &() const;
132
133    void insert(sc_event const &e) const;
134    void insert(sc_event_and_list const &eal) const;
135
136    ~sc_event_and_expr();
137
138  private:
139    friend class sc_event_and_list;
140    friend class sc_event;
141
142    sc_event_and_expr();
143    mutable sc_event_and_list *list;
144};
145
146sc_event_and_expr operator & (sc_event_and_expr, sc_event const &);
147sc_event_and_expr operator & (sc_event_and_expr, sc_event_and_list const &);
148
149class sc_event_or_expr
150{
151  public:
152    sc_event_or_expr(sc_event_or_expr const &e);
153    operator const sc_event_or_list &() const;
154
155    void insert(sc_event const &e) const;
156    void insert(sc_event_or_list const &eol) const;
157
158    ~sc_event_or_expr();
159
160  private:
161    friend class sc_event_or_list;
162    friend class sc_event;
163
164    sc_event_or_expr();
165    mutable sc_event_or_list *list;
166};
167
168sc_event_or_expr operator | (sc_event_or_expr, sc_event const &);
169sc_event_or_expr operator | (sc_event_or_expr, sc_event_or_list const &);
170
171class sc_event
172{
173  public:
174    sc_event();
175    explicit sc_event(const char *);
176    ~sc_event();
177
178    const char *name() const;
179    const char *basename() const;
180    bool in_hierarchy() const;
181    sc_object *get_parent_object() const;
182
183    void notify();
184    void notify(const sc_time &);
185    void notify(double, sc_time_unit);
186    void cancel();
187
188    // Nonstandard
189    // Returns whether this event is currently triggered.
190    bool triggered() const;
191
192    // Deprecated
193    void notify_delayed();
194    void notify_delayed(const sc_time &);
195
196    sc_event_and_expr operator & (const sc_event &) const;
197    sc_event_and_expr operator & (const sc_event_and_list &) const;
198    sc_event_or_expr operator | (const sc_event &) const;
199    sc_event_or_expr operator | (const sc_event_or_list &) const;
200
201  protected:
202    explicit sc_event(bool);
203    explicit sc_event(bool, const char *);
204
205  private:
206    // Disabled
207    sc_event(const sc_event &) {}
208    sc_event &operator = (const sc_event &) { return *this; }
209
210    friend class ::sc_gem5::Event;
211    ::sc_gem5::Event *_gem5_event;
212};
213
214class sc_event_finder
215{
216  protected:
217    virtual ~sc_event_finder() {}
218
219  public:
220    // Should be "implementation defined" but used in the tests.
221    virtual const sc_event &find_event(sc_interface *if_p=NULL) const = 0;
222    virtual const sc_port_base *port() const = 0;
223};
224
225template <class IF>
226class sc_event_finder_t : public sc_event_finder
227{
228  public:
229    sc_event_finder_t(const sc_port_base &p,
230                      const sc_event & (IF::*_method)() const) :
231        _method(_method)
232    {
233        _port = dynamic_cast<const sc_port_b<IF> *>(&p);
234        assert(_port);
235    }
236
237    virtual ~sc_event_finder_t() {}
238
239    const sc_port_base *port() const override { return _port; }
240
241    const sc_event &find_event(sc_interface *if_p=NULL) const override;
242
243  private:
244    const sc_port_b<IF> *_port;
245    const sc_event &(IF::*_method)() const;
246};
247
248const std::vector<sc_event *> &sc_get_top_level_events();
249sc_event *sc_find_event(const char *);
250
251} // namespace sc_core
252
253namespace sc_gem5
254{
255
256class InternalScEvent : public ::sc_core::sc_event
257{
258  public:
259    InternalScEvent();
260    InternalScEvent(const char *);
261};
262
263} // namespace sc_gem5
264
265namespace sc_core
266{
267
268template <class IF>
269const sc_event &
270sc_event_finder_t<IF>::find_event(sc_interface *if_p) const
271{
272    static const sc_gem5::InternalScEvent none;
273    const IF *iface = if_p ? dynamic_cast<const IF *>(if_p) :
274        dynamic_cast<const IF *>(_port->get_interface());
275    if (!iface) {
276        std::ostringstream ss;
277        ss << "port is not bound: port '" << _port->name() << "' (" <<
278            _port->kind() << ")";
279        SC_REPORT_ERROR(SC_ID_FIND_EVENT_, ss.str().c_str());
280        return none;
281    }
282    return (const_cast<IF *>(iface)->*_method)();
283}
284
285} // namespace sc_core
286
287#endif  //__SYSTEMC_EXT_CORE_SC_INTERFACE_HH__
288