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