sc_inout.hh revision 13245
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 "../utils/sc_trace_file.hh"
39#include "sc_signal_inout_if.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        for (auto params: traceParamsVec)
116            sc_trace(params->tf, (*this)->read(), params->name);
117
118        traceParamsVec.clear();
119    }
120
121    const T &read() const { return (*this)->read(); }
122    operator const T& () const { return (*this)->read(); }
123
124    void write(const T &t) { (*this)->write(t); }
125    sc_inout<T> &
126    operator = (const T &t)
127    {
128        (*this)->write(t);
129        return *this;
130    }
131    sc_inout<T> &
132    operator = (const sc_signal_in_if<T> &i)
133    {
134        (*this)->write(i.read());
135        return *this;
136    }
137    sc_inout<T> &
138    operator = (const sc_port<sc_signal_in_if<T>, 1> &p)
139    {
140        (*this)->write(p->read());
141        return *this;
142    }
143    sc_inout<T> &
144    operator = (const sc_port<sc_signal_inout_if<T>, 1> &p)
145    {
146        (*this)->write(p->read());
147        return *this;
148    }
149    sc_inout<T> &
150    operator = (const sc_inout<T> &p)
151    {
152        (*this)->write(p->read());
153        return *this;
154    }
155
156    const sc_event &default_event() const { return (*this)->default_event(); }
157    const sc_event &
158    value_changed_event() const
159    {
160        return (*this)->value_changed_event();
161    }
162    bool event() const { return (*this)->event(); }
163    sc_event_finder &value_changed() const { return _valueChangedFinder; }
164
165    virtual const char *kind() const { return "sc_inout"; }
166
167    void
168    add_trace(sc_trace_file *tf, const std::string &name) const
169    {
170        traceParamsVec.push_back(new sc_trace_params(tf, name));
171    }
172
173  private:
174    T *initValue;
175    mutable sc_event_finder_t<sc_signal_inout_if<T> > _valueChangedFinder;
176
177    mutable sc_trace_params_vec traceParamsVec;
178
179    // Disabled
180    sc_inout(const sc_inout<T> &);
181};
182
183template <class T>
184inline void
185sc_trace(sc_trace_file *tf, const sc_inout<T> &i, const std::string &name)
186{
187    if (i.size())
188        sc_trace(tf, i->read(), name);
189    else
190        i.add_trace(tf, name);
191}
192
193template <>
194class sc_inout<bool> : public sc_port<sc_signal_inout_if<bool>, 1>
195{
196  public:
197    sc_inout() : sc_port<sc_signal_inout_if<bool>, 1>(), initValue(nullptr),
198        _valueChangedFinder(*this,
199                &sc_signal_inout_if<bool>::value_changed_event),
200        _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event),
201        _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event)
202    {}
203    explicit sc_inout(const char *name) :
204            sc_port<sc_signal_inout_if<bool>, 1>(name), initValue(nullptr),
205        _valueChangedFinder(*this,
206                &sc_signal_inout_if<bool>::value_changed_event),
207        _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event),
208        _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event)
209    {}
210    virtual ~sc_inout() { delete initValue; }
211
212    // Deprecated binding constructors.
213    explicit sc_inout(const sc_signal_inout_if<bool> &interface) :
214        sc_port<sc_signal_inout_if<bool>, 1>(interface), initValue(nullptr),
215        _valueChangedFinder(*this,
216                &sc_signal_inout_if<bool>::value_changed_event),
217        _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event),
218        _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event)
219    {}
220    sc_inout(const char *name, const sc_signal_inout_if<bool> &interface) :
221        sc_port<sc_signal_inout_if<bool>, 1>(name, interface),
222        initValue(nullptr),
223        _valueChangedFinder(*this,
224                &sc_signal_inout_if<bool>::value_changed_event),
225        _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event),
226        _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event)
227    {}
228    explicit sc_inout(sc_port_b<sc_signal_inout_if<bool> > &parent) :
229        sc_port<sc_signal_inout_if<bool>, 1>(parent), initValue(nullptr),
230        _valueChangedFinder(*this,
231                &sc_signal_inout_if<bool>::value_changed_event),
232        _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event),
233        _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event)
234    {}
235    sc_inout(const char *name, sc_port_b<sc_signal_inout_if<bool> > &parent) :
236        sc_port<sc_signal_inout_if<bool>, 1>(name, parent), initValue(nullptr),
237        _valueChangedFinder(*this,
238                &sc_signal_inout_if<bool>::value_changed_event),
239        _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event),
240        _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event)
241    {}
242    explicit sc_inout(sc_port<sc_signal_inout_if<bool>, 1> &parent) :
243        sc_port<sc_signal_inout_if<bool>, 1>(parent), initValue(nullptr),
244        _valueChangedFinder(*this,
245                &sc_signal_inout_if<bool>::value_changed_event),
246        _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event),
247        _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event)
248    {}
249    sc_inout(const char *name, sc_port<sc_signal_inout_if<bool>, 1> &parent) :
250        sc_port<sc_signal_inout_if<bool>, 1>(name, parent), initValue(nullptr),
251        _valueChangedFinder(*this,
252                &sc_signal_inout_if<bool>::value_changed_event),
253        _posFinder(*this, &sc_signal_inout_if<bool>::posedge_event),
254        _negFinder(*this, &sc_signal_inout_if<bool>::negedge_event)
255    {}
256
257    void
258    initialize(const bool &b)
259    {
260        if (this->size()) {
261            (*this)->write(b);
262        } else {
263            if (!initValue)
264                initValue = new bool;
265            *initValue = b;
266        }
267    }
268    void initialize(const sc_signal_in_if<bool> &i) { initialize(i.read()); }
269
270    virtual void
271    end_of_elaboration()
272    {
273        if (initValue) {
274            write(*initValue);
275            delete initValue;
276            initValue = nullptr;
277        }
278
279        for (auto params: traceParamsVec)
280            sc_trace(params->tf, (*this)->read(), params->name);
281
282        traceParamsVec.clear();
283    }
284
285    const bool &read() const { return (*this)->read(); }
286    operator const bool& () const { return (*this)->read(); }
287
288    void write(const bool &b) { (*this)->write(b); }
289    sc_inout<bool> &
290    operator = (const bool &b)
291    {
292        (*this)->write(b);
293        return *this;
294    }
295    sc_inout<bool> &
296    operator = (const sc_signal_in_if<bool> &i)
297    {
298        (*this)->write(i.read());
299        return *this;
300    }
301    sc_inout<bool> &
302    operator = (const sc_port<sc_signal_in_if<bool>, 1> &p)
303    {
304        (*this)->write(p->read());
305        return *this;
306    }
307    sc_inout<bool> &
308    operator = (const sc_port<sc_signal_inout_if<bool>, 1> &p)
309    {
310        (*this)->write(p->read());
311        return *this;
312    }
313    sc_inout<bool> &
314    operator = (const sc_inout<bool> &p)
315    {
316        (*this)->write(p->read());
317        return *this;
318    }
319
320    const sc_event &default_event() const { return (*this)->default_event(); }
321    const sc_event &
322    value_changed_event() const
323    {
324        return (*this)->value_changed_event();
325    }
326    const sc_event &posedge_event() const { return (*this)->posedge_event(); }
327    const sc_event &negedge_event() const { return (*this)->negedge_event(); }
328    bool event() const { return (*this)->event(); }
329    bool posedge() const { return (*this)->posedge(); }
330    bool negedge() const { return (*this)->negedge(); }
331
332    sc_event_finder &value_changed() const { return _valueChangedFinder; }
333    sc_event_finder &pos() const { return _posFinder; }
334    sc_event_finder &neg() const { return _negFinder; }
335
336    virtual const char *kind() const { return "sc_inout"; }
337
338    void
339    add_trace(sc_trace_file *tf, const std::string &name) const
340    {
341        traceParamsVec.push_back(new sc_trace_params(tf, name));
342    }
343
344  private:
345    bool *initValue;
346    mutable sc_event_finder_t<sc_signal_inout_if<bool> > _valueChangedFinder;
347    mutable sc_event_finder_t<sc_signal_inout_if<bool> > _posFinder;
348    mutable sc_event_finder_t<sc_signal_inout_if<bool> > _negFinder;
349
350    mutable sc_trace_params_vec traceParamsVec;
351
352    // Disabled
353    sc_inout(const sc_inout<bool> &);
354};
355
356template <>
357inline void sc_trace<bool>(
358        sc_trace_file *tf, const sc_inout<bool> &i, const std::string &name)
359{
360    if (i.size())
361        sc_trace(tf, i->read(), name);
362    else
363        i.add_trace(tf, name);
364}
365
366template <>
367class sc_inout<sc_dt::sc_logic> :
368        public sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>
369{
370  public:
371    sc_inout() : sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(),
372        initValue(nullptr),
373        _valueChangedFinder(*this,
374                &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event),
375        _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event),
376        _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event)
377    {}
378    explicit sc_inout(const char *name) :
379            sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(name),
380        initValue(nullptr),
381        _valueChangedFinder(*this,
382                &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event),
383        _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event),
384        _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event)
385    {}
386    virtual ~sc_inout() { delete initValue; }
387
388    // Deprecated binding constructors.
389    explicit sc_inout(const sc_signal_inout_if<sc_dt::sc_logic> &interface) :
390        sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(interface),
391        initValue(nullptr),
392        _valueChangedFinder(*this,
393                &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event),
394        _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event),
395        _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event)
396    {}
397    sc_inout(const char *name,
398            const sc_signal_inout_if<sc_dt::sc_logic> &interface) :
399        sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(name, interface),
400        initValue(nullptr),
401        _valueChangedFinder(*this,
402                &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event),
403        _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event),
404        _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event)
405    {}
406    explicit sc_inout(
407            sc_port_b<sc_signal_inout_if<sc_dt::sc_logic> > &parent) :
408        sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(parent),
409        initValue(nullptr),
410        _valueChangedFinder(*this,
411                &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event),
412        _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event),
413        _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event)
414    {}
415    sc_inout(const char *name,
416            sc_port_b<sc_signal_inout_if<sc_dt::sc_logic> > &parent) :
417        sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(name, parent),
418        initValue(nullptr),
419        _valueChangedFinder(*this,
420                &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event),
421        _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event),
422        _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event)
423    {}
424    explicit sc_inout(
425            sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1> &parent) :
426        sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(parent),
427        initValue(nullptr),
428        _valueChangedFinder(*this,
429                &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event),
430        _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event),
431        _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event)
432    {}
433    sc_inout(const char *name,
434            sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1> &parent) :
435        sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1>(name, parent),
436        initValue(nullptr),
437        _valueChangedFinder(*this,
438                &sc_signal_inout_if<sc_dt::sc_logic>::value_changed_event),
439        _posFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::posedge_event),
440        _negFinder(*this, &sc_signal_inout_if<sc_dt::sc_logic>::negedge_event)
441    {}
442
443    void
444    initialize(const sc_dt::sc_logic &l)
445    {
446        if (this->size()) {
447            (*this)->write(l);
448        } else {
449            if (!initValue)
450                initValue = new sc_dt::sc_logic;
451            *initValue = l;
452        }
453    }
454    void
455    initialize(const sc_signal_in_if<sc_dt::sc_logic> &i)
456    {
457        initialize(i.read());
458    }
459
460    virtual void
461    end_of_elaboration()
462    {
463        if (initValue) {
464            write(*initValue);
465            delete initValue;
466            initValue = nullptr;
467        }
468
469        for (auto params: traceParamsVec)
470            sc_trace(params->tf, (*this)->read(), params->name);
471
472        traceParamsVec.clear();
473    }
474
475    const sc_dt::sc_logic &read() const { return (*this)->read(); }
476    operator const sc_dt::sc_logic& () const { return (*this)->read(); }
477
478    void write(const sc_dt::sc_logic &l) { (*this)->write(l); }
479    sc_inout<sc_dt::sc_logic> &
480    operator = (const sc_dt::sc_logic &l)
481    {
482        (*this)->write(l);
483        return *this;
484    }
485    sc_inout<sc_dt::sc_logic> &
486    operator = (const sc_signal_in_if<sc_dt::sc_logic> &i)
487    {
488        (*this)->write(i.read());
489        return *this;
490    }
491    sc_inout<sc_dt::sc_logic> &
492    operator = (const sc_port<sc_signal_in_if<sc_dt::sc_logic>, 1> &p)
493    {
494        (*this)->write(p->read());
495        return *this;
496    }
497    sc_inout<sc_dt::sc_logic> &
498    operator = (const sc_port<sc_signal_inout_if<sc_dt::sc_logic>, 1> &p)
499    {
500        (*this)->write(p->read());
501        return *this;
502    }
503    sc_inout<sc_dt::sc_logic> &
504    operator = (const sc_inout<sc_dt::sc_logic> &p)
505    {
506        (*this)->write(p->read());
507        return *this;
508    }
509
510    const sc_event &default_event() const { return (*this)->default_event(); }
511    const sc_event &
512    value_changed_event() const
513    {
514        return (*this)->value_changed_event();
515    }
516    const sc_event &posedge_event() const { return (*this)->posedge_event(); }
517    const sc_event &negedge_event() const { return (*this)->negedge_event(); }
518    bool event() const { return (*this)->event(); }
519    bool posedge() const { return (*this)->posedge(); }
520    bool negedge() const { return (*this)->negedge(); }
521
522    sc_event_finder &value_changed() const { return _valueChangedFinder; }
523    sc_event_finder &pos() const { return _posFinder; }
524    sc_event_finder &neg() const { return _negFinder; }
525
526    virtual const char *kind() const { return "sc_inout"; }
527
528    void
529    add_trace(sc_trace_file *tf, const std::string &name) const
530    {
531        traceParamsVec.push_back(new sc_trace_params(tf, name));
532    }
533
534  private:
535    sc_dt::sc_logic *initValue;
536    mutable sc_event_finder_t<
537        sc_signal_inout_if<sc_dt::sc_logic> > _valueChangedFinder;
538    mutable sc_event_finder_t<sc_signal_inout_if<sc_dt::sc_logic> > _posFinder;
539    mutable sc_event_finder_t<sc_signal_inout_if<sc_dt::sc_logic> > _negFinder;
540
541    mutable sc_trace_params_vec traceParamsVec;
542
543    // Disabled
544    sc_inout(const sc_inout<sc_dt::sc_logic> &);
545};
546
547template <>
548inline void
549sc_trace<sc_dt::sc_logic>(sc_trace_file *tf,
550        const sc_inout<sc_dt::sc_logic> &i, const std::string &name)
551{
552    if (i.size())
553        sc_trace(tf, i->read(), name);
554    else
555        i.add_trace(tf, name);
556}
557
558} // namespace sc_core
559
560#endif  //__SYSTEMC_EXT_CHANNEL_SC_INOUT_HH__
561