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