sc_clock.cc revision 13324:c8b709468e61
17753SWilliam.Wang@arm.com/*
27753SWilliam.Wang@arm.com * Copyright 2018 Google, Inc.
37753SWilliam.Wang@arm.com *
47753SWilliam.Wang@arm.com * Redistribution and use in source and binary forms, with or without
57753SWilliam.Wang@arm.com * modification, are permitted provided that the following conditions are
67753SWilliam.Wang@arm.com * met: redistributions of source code must retain the above copyright
77753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer;
87753SWilliam.Wang@arm.com * redistributions in binary form must reproduce the above copyright
97753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer in the
107753SWilliam.Wang@arm.com * documentation and/or other materials provided with the distribution;
117753SWilliam.Wang@arm.com * neither the name of the copyright holders nor the names of its
127753SWilliam.Wang@arm.com * contributors may be used to endorse or promote products derived from
137753SWilliam.Wang@arm.com * this software without specific prior written permission.
147753SWilliam.Wang@arm.com *
157753SWilliam.Wang@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
167753SWilliam.Wang@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
177753SWilliam.Wang@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
187753SWilliam.Wang@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
197753SWilliam.Wang@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
207753SWilliam.Wang@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
217753SWilliam.Wang@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
227753SWilliam.Wang@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
237753SWilliam.Wang@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
247753SWilliam.Wang@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
257753SWilliam.Wang@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
267753SWilliam.Wang@arm.com *
277753SWilliam.Wang@arm.com * Authors: Gabe Black
287753SWilliam.Wang@arm.com */
297753SWilliam.Wang@arm.com
307753SWilliam.Wang@arm.com#include "base/logging.hh"
317753SWilliam.Wang@arm.com#include "base/types.hh"
327753SWilliam.Wang@arm.com#include "sim/core.hh"
337753SWilliam.Wang@arm.com#include "sim/eventq.hh"
347753SWilliam.Wang@arm.com#include "systemc/core/kernel.hh"
357753SWilliam.Wang@arm.com#include "systemc/core/process_types.hh"
367753SWilliam.Wang@arm.com#include "systemc/core/sched_event.hh"
377753SWilliam.Wang@arm.com#include "systemc/core/scheduler.hh"
387753SWilliam.Wang@arm.com#include "systemc/ext/channel/messages.hh"
397753SWilliam.Wang@arm.com#include "systemc/ext/channel/sc_clock.hh"
407753SWilliam.Wang@arm.com#include "systemc/ext/core/sc_main.hh"
417753SWilliam.Wang@arm.com#include "systemc/ext/core/sc_module.hh" // for sc_gen_unique_name
427753SWilliam.Wang@arm.com#include "systemc/ext/utils/sc_report_handler.hh"
437753SWilliam.Wang@arm.com
447753SWilliam.Wang@arm.comnamespace sc_gem5
457753SWilliam.Wang@arm.com{
467753SWilliam.Wang@arm.com
477753SWilliam.Wang@arm.comclass ClockTick : public ScEvent
487753SWilliam.Wang@arm.com{
497753SWilliam.Wang@arm.com  private:
507753SWilliam.Wang@arm.com    ::sc_core::sc_clock *clock;
517753SWilliam.Wang@arm.com    ::sc_core::sc_time _period;
527753SWilliam.Wang@arm.com    std::string name;
537753SWilliam.Wang@arm.com    Process *p;
547753SWilliam.Wang@arm.com    ProcessMemberFuncWrapper<::sc_core::sc_clock> funcWrapper;
557753SWilliam.Wang@arm.com
567753SWilliam.Wang@arm.com  public:
577753SWilliam.Wang@arm.com    ClockTick(::sc_core::sc_clock *clock, bool to,
587753SWilliam.Wang@arm.com            ::sc_core::sc_time _period) :
597753SWilliam.Wang@arm.com        ScEvent([this]() { tick(); }),
607753SWilliam.Wang@arm.com        clock(clock), _period(_period), name(clock->basename()), p(nullptr),
617753SWilliam.Wang@arm.com        funcWrapper(clock, to ? &::sc_core::sc_clock::tickUp :
627753SWilliam.Wang@arm.com                                &::sc_core::sc_clock::tickDown)
637753SWilliam.Wang@arm.com    {
647753SWilliam.Wang@arm.com        name += std::string(to ? "_posedge_action" : "_negedge_action");
657753SWilliam.Wang@arm.com        name = ::sc_core::sc_gen_unique_name(name.c_str());
667753SWilliam.Wang@arm.com    }
677753SWilliam.Wang@arm.com
687753SWilliam.Wang@arm.com    void
697753SWilliam.Wang@arm.com    createProcess()
707753SWilliam.Wang@arm.com    {
717753SWilliam.Wang@arm.com        p = new Method(name.c_str(), &funcWrapper, true);
727753SWilliam.Wang@arm.com        p->dontInitialize(true);
737753SWilliam.Wang@arm.com        scheduler.reg(p);
747753SWilliam.Wang@arm.com    }
757753SWilliam.Wang@arm.com
767753SWilliam.Wang@arm.com    ~ClockTick()
777753SWilliam.Wang@arm.com    {
787753SWilliam.Wang@arm.com        if (scheduled())
797753SWilliam.Wang@arm.com            scheduler.deschedule(this);
807753SWilliam.Wang@arm.com        if (p)
817753SWilliam.Wang@arm.com            p->popListNode();
827753SWilliam.Wang@arm.com    }
837753SWilliam.Wang@arm.com
847753SWilliam.Wang@arm.com    void
857753SWilliam.Wang@arm.com    tick()
867753SWilliam.Wang@arm.com    {
877753SWilliam.Wang@arm.com        scheduler.schedule(this, _period);
887753SWilliam.Wang@arm.com        p->ready();
897753SWilliam.Wang@arm.com    }
907753SWilliam.Wang@arm.com};
917753SWilliam.Wang@arm.com
927753SWilliam.Wang@arm.com};
937753SWilliam.Wang@arm.com
947753SWilliam.Wang@arm.comnamespace sc_core
957753SWilliam.Wang@arm.com{
967753SWilliam.Wang@arm.com
977753SWilliam.Wang@arm.comsc_clock::sc_clock() :
987753SWilliam.Wang@arm.com    sc_clock(sc_gen_unique_name("clock"), sc_time(1.0, SC_NS),
997753SWilliam.Wang@arm.com            0.5, SC_ZERO_TIME, true)
1007753SWilliam.Wang@arm.com{}
1017753SWilliam.Wang@arm.com
1027753SWilliam.Wang@arm.comsc_clock::sc_clock(const char *name) :
1037753SWilliam.Wang@arm.com    sc_clock(name, sc_time(1.0, SC_NS), 0.5, SC_ZERO_TIME, true)
1047753SWilliam.Wang@arm.com{}
1057753SWilliam.Wang@arm.com
1067753SWilliam.Wang@arm.comsc_clock::sc_clock(const char *name, const sc_time &period,
1077753SWilliam.Wang@arm.com                   double duty_cycle, const sc_time &start_time,
1087753SWilliam.Wang@arm.com                   bool posedge_first) :
1097753SWilliam.Wang@arm.com    sc_interface(), sc_signal<bool>(name, posedge_first ? false : true),
1107753SWilliam.Wang@arm.com    _period(period), _dutyCycle(duty_cycle), _startTime(start_time),
1117753SWilliam.Wang@arm.com    _posedgeFirst(posedge_first)
1127753SWilliam.Wang@arm.com{
1137753SWilliam.Wang@arm.com    if (period == SC_ZERO_TIME) {
1147753SWilliam.Wang@arm.com        std::string msg =
1157753SWilliam.Wang@arm.com            "increase the period: clock '" +
1167753SWilliam.Wang@arm.com            std::string(name) + "'";
1177753SWilliam.Wang@arm.com        SC_REPORT_ERROR(SC_ID_CLOCK_PERIOD_ZERO_, msg.c_str());
1187753SWilliam.Wang@arm.com    }
1197753SWilliam.Wang@arm.com
1207753SWilliam.Wang@arm.com    if (duty_cycle * period == SC_ZERO_TIME) {
1217753SWilliam.Wang@arm.com        std::string msg =
1227753SWilliam.Wang@arm.com            "increase the period or increase the duty cycle: clock '" +
1237753SWilliam.Wang@arm.com            std::string(name) + "'";
1247753SWilliam.Wang@arm.com        SC_REPORT_ERROR(SC_ID_CLOCK_HIGH_TIME_ZERO_, msg.c_str());
1257753SWilliam.Wang@arm.com    }
1267753SWilliam.Wang@arm.com
1277753SWilliam.Wang@arm.com    if (duty_cycle * period == period) {
1287753SWilliam.Wang@arm.com        std::string msg =
1297753SWilliam.Wang@arm.com            "increase the period or decrease the duty cycle: clock '" +
1307753SWilliam.Wang@arm.com            std::string(name) + "'";
1317753SWilliam.Wang@arm.com        SC_REPORT_ERROR(SC_ID_CLOCK_LOW_TIME_ZERO_, msg.c_str());
1327753SWilliam.Wang@arm.com    }
1337753SWilliam.Wang@arm.com
1347753SWilliam.Wang@arm.com    _gem5UpEdge = new ::sc_gem5::ClockTick(this, true, period);
1357753SWilliam.Wang@arm.com    _gem5DownEdge = new ::sc_gem5::ClockTick(this, false, period);
1367753SWilliam.Wang@arm.com}
1377753SWilliam.Wang@arm.com
1387753SWilliam.Wang@arm.comsc_clock::sc_clock(const char *name, double period_v, sc_time_unit period_tu,
1397753SWilliam.Wang@arm.com                   double duty_cycle) :
1407753SWilliam.Wang@arm.com    sc_clock(name, sc_time(period_v, period_tu), duty_cycle, SC_ZERO_TIME,
1417753SWilliam.Wang@arm.com            true)
1427753SWilliam.Wang@arm.com{}
1437753SWilliam.Wang@arm.com
1447753SWilliam.Wang@arm.comsc_clock::sc_clock(const char *name, double period_v, sc_time_unit period_tu,
1457753SWilliam.Wang@arm.com                   double duty_cycle, double start_time_v,
1467753SWilliam.Wang@arm.com                   sc_time_unit start_time_tu, bool posedge_first) :
1477753SWilliam.Wang@arm.com    sc_clock(name, sc_time(period_v, period_tu), duty_cycle,
1487753SWilliam.Wang@arm.com            sc_time(start_time_v, start_time_tu), posedge_first)
1497753SWilliam.Wang@arm.com{}
1507753SWilliam.Wang@arm.com
1517753SWilliam.Wang@arm.comsc_clock::sc_clock(const char *name, double period, double duty_cycle,
1527753SWilliam.Wang@arm.com                   double start_time, bool posedge_first) :
1537753SWilliam.Wang@arm.com    sc_clock(name, sc_time(period, true), duty_cycle,
1547753SWilliam.Wang@arm.com            sc_time(start_time, true), posedge_first)
1557753SWilliam.Wang@arm.com{}
1567753SWilliam.Wang@arm.com
1577753SWilliam.Wang@arm.comsc_clock::~sc_clock()
1587753SWilliam.Wang@arm.com{
1597753SWilliam.Wang@arm.com    if (_gem5UpEdge->scheduled())
1607753SWilliam.Wang@arm.com        ::sc_gem5::scheduler.deschedule(_gem5UpEdge);
1617753SWilliam.Wang@arm.com    if (_gem5DownEdge->scheduled())
1627753SWilliam.Wang@arm.com        ::sc_gem5::scheduler.deschedule(_gem5DownEdge);
1637753SWilliam.Wang@arm.com    delete _gem5UpEdge;
1647753SWilliam.Wang@arm.com    delete _gem5DownEdge;
1657753SWilliam.Wang@arm.com}
1667753SWilliam.Wang@arm.com
1677753SWilliam.Wang@arm.comvoid
1687753SWilliam.Wang@arm.comsc_clock::write(const bool &)
1697753SWilliam.Wang@arm.com{
1707753SWilliam.Wang@arm.com    panic("write() called on sc_clock.");
1717753SWilliam.Wang@arm.com}
1727753SWilliam.Wang@arm.com
1737753SWilliam.Wang@arm.comconst sc_time &sc_clock::period() const { return _period; }
1747753SWilliam.Wang@arm.comdouble sc_clock::duty_cycle() const { return _dutyCycle; }
1757753SWilliam.Wang@arm.comconst sc_time &sc_clock::start_time() const { return _startTime; }
1767753SWilliam.Wang@arm.combool sc_clock::posedge_first() const { return _posedgeFirst; }
1777753SWilliam.Wang@arm.com
1787753SWilliam.Wang@arm.comconst sc_time &
1797753SWilliam.Wang@arm.comsc_clock::time_stamp()
1807753SWilliam.Wang@arm.com{
1817753SWilliam.Wang@arm.com    return sc_time_stamp();
1827753SWilliam.Wang@arm.com}
1837753SWilliam.Wang@arm.com
1847753SWilliam.Wang@arm.comvoid
1857753SWilliam.Wang@arm.comsc_clock::before_end_of_elaboration()
1867753SWilliam.Wang@arm.com{
1877753SWilliam.Wang@arm.com    _gem5UpEdge->createProcess();
1887753SWilliam.Wang@arm.com    _gem5DownEdge->createProcess();
1897753SWilliam.Wang@arm.com    if (_posedgeFirst) {
1907753SWilliam.Wang@arm.com        ::sc_gem5::scheduler.schedule(_gem5UpEdge, _startTime);
1917753SWilliam.Wang@arm.com        ::sc_gem5::scheduler.schedule(_gem5DownEdge,
1927753SWilliam.Wang@arm.com                _startTime + _period * _dutyCycle);
1937753SWilliam.Wang@arm.com    } else {
1947753SWilliam.Wang@arm.com        ::sc_gem5::scheduler.schedule(_gem5DownEdge, _startTime);
1957753SWilliam.Wang@arm.com        ::sc_gem5::scheduler.schedule(_gem5UpEdge,
1967753SWilliam.Wang@arm.com                _startTime + _period * (1.0 - _dutyCycle));
1977753SWilliam.Wang@arm.com    }
1987753SWilliam.Wang@arm.com}
1997753SWilliam.Wang@arm.com
2007753SWilliam.Wang@arm.com} // namespace sc_core
2017753SWilliam.Wang@arm.com