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_CHANNEL_SC_IN_HH__
31#define __SYSTEMC_EXT_CHANNEL_SC_IN_HH__
32
33#include <string>
34
35#include "../core/sc_event.hh"
36#include "../core/sc_main.hh"
37#include "../core/sc_port.hh"
38#include "../utils/sc_trace_file.hh"
39#include "sc_signal_in_if.hh"
40#include "sc_signal_inout_if.hh"
41
42namespace sc_core
43{
44
45class sc_event;
46class sc_trace_file;
47
48template <class T>
49class sc_in : public sc_port<sc_signal_in_if<T>, 1>
50{
51  public:
52    sc_in() : sc_port<sc_signal_in_if<T>, 1>(),
53        _valueChangedFinder(*this, &sc_signal_in_if<T>::value_changed_event)
54    {}
55    explicit sc_in(const char *name) : sc_port<sc_signal_in_if<T>, 1>(name),
56        _valueChangedFinder(*this, &sc_signal_in_if<T>::value_changed_event)
57    {}
58    virtual ~sc_in() {}
59
60    // Deprecated binding constructors.
61    explicit sc_in(const sc_signal_in_if<T> &interface) :
62        sc_port<sc_signal_in_if<T>, 1>(interface),
63        _valueChangedFinder(*this, &sc_signal_in_if<T>::value_changed_event)
64    {}
65    sc_in(const char *name, const sc_signal_in_if<T> &interface) :
66        sc_port<sc_signal_in_if<T>, 1>(name, interface),
67        _valueChangedFinder(*this, &sc_signal_in_if<T>::value_changed_event)
68    {}
69    explicit sc_in(sc_port_b<sc_signal_in_if<T> > &parent) :
70        sc_port<sc_signal_in_if<T>, 1>(parent),
71        _valueChangedFinder(*this, &sc_signal_in_if<T>::value_changed_event)
72    {}
73    sc_in(const char *name, sc_port_b<sc_signal_in_if<T> > &parent) :
74        sc_port<sc_signal_in_if<T>, 1>(name, parent),
75        _valueChangedFinder(*this, &sc_signal_in_if<T>::value_changed_event)
76    {}
77    explicit sc_in(sc_port<sc_signal_in_if<T>, 1> &parent) :
78        sc_port<sc_signal_in_if<T>, 1>(parent),
79        _valueChangedFinder(*this, &sc_signal_in_if<T>::value_changed_event)
80    {}
81    sc_in(const char *name, sc_port<sc_signal_in_if<T>, 1> &parent) :
82        sc_port<sc_signal_in_if<T>, 1>(name, parent),
83        _valueChangedFinder(*this, &sc_signal_in_if<T>::value_changed_event)
84    {}
85
86    using sc_port<sc_signal_in_if<T>, 1>::bind;
87    virtual void
88    bind(const sc_signal_in_if<T> &i)
89    {
90        sc_port<sc_signal_in_if<T>, 1>::bind(
91                const_cast<sc_signal_in_if<T> &>(i));
92    }
93    void operator () (const sc_signal_in_if<T> &i) { bind(i); }
94
95    virtual void
96    bind(sc_port<sc_signal_in_if<T>, 1> &i)
97    {
98        sc_port<sc_signal_in_if<T>, 1>::bind(i);
99    }
100    void
101    operator () (sc_port<sc_signal_in_if<T>, 1> &p)
102    {
103        bind(p);
104    }
105
106    virtual void
107    bind(sc_port<sc_signal_inout_if<T>, 1> &p)
108    {
109        sc_port_base::bind(p);
110    }
111    void
112    operator () (sc_port<sc_signal_inout_if<T>, 1> &p)
113    {
114        bind(p);
115    }
116
117    virtual void
118    end_of_elaboration()
119    {
120        for (auto params: traceParamsVec)
121            sc_trace(params->tf, (*this)->read(), params->name);
122
123        traceParamsVec.clear();
124    }
125
126    const T &read() const { return (*this)->read(); }
127    operator const T& () const { return (*this)->read(); }
128
129    const sc_event &default_event() const { return (*this)->default_event(); }
130    const sc_event &
131    value_changed_event() const
132    {
133        return (*this)->value_changed_event();
134    }
135    bool event() const { return (*this)->event(); }
136    sc_event_finder &value_changed() const { return _valueChangedFinder; }
137
138    virtual const char *kind() const { return "sc_in"; }
139
140    void
141    add_trace(sc_trace_file *tf, const std::string &name) const
142    {
143        traceParamsVec.push_back(new sc_trace_params(tf, name));
144    }
145
146  private:
147    mutable sc_event_finder_t<sc_signal_in_if<T> > _valueChangedFinder;
148
149    mutable sc_trace_params_vec traceParamsVec;
150
151    // Disabled
152    sc_in(const sc_in<T> &);
153    sc_in<T> &operator = (const sc_in<T> &);
154};
155
156template <class T>
157inline void
158sc_trace(sc_trace_file *tf, const sc_in<T> &i, const std::string &name)
159{
160    if (::sc_core::sc_get_status() < ::sc_core::SC_START_OF_SIMULATION)
161        i.add_trace(tf, name);
162    else
163        sc_trace(tf, i->read(), name);
164}
165
166template <>
167class sc_in<bool> : public sc_port<sc_signal_in_if<bool>, 1>
168{
169  public:
170    sc_in() : sc_port<sc_signal_in_if<bool>, 1>(),
171        _valueChangedFinder(*this,
172                &sc_signal_in_if<bool>::value_changed_event),
173        _posFinder(*this, &sc_signal_in_if<bool>::posedge_event),
174        _negFinder(*this, &sc_signal_in_if<bool>::negedge_event)
175    {}
176    explicit sc_in(const char *name) :
177        sc_port<sc_signal_in_if<bool>, 1>(name),
178        _valueChangedFinder(*this,
179                &sc_signal_in_if<bool>::value_changed_event),
180        _posFinder(*this, &sc_signal_in_if<bool>::posedge_event),
181        _negFinder(*this, &sc_signal_in_if<bool>::negedge_event)
182    {}
183    virtual ~sc_in() {}
184
185    // Deprecated binding constructors.
186    explicit sc_in(const sc_signal_in_if<bool> &interface) :
187        sc_port<sc_signal_in_if<bool>, 1>(interface),
188        _valueChangedFinder(*this,
189                &sc_signal_in_if<bool>::value_changed_event),
190        _posFinder(*this, &sc_signal_in_if<bool>::posedge_event),
191        _negFinder(*this, &sc_signal_in_if<bool>::negedge_event)
192    {}
193    sc_in(const char *name, const sc_signal_in_if<bool> &interface) :
194        sc_port<sc_signal_in_if<bool>, 1>(name, interface),
195        _valueChangedFinder(*this,
196                &sc_signal_in_if<bool>::value_changed_event),
197        _posFinder(*this, &sc_signal_in_if<bool>::posedge_event),
198        _negFinder(*this, &sc_signal_in_if<bool>::negedge_event)
199    {}
200    explicit sc_in(sc_port_b<sc_signal_in_if<bool> > &parent) :
201        sc_port<sc_signal_in_if<bool>, 1>(parent),
202        _valueChangedFinder(*this,
203                &sc_signal_in_if<bool>::value_changed_event),
204        _posFinder(*this, &sc_signal_in_if<bool>::posedge_event),
205        _negFinder(*this, &sc_signal_in_if<bool>::negedge_event)
206    {}
207    sc_in(const char *name, sc_port_b<sc_signal_in_if<bool> > &parent) :
208        sc_port<sc_signal_in_if<bool>, 1>(name, parent),
209        _valueChangedFinder(*this,
210                &sc_signal_in_if<bool>::value_changed_event),
211        _posFinder(*this, &sc_signal_in_if<bool>::posedge_event),
212        _negFinder(*this, &sc_signal_in_if<bool>::negedge_event)
213    {}
214    explicit sc_in(sc_port<sc_signal_in_if<bool>, 1> &parent) :
215        sc_port<sc_signal_in_if<bool>, 1>(parent),
216        _valueChangedFinder(*this,
217                &sc_signal_in_if<bool>::value_changed_event),
218        _posFinder(*this, &sc_signal_in_if<bool>::posedge_event),
219        _negFinder(*this, &sc_signal_in_if<bool>::negedge_event)
220    {}
221    sc_in(const char *name, sc_port<sc_signal_in_if<bool>, 1> &parent) :
222        sc_port<sc_signal_in_if<bool>, 1>(name, parent),
223        _valueChangedFinder(*this,
224                &sc_signal_in_if<bool>::value_changed_event),
225        _posFinder(*this, &sc_signal_in_if<bool>::posedge_event),
226        _negFinder(*this, &sc_signal_in_if<bool>::negedge_event)
227    {}
228
229    using sc_port<sc_signal_in_if<bool>, 1>::bind;
230
231    virtual void
232    bind(const sc_signal_in_if<bool> &i)
233    {
234        sc_port<sc_signal_in_if<bool>, 1>::bind(
235                const_cast<sc_signal_in_if<bool> &>(i));
236    }
237    void operator () (const sc_signal_in_if<bool> &i) { bind(i); }
238
239    virtual void
240    bind(sc_port<sc_signal_in_if<bool>, 1> &p)
241    {
242        sc_port<sc_signal_in_if<bool>, 1>::bind(p);
243    }
244    void
245    operator () (sc_port<sc_signal_in_if<bool>, 1> &p)
246    {
247        bind(p);
248    }
249
250    virtual void
251    bind(sc_port<sc_signal_inout_if<bool>, 1> &p)
252    {
253        sc_port_base::bind(p);
254    }
255    void
256    operator () (sc_port<sc_signal_inout_if<bool>, 1> &p)
257    {
258        bind(p);
259    }
260
261    virtual void
262    end_of_elaboration()
263    {
264        for (auto params: traceParamsVec)
265            sc_trace(params->tf, (*this)->read(), params->name);
266
267        traceParamsVec.clear();
268    }
269
270    const bool &read() const { return (*this)->read(); }
271    operator const bool& () const { return (*this)->read(); }
272
273    const sc_event &default_event() const { return (*this)->default_event(); }
274    const sc_event &
275    value_changed_event() const
276    {
277        return (*this)->value_changed_event();
278    }
279    const sc_event &
280    posedge_event() const
281    {
282        return (*this)->posedge_event();
283    }
284    const sc_event &
285    negedge_event() const
286    {
287        return (*this)->negedge_event();
288    }
289
290    bool event() const { return (*this)->event(); }
291    bool posedge() const { return (*this)->posedge(); }
292    bool negedge() const { return (*this)->negedge(); }
293
294    sc_event_finder &value_changed() const { return _valueChangedFinder; }
295    sc_event_finder &pos() const { return _posFinder; }
296    sc_event_finder &neg() const { return _negFinder; }
297
298    virtual const char *kind() const { return "sc_in"; }
299
300    void
301    add_trace(sc_trace_file *tf, const std::string &name) const
302    {
303        traceParamsVec.push_back(new sc_trace_params(tf, name));
304    }
305
306  private:
307    mutable sc_event_finder_t<sc_signal_in_if<bool> > _valueChangedFinder;
308    mutable sc_event_finder_t<sc_signal_in_if<bool> > _posFinder;
309    mutable sc_event_finder_t<sc_signal_in_if<bool> > _negFinder;
310
311    mutable sc_trace_params_vec traceParamsVec;
312
313    // Disabled
314    sc_in(const sc_in<bool> &);
315    sc_in<bool> &operator = (const sc_in<bool> &);
316};
317
318template <>
319inline void
320sc_trace<bool>(sc_trace_file *tf, const sc_in<bool> &i,
321        const std::string &name)
322{
323    if (::sc_core::sc_get_status() < ::sc_core::SC_START_OF_SIMULATION)
324        i.add_trace(tf, name);
325    else
326        sc_trace(tf, i->read(), name);
327}
328
329template <>
330class sc_in<sc_dt::sc_logic> :
331    public sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>
332{
333  public:
334    sc_in() : sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>(),
335        _valueChangedFinder(*this,
336                &sc_signal_in_if<sc_dt::sc_logic>::value_changed_event),
337        _posFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::posedge_event),
338        _negFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::negedge_event)
339    {}
340    explicit sc_in(const char *name) :
341        sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>(name),
342        _valueChangedFinder(*this,
343                &sc_signal_in_if<sc_dt::sc_logic>::value_changed_event),
344        _posFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::posedge_event),
345        _negFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::negedge_event)
346    {}
347    virtual ~sc_in() {}
348
349    // Deprecated binding constructors.
350    explicit sc_in(const sc_signal_in_if<sc_dt::sc_logic> &interface) :
351        sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>(interface),
352        _valueChangedFinder(*this,
353                &sc_signal_in_if<sc_dt::sc_logic>::value_changed_event),
354        _posFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::posedge_event),
355        _negFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::negedge_event)
356    {}
357    sc_in(const char *name,
358            const sc_signal_in_if<sc_dt::sc_logic> &interface) :
359        sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>(name, interface),
360        _valueChangedFinder(*this,
361                &sc_signal_in_if<sc_dt::sc_logic>::value_changed_event),
362        _posFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::posedge_event),
363        _negFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::negedge_event)
364    {}
365    explicit sc_in(sc_port_b<sc_signal_in_if<sc_dt::sc_logic> > &parent) :
366        sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>(parent),
367        _valueChangedFinder(*this,
368                &sc_signal_in_if<sc_dt::sc_logic>::value_changed_event),
369        _posFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::posedge_event),
370        _negFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::negedge_event)
371    {}
372    sc_in(const char *name,
373            sc_port_b<sc_signal_in_if<sc_dt::sc_logic> > &parent) :
374        sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>(name, parent),
375        _valueChangedFinder(*this,
376                &sc_signal_in_if<sc_dt::sc_logic>::value_changed_event),
377        _posFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::posedge_event),
378        _negFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::negedge_event)
379    {}
380    explicit sc_in(sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1> &parent) :
381        sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>(parent),
382        _valueChangedFinder(*this,
383                &sc_signal_in_if<sc_dt::sc_logic>::value_changed_event),
384        _posFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::posedge_event),
385        _negFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::negedge_event)
386    {}
387    sc_in(const char *name,
388            sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1> &parent) :
389        sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>(name, parent),
390        _valueChangedFinder(*this,
391                &sc_signal_in_if<sc_dt::sc_logic>::value_changed_event),
392        _posFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::posedge_event),
393        _negFinder(*this, &sc_signal_in_if<sc_dt::sc_logic>::negedge_event)
394    {}
395
396    using sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>::bind;
397
398    virtual void
399    bind(const sc_signal_in_if<sc_dt::sc_logic> &i)
400    {
401        sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>::bind(
402                const_cast<sc_signal_in_if<sc_dt::sc_logic> &>(i));
403    }
404    void
405    operator () (const sc_signal_in_if<sc_dt::sc_logic> &i) { bind(i); }
406
407    virtual void
408    bind(sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1> &i)
409    {
410        sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1>::bind(i);
411    }
412    void
413    operator () (sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1> &p)
414    {
415        bind(p);
416    }
417
418    virtual void
419    bind(sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1> &p)
420    {
421        sc_port_base::bind(p);
422    }
423    void
424    operator () (sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1> &p)
425    {
426        bind(p);
427    }
428
429    virtual void
430    end_of_elaboration()
431    {
432        for (auto params: traceParamsVec)
433            sc_trace(params->tf, (*this)->read(), params->name);
434
435        traceParamsVec.clear();
436    }
437
438    const sc_dt::sc_logic &read() const { return (*this)->read(); }
439    operator const sc_dt::sc_logic& () const { return (*this)->read(); }
440
441    const sc_event &default_event() const { return (*this)->default_event(); }
442    const sc_event &
443    value_changed_event() const
444    {
445        return (*this)->value_changed_event();
446    }
447    const sc_event &posedge_event() const { return (*this)->posedge_event(); }
448    const sc_event &negedge_event() const { return (*this)->negedge_event(); }
449
450    bool event() const { return (*this)->event(); }
451    bool posedge() const { return (*this)->posedge(); }
452    bool negedge() const { return (*this)->negedge(); }
453
454    sc_event_finder &value_changed() const { return _valueChangedFinder; }
455    sc_event_finder &pos() const { return _posFinder; }
456    sc_event_finder &neg() const { return _negFinder; }
457
458    virtual const char *kind() const { return "sc_in"; }
459
460    void
461    add_trace(sc_trace_file *tf, const std::string &name) const
462    {
463        traceParamsVec.push_back(new sc_trace_params(tf, name));
464    }
465
466  private:
467    mutable sc_event_finder_t<sc_signal_in_if<sc_dt::sc_logic> >
468        _valueChangedFinder;
469    mutable sc_event_finder_t<sc_signal_in_if<sc_dt::sc_logic> > _posFinder;
470    mutable sc_event_finder_t<sc_signal_in_if<sc_dt::sc_logic> > _negFinder;
471
472    mutable sc_trace_params_vec traceParamsVec;
473
474    // Disabled
475    sc_in(const sc_in<sc_dt::sc_logic> &);
476    sc_in<sc_dt::sc_logic> &operator = (const sc_in<sc_dt::sc_logic> &);
477};
478
479template <>
480inline void
481sc_trace<sc_dt::sc_logic>(sc_trace_file *tf, const sc_in<sc_dt::sc_logic> &i,
482        const std::string &name)
483{
484    if (::sc_core::sc_get_status() < ::sc_core::SC_START_OF_SIMULATION)
485        i.add_trace(tf, name);
486    else
487        sc_trace(tf, i->read(), name);
488}
489
490} // namespace sc_core
491
492#endif  //__SYSTEMC_EXT_CHANNEL_SC_IN_HH__
493