systemc: Implement a significant portion of sc_clock.
authorGabe Black <gabeblack@google.com>
Fri, 17 Aug 2018 02:10:09 +0000 (19:10 -0700)
committerGabe Black <gabeblack@google.com>
Tue, 25 Sep 2018 23:50:23 +0000 (23:50 +0000)
Change-Id: Ic195f46ac13b46a02c86a5fc8d90ba66a415a9c8
Reviewed-on: https://gem5-review.googlesource.com/12215
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/channel/sc_clock.cc
src/systemc/ext/channel/sc_clock.hh

index 65f1f100d3b37aa970026cc4ddec2fd346c946a6..6736e57cf2f7b0e02835896b641b4b1d43bf7a51 100644 (file)
  */
 
 #include "base/logging.hh"
+#include "base/types.hh"
+#include "sim/core.hh"
+#include "sim/eventq.hh"
+#include "systemc/core/kernel.hh"
+#include "systemc/core/sched_event.hh"
+#include "systemc/core/scheduler.hh"
 #include "systemc/ext/channel/sc_clock.hh"
 #include "systemc/ext/core/sc_module.hh" // for sc_gen_unique_name
 
-namespace sc_core
+namespace sc_gem5
 {
 
-sc_clock::sc_clock() :
-        sc_interface(), sc_signal<bool>(sc_gen_unique_name("clock"))
+class ClockTick : public ScEvent
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
+  private:
+    ::sc_core::sc_clock *clock;
+    ::sc_core::sc_time _period;
+    std::string _name;
+    Process *p;
+    ProcessMemberFuncWrapper<::sc_core::sc_clock> funcWrapper;
+    std::string _procName;
+
+  public:
+    ClockTick(::sc_core::sc_clock *clock, bool to,
+            ::sc_core::sc_time _period) :
+        ScEvent([this]() { tick(); }),
+        clock(clock), _period(_period), _name(clock->name()),
+        funcWrapper(clock, to ? &::sc_core::sc_clock::tickUp :
+                                &::sc_core::sc_clock::tickDown)
+    {
+        _name += (to ? ".up_tick" : ".down_tick");
+        _procName = _name + ".p";
+        p = newMethodProcess(_procName.c_str(), &funcWrapper);
+        scheduler.dontInitialize(p);
+    }
+
+    ~ClockTick()
+    {
+        if (scheduled())
+            scheduler.deschedule(this);
+        p->popListNode();
+    }
+
+    void
+    tick()
+    {
+        scheduler.schedule(this, _period);
+        p->ready();
+    }
+};
+
+};
 
-sc_clock::sc_clock(const char *name) : sc_interface(), sc_signal<bool>(name)
+namespace sc_core
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
+
+sc_clock::sc_clock() :
+    sc_clock(sc_gen_unique_name("clock"), sc_time(1.0, SC_NS),
+            0.5, SC_ZERO_TIME, true)
+{}
+
+sc_clock::sc_clock(const char *name) :
+    sc_clock(name, sc_time(1.0, SC_NS), 0.5, SC_ZERO_TIME, true)
+{}
 
 sc_clock::sc_clock(const char *name, const sc_time &period,
                    double duty_cycle, const sc_time &start_time,
-                   bool posedge_first)
+                   bool posedge_first) :
+    sc_interface(), sc_signal<bool>(name, posedge_first ? false : true),
+    _period(period), _dutyCycle(duty_cycle), _startTime(start_time),
+    _posedgeFirst(posedge_first)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _gem5UpEdge = new ::sc_gem5::ClockTick(this, true, period);
+    _gem5DownEdge = new ::sc_gem5::ClockTick(this, false, period);
 }
 
 sc_clock::sc_clock(const char *name, double period_v, sc_time_unit period_tu,
-                   double duty_cycle)
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
+                   double duty_cycle) :
+    sc_clock(name, sc_time(period_v, period_tu), duty_cycle, SC_ZERO_TIME,
+            true)
+{}
 
 sc_clock::sc_clock(const char *name, double period_v, sc_time_unit period_tu,
                    double duty_cycle, double start_time_v,
-                   sc_time_unit start_time_tu, bool posedge_first)
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
+                   sc_time_unit start_time_tu, bool posedge_first) :
+    sc_clock(name, sc_time(period_v, period_tu), duty_cycle,
+            sc_time(start_time_v, start_time_tu), posedge_first)
+{}
 
 sc_clock::sc_clock(const char *name, double period, double duty_cycle,
-                   double start_time, bool posedge_first)
+                   double start_time, bool posedge_first) :
+    sc_clock(name, sc_time(period, true), duty_cycle,
+            sc_time(start_time, true), posedge_first)
+{}
+
+sc_clock::~sc_clock()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    if (_gem5UpEdge->scheduled())
+        ::sc_gem5::scheduler.deschedule(_gem5UpEdge);
+    if (_gem5DownEdge->scheduled())
+        ::sc_gem5::scheduler.deschedule(_gem5DownEdge);
+    delete _gem5UpEdge;
+    delete _gem5DownEdge;
 }
 
