sc_signal.hh revision 13245:c666c5d4996b
16313Sgblack@eecs.umich.edu/*
26313Sgblack@eecs.umich.edu * Copyright 2018 Google, Inc.
36313Sgblack@eecs.umich.edu *
46313Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
56313Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
66313Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
76313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
86313Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
96313Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
106313Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
116313Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
126313Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
136313Sgblack@eecs.umich.edu * this software without specific prior written permission.
146313Sgblack@eecs.umich.edu *
156313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
166313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
176313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
186313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
196313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
206313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
216313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
226313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
236313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
246313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
256313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
266313Sgblack@eecs.umich.edu *
276313Sgblack@eecs.umich.edu * Authors: Gabe Black
286313Sgblack@eecs.umich.edu */
296313Sgblack@eecs.umich.edu
306313Sgblack@eecs.umich.edu#ifndef __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
316313Sgblack@eecs.umich.edu#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
326313Sgblack@eecs.umich.edu
336313Sgblack@eecs.umich.edu#include <iostream>
348229Snate@binkert.org#include <string>
358229Snate@binkert.org#include <vector>
368229Snate@binkert.org
376335Sgblack@eecs.umich.edu#include "../core/sc_event.hh"
386313Sgblack@eecs.umich.edu#include "../core/sc_module.hh" // for sc_gen_unique_name
396335Sgblack@eecs.umich.edu#include "../core/sc_prim.hh"
406335Sgblack@eecs.umich.edu#include "../dt/bit/sc_logic.hh"
416335Sgblack@eecs.umich.edu#include "sc_signal_inout_if.hh"
426313Sgblack@eecs.umich.edu#include "warn_unimpl.hh" // for warn_unimpl
436313Sgblack@eecs.umich.edu
446335Sgblack@eecs.umich.edunamespace sc_core
456313Sgblack@eecs.umich.edu{
466313Sgblack@eecs.umich.edu
476313Sgblack@eecs.umich.educlass sc_port_base;
487741Sgblack@eecs.umich.edu
497741Sgblack@eecs.umich.edutemplate <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER>
507741Sgblack@eecs.umich.educlass sc_signal : public sc_signal_inout_if<T>,
516335Sgblack@eecs.umich.edu                  public sc_prim_channel
527741Sgblack@eecs.umich.edu{
537741Sgblack@eecs.umich.edu  public:
547741Sgblack@eecs.umich.edu    sc_signal() : sc_signal_inout_if<T>(),
557741Sgblack@eecs.umich.edu                  sc_prim_channel(sc_gen_unique_name("signal")),
567741Sgblack@eecs.umich.edu                  m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL)
577741Sgblack@eecs.umich.edu    {}
587741Sgblack@eecs.umich.edu    explicit sc_signal(const char *name) :
597741Sgblack@eecs.umich.edu        sc_signal_inout_if<T>(), sc_prim_channel(name),
607741Sgblack@eecs.umich.edu        m_cur_val(T()), m_new_val(T()), _changeStamp(~0ULL)
617741Sgblack@eecs.umich.edu    {}
627741Sgblack@eecs.umich.edu    explicit sc_signal(const char *name, const T &initial_value) :
636335Sgblack@eecs.umich.edu        sc_signal_inout_if<T>(), sc_prim_channel(name),
646335Sgblack@eecs.umich.edu        m_cur_val(initial_value), m_new_val(initial_value), _changeStamp(~0ULL)
657741Sgblack@eecs.umich.edu    {}
667741Sgblack@eecs.umich.edu    virtual ~sc_signal() {}
677741Sgblack@eecs.umich.edu
687741Sgblack@eecs.umich.edu    virtual void
697741Sgblack@eecs.umich.edu    register_port(sc_port_base &, const char *)
707741Sgblack@eecs.umich.edu    {
717741Sgblack@eecs.umich.edu        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
727741Sgblack@eecs.umich.edu    }
737741Sgblack@eecs.umich.edu
746335Sgblack@eecs.umich.edu    virtual const T &read() const { return m_cur_val; }
757741Sgblack@eecs.umich.edu    operator const T&() const { return read(); }
767741Sgblack@eecs.umich.edu
777741Sgblack@eecs.umich.edu    virtual sc_writer_policy
787741Sgblack@eecs.umich.edu    get_writer_policy() const
797741Sgblack@eecs.umich.edu    {
807741Sgblack@eecs.umich.edu        return WRITER_POLICY;
817741Sgblack@eecs.umich.edu    }
827741Sgblack@eecs.umich.edu    virtual void
837741Sgblack@eecs.umich.edu    write(const T &t)
847741Sgblack@eecs.umich.edu    {
856335Sgblack@eecs.umich.edu        m_new_val = t;
867741Sgblack@eecs.umich.edu        bool changed = !(m_cur_val == m_new_val);
877741Sgblack@eecs.umich.edu        //TODO check whether this write follows the write policy.
887741Sgblack@eecs.umich.edu        if (changed)
897741Sgblack@eecs.umich.edu            request_update();
907741Sgblack@eecs.umich.edu    }
917741Sgblack@eecs.umich.edu    sc_signal<T, WRITER_POLICY> &
926335Sgblack@eecs.umich.edu    operator = (const T &t)
937741Sgblack@eecs.umich.edu    {
946335Sgblack@eecs.umich.edu        write(t);
957741Sgblack@eecs.umich.edu        return *this;
967741Sgblack@eecs.umich.edu    }
976335Sgblack@eecs.umich.edu    sc_signal<T, WRITER_POLICY> &
987741Sgblack@eecs.umich.edu    operator = (const sc_signal<T, WRITER_POLICY> &s)
997741Sgblack@eecs.umich.edu    {
1007741Sgblack@eecs.umich.edu        write(s.read());
1017741Sgblack@eecs.umich.edu        return *this;
1027741Sgblack@eecs.umich.edu    }
1036335Sgblack@eecs.umich.edu
1047741Sgblack@eecs.umich.edu    virtual const sc_event &
1056335Sgblack@eecs.umich.edu    default_event() const
1067741Sgblack@eecs.umich.edu    {
1077741Sgblack@eecs.umich.edu        return value_changed_event();
1087741Sgblack@eecs.umich.edu    }
1097741Sgblack@eecs.umich.edu    virtual const sc_event &
1107741Sgblack@eecs.umich.edu    value_changed_event() const
1117741Sgblack@eecs.umich.edu    {
1127741Sgblack@eecs.umich.edu        return _valueChangedEvent;
1137741Sgblack@eecs.umich.edu    }
1146335Sgblack@eecs.umich.edu    virtual bool
1157741Sgblack@eecs.umich.edu    event() const
1167741Sgblack@eecs.umich.edu    {
1176335Sgblack@eecs.umich.edu        return _changeStamp == ::sc_gem5::getChangeStamp();
1187741Sgblack@eecs.umich.edu    }
1197741Sgblack@eecs.umich.edu
1206335Sgblack@eecs.umich.edu    virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
1217741Sgblack@eecs.umich.edu    virtual void
1227741Sgblack@eecs.umich.edu    dump(std::ostream &os=std::cout) const
1236335Sgblack@eecs.umich.edu    {
1247741Sgblack@eecs.umich.edu        os << "     name = " << name() << ::std::endl;
1257741Sgblack@eecs.umich.edu        os << "    value = " << m_cur_val << ::std::endl;
1267741Sgblack@eecs.umich.edu        os << "new value = " << m_new_val << ::std::endl;
1277741Sgblack@eecs.umich.edu    }
1287741Sgblack@eecs.umich.edu    virtual const char *kind() const { return "sc_signal"; }
1296335Sgblack@eecs.umich.edu
1307741Sgblack@eecs.umich.edu  protected:
1317741Sgblack@eecs.umich.edu    virtual void
1327741Sgblack@eecs.umich.edu    update()
1336335Sgblack@eecs.umich.edu    {
1347741Sgblack@eecs.umich.edu        if (m_new_val == m_cur_val)
1357741Sgblack@eecs.umich.edu            return;
1367741Sgblack@eecs.umich.edu
1376335Sgblack@eecs.umich.edu        m_cur_val = m_new_val;
1387741Sgblack@eecs.umich.edu        _signalChange();
1397741Sgblack@eecs.umich.edu        _changeStamp = ::sc_gem5::getChangeStamp();
1407741Sgblack@eecs.umich.edu        _valueChangedEvent.notify(SC_ZERO_TIME);
1416335Sgblack@eecs.umich.edu    }
1426337Sgblack@eecs.umich.edu
1437741Sgblack@eecs.umich.edu    void
1447741Sgblack@eecs.umich.edu    _signalChange()
1457741Sgblack@eecs.umich.edu    {
1466337Sgblack@eecs.umich.edu        _changeStamp = ::sc_gem5::getChangeStamp();
1477741Sgblack@eecs.umich.edu        _valueChangedEvent.notify(SC_ZERO_TIME);
1487741Sgblack@eecs.umich.edu    }
1497741Sgblack@eecs.umich.edu
1506337Sgblack@eecs.umich.edu    // These members which store the current and future value of the signal
1517741Sgblack@eecs.umich.edu    // are not specified in the standard but are referred to directly by one
1527741Sgblack@eecs.umich.edu    // of the tests.
1537741Sgblack@eecs.umich.edu    T m_cur_val;
1547741Sgblack@eecs.umich.edu    T m_new_val;
1557741Sgblack@eecs.umich.edu
1567741Sgblack@eecs.umich.edu  private:
1577741Sgblack@eecs.umich.edu    sc_event _valueChangedEvent;
1587741Sgblack@eecs.umich.edu    uint64_t _changeStamp;
1597741Sgblack@eecs.umich.edu
1607741Sgblack@eecs.umich.edu    // Disabled
1616337Sgblack@eecs.umich.edu    sc_signal(const sc_signal<T, WRITER_POLICY> &) :
1627741Sgblack@eecs.umich.edu            sc_signal_inout_if<T>(), sc_prim_channel("")
1637741Sgblack@eecs.umich.edu    {}
1647741Sgblack@eecs.umich.edu};
1657741Sgblack@eecs.umich.edu
1666337Sgblack@eecs.umich.edutemplate <class T, sc_writer_policy WRITER_POLICY>
1677741Sgblack@eecs.umich.eduinline std::ostream &
1686335Sgblack@eecs.umich.eduoperator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &s)
1697741Sgblack@eecs.umich.edu{
1706335Sgblack@eecs.umich.edu    os << s.read();
1717741Sgblack@eecs.umich.edu    return os;
1726335Sgblack@eecs.umich.edu}
1737741Sgblack@eecs.umich.edu
1747741Sgblack@eecs.umich.edutemplate <sc_writer_policy WRITER_POLICY>
1756335Sgblack@eecs.umich.educlass sc_signal<bool, WRITER_POLICY> :
1767741Sgblack@eecs.umich.edu    public sc_signal_inout_if<bool>, public sc_prim_channel
1776335Sgblack@eecs.umich.edu{
1787741Sgblack@eecs.umich.edu  public:
1797741Sgblack@eecs.umich.edu    sc_signal() : sc_signal_inout_if<bool>(),
1807741Sgblack@eecs.umich.edu                  sc_prim_channel(sc_gen_unique_name("signal")),
1816313Sgblack@eecs.umich.edu                  m_cur_val(bool()), m_new_val(bool()),
1827741Sgblack@eecs.umich.edu                  _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
1836313Sgblack@eecs.umich.edu    {}
1847741Sgblack@eecs.umich.edu    explicit sc_signal(const char *name) :
1857741Sgblack@eecs.umich.edu        sc_signal_inout_if<bool>(), sc_prim_channel(name),
1866313Sgblack@eecs.umich.edu        m_cur_val(bool()), m_new_val(bool()),
1877741Sgblack@eecs.umich.edu        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
1887741Sgblack@eecs.umich.edu    {}
1897741Sgblack@eecs.umich.edu    explicit sc_signal(const char *name, const bool &initial_value) :
1906313Sgblack@eecs.umich.edu        sc_signal_inout_if<bool>(), sc_prim_channel(name),
1917741Sgblack@eecs.umich.edu        m_cur_val(initial_value), m_new_val(initial_value),
1927741Sgblack@eecs.umich.edu        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
1937741Sgblack@eecs.umich.edu    {}
1947741Sgblack@eecs.umich.edu    virtual ~sc_signal() {}
1957741Sgblack@eecs.umich.edu
1967741Sgblack@eecs.umich.edu    virtual void
1977741Sgblack@eecs.umich.edu    register_port(sc_port_base &, const char *)
1987741Sgblack@eecs.umich.edu    {
1996313Sgblack@eecs.umich.edu        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
2007741Sgblack@eecs.umich.edu    }
2017741Sgblack@eecs.umich.edu
2027741Sgblack@eecs.umich.edu    virtual const bool &read() const { return m_cur_val; }
2037741Sgblack@eecs.umich.edu    operator const bool &() const { return read(); }
2047741Sgblack@eecs.umich.edu
2056313Sgblack@eecs.umich.edu    virtual sc_writer_policy
2067741Sgblack@eecs.umich.edu    get_writer_policy() const
2077741Sgblack@eecs.umich.edu    {
2087703Sgblack@eecs.umich.edu        return WRITER_POLICY;
2097741Sgblack@eecs.umich.edu    }
2107741Sgblack@eecs.umich.edu    virtual void
2117741Sgblack@eecs.umich.edu    write(const bool &b)
2127703Sgblack@eecs.umich.edu    {
2137703Sgblack@eecs.umich.edu        m_new_val = b;
2147741Sgblack@eecs.umich.edu        bool changed = !(m_cur_val == m_new_val);
2157741Sgblack@eecs.umich.edu        //TODO check whether this write follows the write policy.
2167741Sgblack@eecs.umich.edu        if (changed)
2176313Sgblack@eecs.umich.edu            request_update();
2186313Sgblack@eecs.umich.edu    }
2196313Sgblack@eecs.umich.edu    sc_signal<bool, WRITER_POLICY> &
220    operator = (const bool &b)
221    {
222        write(b);
223        return *this;
224    }
225    sc_signal<bool, WRITER_POLICY> &
226    operator = (const sc_signal<bool, WRITER_POLICY> &s)
227    {
228        write(s.read());
229        return *this;
230    }
231
232    virtual const sc_event &
233    default_event() const
234    {
235        return value_changed_event();
236    }
237
238    virtual const sc_event &
239    value_changed_event() const
240    {
241        return _valueChangedEvent;
242    }
243    virtual const sc_event &
244    posedge_event() const
245    {
246        return _posedgeEvent;
247    }
248    virtual const sc_event &
249    negedge_event() const
250    {
251        return _negedgeEvent;
252    }
253
254    virtual bool
255    event() const
256    {
257        return _changeStamp == ::sc_gem5::getChangeStamp();
258    }
259    virtual bool
260    posedge() const
261    {
262        return _posStamp == ::sc_gem5::getChangeStamp();
263    }
264    virtual bool
265    negedge() const
266    {
267        return _negStamp == ::sc_gem5::getChangeStamp();
268    }
269
270    virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
271    virtual void
272    dump(std::ostream &os=std::cout) const
273    {
274        os << "     name = " << name() << ::std::endl;
275        os << "    value = " << m_cur_val << ::std::endl;
276        os << "new value = " << m_new_val << ::std::endl;
277    }
278    virtual const char *kind() const { return "sc_signal"; }
279
280  protected:
281    virtual void
282    update()
283    {
284        if (m_new_val == m_cur_val)
285            return;
286
287        m_cur_val = m_new_val;
288        _signalChange();
289        if (m_cur_val) {
290            _posStamp = ::sc_gem5::getChangeStamp();
291            _posedgeEvent.notify(SC_ZERO_TIME);
292        } else {
293            _negStamp = ::sc_gem5::getChangeStamp();
294            _negedgeEvent.notify(SC_ZERO_TIME);
295        }
296    }
297
298    void
299    _signalChange()
300    {
301        _changeStamp = ::sc_gem5::getChangeStamp();
302        _valueChangedEvent.notify(SC_ZERO_TIME);
303    }
304
305    bool m_cur_val;
306    bool m_new_val;
307
308  private:
309    sc_event _valueChangedEvent;
310    sc_event _posedgeEvent;
311    sc_event _negedgeEvent;
312
313    uint64_t _changeStamp;
314    uint64_t _posStamp;
315    uint64_t _negStamp;
316
317    // Disabled
318    sc_signal(const sc_signal<bool, WRITER_POLICY> &) :
319            sc_signal_inout_if<bool>(), sc_prim_channel("")
320    {}
321};
322
323template <sc_writer_policy WRITER_POLICY>
324class sc_signal<sc_dt::sc_logic, WRITER_POLICY> :
325    public sc_signal_inout_if<sc_dt::sc_logic>, public sc_prim_channel
326{
327  public:
328    sc_signal() : sc_signal_inout_if<sc_dt::sc_logic>(),
329                  sc_prim_channel(sc_gen_unique_name("signal")),
330                  m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
331                  _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
332    {}
333    explicit sc_signal(const char *name) :
334        sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
335        m_cur_val(sc_dt::sc_logic()), m_new_val(sc_dt::sc_logic()),
336        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
337    {}
338    explicit sc_signal(const char *name,
339            const sc_dt::sc_logic &initial_value) :
340        sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name),
341        m_cur_val(initial_value), m_new_val(initial_value),
342        _changeStamp(~0ULL), _posStamp(~0ULL), _negStamp(~0ULL)
343    {}
344    virtual ~sc_signal() {}
345
346    virtual void
347    register_port(sc_port_base &, const char *)
348    {
349        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
350    }
351
352    virtual const sc_dt::sc_logic &read() const { return m_cur_val; }
353    operator const sc_dt::sc_logic &() const { return read(); }
354
355    virtual sc_writer_policy
356    get_writer_policy() const
357    {
358        return WRITER_POLICY;
359    }
360    virtual void
361    write(const sc_dt::sc_logic &l)
362    {
363        m_new_val = l;
364        bool changed = !(m_cur_val == m_new_val);
365        //TODO check whether this write follows the write policy.
366        if (changed)
367            request_update();
368    }
369    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
370    operator = (const sc_dt::sc_logic &l)
371    {
372        write(l);
373        return *this;
374    }
375    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
376    operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &s)
377    {
378        write(s.read());
379        return *this;
380    }
381
382    virtual const sc_event &
383    default_event() const
384    {
385        return value_changed_event();
386    }
387
388    virtual const sc_event &
389    value_changed_event() const
390    {
391        return _valueChangedEvent;
392    }
393    virtual const sc_event &
394    posedge_event() const
395    {
396        return _posedgeEvent;
397    }
398    virtual const sc_event &
399    negedge_event() const
400    {
401        return _negedgeEvent;
402    }
403
404    virtual bool
405    event() const
406    {
407        return _changeStamp == ::sc_gem5::getChangeStamp();
408    }
409    virtual bool
410    posedge() const
411    {
412        return _posStamp == ::sc_gem5::getChangeStamp();
413    }
414    virtual bool
415    negedge() const
416    {
417        return _negStamp == ::sc_gem5::getChangeStamp();
418    }
419
420    virtual void print(std::ostream &os=std::cout) const { os << m_cur_val; }
421    virtual void
422    dump(std::ostream &os=std::cout) const
423    {
424        os << "     name = " << name() << ::std::endl;
425        os << "    value = " << m_cur_val << ::std::endl;
426        os << "new value = " << m_new_val << ::std::endl;
427    }
428    virtual const char *kind() const { return "sc_signal"; }
429
430  protected:
431    virtual void
432    update()
433    {
434        if (m_new_val == m_cur_val)
435            return;
436
437        m_cur_val = m_new_val;
438        _signalChange();
439        if (m_cur_val == sc_dt::SC_LOGIC_1) {
440            _posStamp = ::sc_gem5::getChangeStamp();
441            _posedgeEvent.notify(SC_ZERO_TIME);
442        } else if (m_cur_val == sc_dt::SC_LOGIC_0) {
443            _negStamp = ::sc_gem5::getChangeStamp();
444            _negedgeEvent.notify(SC_ZERO_TIME);
445        }
446    }
447
448    void
449    _signalChange()
450    {
451        _changeStamp = ::sc_gem5::getChangeStamp();
452        _valueChangedEvent.notify(SC_ZERO_TIME);
453    }
454
455    sc_dt::sc_logic m_cur_val;
456    sc_dt::sc_logic m_new_val;
457
458  private:
459    sc_event _valueChangedEvent;
460    sc_event _posedgeEvent;
461    sc_event _negedgeEvent;
462
463    uint64_t _changeStamp;
464    uint64_t _posStamp;
465    uint64_t _negStamp;
466
467    // Disabled
468    sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &) :
469            sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel("")
470    {}
471};
472
473} // namespace sc_core
474
475#endif  //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
476