-sc_clock::~sc_clock() {}
-
 void
 sc_clock::write(const bool &)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
-
-const sc_time &
-sc_clock::period() const
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return *(const sc_time *)nullptr;
+    panic("write() called on sc_clock.");
 }
 
-double
-sc_clock::duty_cycle() const
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return 0.0;
-}
+const sc_time &sc_clock::period() const { return _period; }
+double sc_clock::duty_cycle() const { return _dutyCycle; }
+const sc_time &sc_clock::start_time() const { return _startTime; }
+bool sc_clock::posedge_first() const { return _posedgeFirst; }
 
 const sc_time &
-sc_clock::start_time() const
+sc_clock::time_stamp()
 {
     warn("%s not implemented.\n", __PRETTY_FUNCTION__);
     return *(const sc_time *)nullptr;
 }
 
-bool
-sc_clock::posedge_first() const
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return false;
-}
-
-const sc_time &
-sc_clock::time_stamp()
+void
+sc_clock::before_end_of_elaboration()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return *(const sc_time *)nullptr;
+    if (_posedgeFirst) {
+        ::sc_gem5::scheduler.schedule(_gem5UpEdge, _startTime);
+        ::sc_gem5::scheduler.schedule(_gem5DownEdge,
+                _startTime + _period * _dutyCycle);
+    } else {
+        ::sc_gem5::scheduler.schedule(_gem5DownEdge, _startTime);
+        ::sc_gem5::scheduler.schedule(_gem5UpEdge,
+                _startTime + _period * (1.0 - _dutyCycle));
+    }
 }
 
-const char *sc_clock::kind() const { return "sc_clock"; }
-
-void sc_clock::before_end_of_elaboration() {}
-
 } // namespace sc_core
index 30895ced2293a4d64a9aaf73ac134efb3becc727..3713394b68d8d20aa7b1eea092374b9f3374def9 100644 (file)
 #include "../core/sc_time.hh"
 #include "sc_signal.hh"
 
+namespace sc_gem5
+{
+
+class ClockTick;
+
+} // namespace sc_gem5
+
 namespace sc_core
 {
 
@@ -74,15 +81,28 @@ class sc_clock : public sc_signal<bool>
     // Nonstandard
     static const sc_time &time_stamp();
 
-    virtual const char *kind() const;
+    virtual const char *kind() const { return "sc_clock"; }
 
   protected:
     virtual void before_end_of_elaboration();
 
   private:
+    friend class ::sc_gem5::ClockTick;
+
     // Disabled
     sc_clock(const sc_clock &) : sc_interface(), sc_signal<bool>() {}
     sc_clock &operator = (const sc_clock &) { return *this; }
+
+    sc_time _period;
+    double _dutyCycle;
+    sc_time _startTime;
+    bool _posedgeFirst;
+
+    ::sc_gem5::ClockTick *_gem5UpEdge;
+    ::sc_gem5::ClockTick *_gem5DownEdge;
+
+    void tickUp() { sc_signal<bool>::write(true); }
+    void tickDown() { sc_signal<bool>::write(false); }
 };
 
 typedef sc_in<bool> sc_in_clk;