systemc: Implement channel updates and rework the scheduler.
authorGabe Black <gabeblack@google.com>
Thu, 5 Jul 2018 05:41:29 +0000 (22:41 -0700)
committerGabe Black <gabeblack@google.com>
Wed, 5 Sep 2018 06:04:19 +0000 (06:04 +0000)
This change implements channel updates, and also reworks the scheduler
to delegate more to the gem5 event queue by taking advantage of
event priorities to ensure things happen in the right order. There's
a lengthy comment in scheduler.hh describes how that all works.

Change-Id: I5dee71b86b2e612bb720a4429f3a72e4b7c6d01f
Reviewed-on: https://gem5-review.googlesource.com/11710
Reviewed-by: Gabe Black <gabeblack@google.com>
Maintainer: Gabe Black <gabeblack@google.com>

src/systemc/core/SConscript
src/systemc/core/channel.cc [new file with mode: 0644]
src/systemc/core/channel.hh [new file with mode: 0644]
src/systemc/core/kernel.cc
src/systemc/core/sc_prim.cc
src/systemc/core/scheduler.cc
src/systemc/core/scheduler.hh
src/systemc/ext/core/sc_prim.hh

index 0453004785018b445900c9acd509b8f6e1eef5e9..8fd5f7af93352a2ae1ce5d9b327ea5a33c8c5210 100644 (file)
@@ -30,6 +30,7 @@ Import('*')
 if env['USE_SYSTEMC']:
     SimObject('SystemC.py')
 
+    Source('channel.cc')
     Source('kernel.cc')
     Source('module.cc')
     Source('object.cc')
diff --git a/src/systemc/core/channel.cc b/src/systemc/core/channel.cc
new file mode 100644 (file)
index 0000000..4a862b8
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "systemc/core/channel.hh"
+
+#include "systemc/core/scheduler.hh"
+
+namespace sc_gem5
+{
+
+void
+Channel::requestUpdate()
+{
+    scheduler.requestUpdate(this);
+}
+
+void
+Channel::asyncRequestUpdate()
+{
+    //TODO This should probably not request an update directly.
+    scheduler.requestUpdate(this);
+}
+
+} // namespace sc_gem5
diff --git a/src/systemc/core/channel.hh b/src/systemc/core/channel.hh
new file mode 100644 (file)
index 0000000..7ce4375
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __SYSTEMC_CORE_CHANNEL_HH__
+#define __SYSTEMC_CORE_CHANNEL_HH__
+
+#include "systemc/core/list.hh"
+#include "systemc/ext/core/sc_prim.hh"
+
+namespace sc_gem5
+{
+
+class Channel : public ListNode
+{
+  public:
+    Channel(sc_core::sc_prim_channel *_sc_chan) : _sc_chan(_sc_chan) {}
+
+    virtual ~Channel() {}
+
+    void requestUpdate();
+    void asyncRequestUpdate();
+    void update() { _sc_chan->update(); }
+
+    sc_core::sc_prim_channel *sc_chan() { return _sc_chan; }
+
+  private:
+    sc_core::sc_prim_channel *_sc_chan;
+};
+
+} // namespace sc_gem5
+
+#endif  //__SYSTEMC_CORE_CHANNEL_HH__
index 82281c085ad8b1a141b1fe69797d636f01949630..e93236541dc7be53beb69c3a4601446da3c7c049 100644 (file)
 namespace SystemC
 {
 
-Kernel::Kernel(Params *params) : SimObject(params), t0Event(this) {}
+Kernel::Kernel(Params *params) :
+    SimObject(params), t0Event(this, false, EventBase::Default_Pri - 1) {}
 
 void
 Kernel::startup()
 {
     schedule(t0Event, curTick());
+    // Install ourselves as the scheduler's event manager.
+    ::sc_gem5::scheduler.setEventQueue(eventQueue());
+    // Run update once before the event queue starts.
+    ::sc_gem5::scheduler.update();
 }
 
 void
 Kernel::t0Handler()
 {
-    ::sc_gem5::scheduler.initialize();
+    // Now that the event queue has started, mark all the processes that
+    // need to be initialized as ready to run.
+    //
+    // This event has greater priority than delta notifications and so will
+    // happen before them, honoring the ordering for the initialization phase
+    // in the spec. The delta phase will happen at normal priority, and then
+    // the event which runs the processes which is at a lower priority.
+    ::sc_gem5::scheduler.initToReady();
 }
 
 } // namespace SystemC
index 4b5cf17802ec17462a993f39d747e5d58d2790c8..91befa836aa3f48aef4a63d2f0e9443b3674468c 100644 (file)
  */
 
 #include "base/logging.hh"
+#include "systemc/core/channel.hh"
 #include "systemc/ext/core/sc_prim.hh"
 
 namespace sc_core
 {
 
-const char *
-sc_prim_channel::kind() const
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return "";
-}
+sc_prim_channel::sc_prim_channel() :
+    _gem5_channel(new sc_gem5::Channel(this))
+{}
 
-sc_prim_channel::sc_prim_channel()
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
+sc_prim_channel::sc_prim_channel(const char *_name) :
+    sc_object(_name), _gem5_channel(new sc_gem5::Channel(this))
+{}
 
-sc_prim_channel::sc_prim_channel(const char *)
-{
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-}
+sc_prim_channel::~sc_prim_channel() { delete _gem5_channel; }
 
 void
 sc_prim_channel::request_update()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _gem5_channel->requestUpdate();
 }
 
 void
 sc_prim_channel::async_request_update()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    _gem5_channel->asyncRequestUpdate();
 }
 
 void
 sc_prim_channel::next_trigger()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger();
 }
 
 void
-sc_prim_channel::next_trigger(const sc_event &)
+sc_prim_channel::next_trigger(const sc_event &e)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(e);
 }
 
 void
-sc_prim_channel::next_trigger(const sc_event_or_list &)
+sc_prim_channel::next_trigger(const sc_event_or_list &eol)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(eol);
 }
 
 void
-sc_prim_channel::next_trigger(const sc_event_and_list &)
+sc_prim_channel::next_trigger(const sc_event_and_list &eal)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(eal);
 }
 
 void
-sc_prim_channel::next_trigger(const sc_time &)
+sc_prim_channel::next_trigger(const sc_time &t)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(t);
 }
 
 void
-sc_prim_channel::next_trigger(double, sc_time_unit)
+sc_prim_channel::next_trigger(double d, sc_time_unit u)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(d, u);
 }
 
 void
-sc_prim_channel::next_trigger(const sc_time &, const sc_event &)
+sc_prim_channel::next_trigger(const sc_time &t, const sc_event &e)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(t, e);
 }
 
 void
-sc_prim_channel::next_trigger(double, sc_time_unit, const sc_event &)
+sc_prim_channel::next_trigger(double d, sc_time_unit u, const sc_event &e)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(d, u, e);
 }
 
 void
-sc_prim_channel::next_trigger(const sc_time &, const sc_event_or_list &)
+sc_prim_channel::next_trigger(const sc_time &t, const sc_event_or_list &eol)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(t, eol);
 }
 
 void
-sc_prim_channel::next_trigger(double, sc_time_unit, const sc_event_or_list &)
+sc_prim_channel::next_trigger(
+        double d, sc_time_unit u, const sc_event_or_list &eol)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(d, u, eol);
 }
 
 void
-sc_prim_channel::next_trigger(const sc_time &, const sc_event_and_list &)
+sc_prim_channel::next_trigger(const sc_time &t, const sc_event_and_list &eal)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(t, eal);
 }
 
 void
-sc_prim_channel::next_trigger(double, sc_time_unit, const sc_event_and_list &)
+sc_prim_channel::next_trigger(
+        double d, sc_time_unit u, const sc_event_and_list &eal)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::next_trigger(d, u, eal);
 }
 
 bool
@@ -144,79 +140,79 @@ sc_prim_channel::timed_out()
 void
 sc_prim_channel::wait()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait();
 }
 
 void
-sc_prim_channel::wait(int)
+sc_prim_channel::wait(int i)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(i);
 }
 
 void
-sc_prim_channel::wait(const sc_event &)
+sc_prim_channel::wait(const sc_event &e)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(e);
 }
 
 void
-sc_prim_channel::wait(const sc_event_or_list &)
+sc_prim_channel::wait(const sc_event_or_list &eol)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(eol);
 }
 
 void
-sc_prim_channel::wait(const sc_event_and_list &)
+sc_prim_channel::wait(const sc_event_and_list &eal)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(eal);
 }
 
 void
-sc_prim_channel::wait(const sc_time &)
+sc_prim_channel::wait(const sc_time &t)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(t);
 }
 
 void
-sc_prim_channel::wait(double, sc_time_unit)
+sc_prim_channel::wait(double d, sc_time_unit u)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(d, u);
 }
 
 void
-sc_prim_channel::wait(const sc_time &, const sc_event &)
+sc_prim_channel::wait(const sc_time &t, const sc_event &e)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(t, e);
 }
 
 void
-sc_prim_channel::wait(double, sc_time_unit, const sc_event &)
+sc_prim_channel::wait(double d, sc_time_unit u, const sc_event &e)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(d, u, e);
 }
 
 void
-sc_prim_channel::wait(const sc_time &, const sc_event_or_list &)
+sc_prim_channel::wait(const sc_time &t, const sc_event_or_list &eol)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(t, eol);
 }
 
 void
-sc_prim_channel::wait(double, sc_time_unit, const sc_event_or_list &)
+sc_prim_channel::wait(double d, sc_time_unit u, const sc_event_or_list &eol)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(d, u, eol);
 }
 
 void
-sc_prim_channel::wait(const sc_time &, const sc_event_and_list &)
+sc_prim_channel::wait(const sc_time &t, const sc_event_and_list &eal)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(t, eal);
 }
 
 void
-sc_prim_channel::wait(double, sc_time_unit, const sc_event_and_list &)
+sc_prim_channel::wait(double d, sc_time_unit u, const sc_event_and_list &eal)
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
+    ::sc_core::wait(d, u, eal);
 }
 
 } // namespace sc_core
index 41c64f876fa8c0c16499f8b3f101b942581653a3..17e7dc43e386b623bf333277ff578bfe9c8cde1f 100644 (file)
 #include "systemc/core/scheduler.hh"
 
 #include "base/fiber.hh"
+#include "base/logging.hh"
+#include "sim/eventq.hh"
 
 namespace sc_gem5
 {
 
-Scheduler::Scheduler() : _numCycles(0), _current(nullptr) {}
+Scheduler::Scheduler() :
+    eq(nullptr), readyEvent(this, false, EventBase::Default_Pri + 1),
+    _numCycles(0), _current(nullptr)
+{}
 
 void
-Scheduler::initialize()
+Scheduler::initToReady()
 {
-    update();
-
     while (!initList.empty())
         ready(initList.getNext());
-
-    delta();
-}
-
-void
-Scheduler::runCycles()
-{
-    while (!readyList.empty()) {
-        evaluate();
-        update();
-        delta();
-    }
 }
 
 void
@@ -77,24 +68,62 @@ Scheduler::yield()
 }
 
 void
-Scheduler::evaluate()
+Scheduler::ready(Process *p)
 {
-    if (!readyList.empty())
-        _numCycles++;
+    // Clump methods together to minimize context switching.
+    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
+        readyList.pushFirst(p);
+    else
+        readyList.pushLast(p);
 
-    do {
-        yield();
-    } while (!readyList.empty());
+    scheduleReadyEvent();
 }
 
 void
-Scheduler::update()
+Scheduler::requestUpdate(Channel *c)
 {
+    updateList.pushLast(c);
+    scheduleReadyEvent();
 }
 
 void
-Scheduler::delta()
+Scheduler::scheduleReadyEvent()
 {
+    // Schedule the evaluate and update phases.
+    if (!readyEvent.scheduled()) {
+        panic_if(!eq, "Need to schedule ready, but no event manager.\n");
+        eq->schedule(&readyEvent, eq->getCurTick());
+    }
+}
+
+void
+Scheduler::runReady()
+{
+    bool empty = readyList.empty();
+
+    // The evaluation phase.
+    do {
+        yield();
+    } while (!readyList.empty());
+
+    if (!empty)
+        _numCycles++;
+
+    // The update phase.
+    update();
+
+    // The delta phase will happen naturally through the event queue.
+}
+
+void
+Scheduler::update()
+{
+    Channel *channel = updateList.getNext();
+    while (channel) {
+        channel->popListNode();
+        channel->update();
+        channel = updateList.getNext();
+    }
 }
 
 Scheduler scheduler;
index a7216231a12dc3aa09080be36867d0c543bdca05..e1ad21a576edb104221740a1c060fe7ea60d21c9 100644 (file)
@@ -30,6 +30,8 @@
 #ifndef __SYSTEMC_CORE_SCHEDULER_HH__
 #define __SYSTEMC_CORE_SCHEDULER_HH__
 
+#include "sim/eventq.hh"
+#include "systemc/core/channel.hh"
 #include "systemc/core/list.hh"
 #include "systemc/core/process.hh"
 
@@ -37,20 +39,84 @@ namespace sc_gem5
 {
 
 typedef NodeList<Process> ProcessList;
+typedef NodeList<Channel> ChannelList;
+
+/*
+ * The scheduler supports three different mechanisms, the initialization phase,
+ * delta cycles, and timed notifications.
+ *
+ * INITIALIZATION PHASE
+ *
+ * The initialization phase has three parts:
+ * 1. Run requested channel updates.
+ * 2. Make processes which need to initialize runnable (methods and threads
+ *    which didn't have dont_initialize called on them).
+ * 3. Process delta notifications.
+ *
+ * First, the Kernel SimObject calls the update() method during its startup()
+ * callback which handles the requested channel updates. The Kernel also
+ * schedules an event to be run at time 0 with a slightly elevated priority
+ * so that it happens before any "normal" event.
+ *
+ * When that t0 event happens, it calls the schedulers initToReady method
+ * which performs step 2 above. That indirectly causes the scheduler's
+ * readyEvent to be scheduled with slightly lowered priority, ensuring it
+ * happens after any "normal" event.
+ *
+ * Because delta notifications are scheduled at the standard priority, all
+ * of those events will happen next, performing step 3 above. Once they finish,
+ * if the readyEvent was scheduled above, there shouldn't be any higher
+ * priority events in front of it. When it runs, it will start the first
+ * evaluate phase of the first delta cycle.
+ *
+ * DELTA CYCLE
+ *
+ * A delta cycle has three phases within it.
+ * 1. The evaluate phase where runnable processes are allowed to run.
+ * 2. The update phase where requested channel updates hapen.
+ * 3. The delta notification phase where delta notifications happen.
+ *
+ * The readyEvent runs the first two steps of the delta cycle. It first goes
+ * through the list of runnable processes and executes them until the set is
+ * empty, and then immediately runs the update phase. Since these are all part
+ * of the same event, there's no chance for other events to intervene and
+ * break the required order above.
+ *
+ * During the update phase above, the spec forbids any action which would make
+ * a process runnable. That means that once the update phase finishes, the set
+ * of runnable processes will be empty. There may, however, have been some
+ * delta notifications/timeouts which will have been scheduled during either
+ * the evaluate or update phase above. Because those are scheduled at the
+ * normal priority, they will now happen together until there aren't any
+ * delta events left.
+ *
+ * If any processes became runnable during the delta notification phase, the
+ * readyEvent will have been scheduled and will have been waiting patiently
+ * behind the delta notification events. That will now run, effectively
+ * starting the next delta cycle.
+ *
+ * TIMED NOTIFICATION PHASE
+ *
+ * If no processes became runnable, the event queue will continue to process
+ * events until it comes across a timed notification, aka a notification
+ * scheduled to happen in the future. Like delta notification events, those
+ * will all happen together since the readyEvent priority is lower,
+ * potentially marking new processes as ready. Once these events finish, the
+ * readyEvent may run, starting the next delta cycle.
+ */
 
 class Scheduler
 {
   public:
     Scheduler();
 
+    const std::string name() const { return "systemc_scheduler"; }
+
     uint64_t numCycles() { return _numCycles; }
     Process *current() { return _current; }
 
-    // Run the initialization phase.
-    void initialize();
-
-    // Run delta cycles until time needs to advance.
-    void runCycles();
+    // Mark processes that need to be initialized as ready.
+    void initToReady();
 
     // Put a process on the list of processes to be initialized.
     void init(Process *p) { initList.pushLast(p); }
@@ -59,15 +125,10 @@ class Scheduler
     void yield();
 
     // Put a process on the ready list.
-    void
-    ready(Process *p)
-    {
-        // Clump methods together to minimize context switching.
-        if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
-            readyList.pushFirst(p);
-        else
-            readyList.pushLast(p);
-    }
+    void ready(Process *p);
+
+    // Schedule an update for a given channel.
+    void requestUpdate(Channel *c);
 
     // Run the given process immediately, preempting whatever may be running.
     void
@@ -81,7 +142,22 @@ class Scheduler
         yield();
     }
 
+    // Set an event queue for scheduling events.
+    void setEventQueue(EventQueue *_eq) { eq = _eq; }
+
+    // Retrieve the event queue.
+    EventQueue &eventQueue() const { return *eq; }
+
+    // Run scheduled channel updates.
+    void update();
+
   private:
+    EventQueue *eq;
+
+    void runReady();
+    EventWrapper<Scheduler, &Scheduler::runReady> readyEvent;
+    void scheduleReadyEvent();
+
     uint64_t _numCycles;
 
     Process *_current;
@@ -89,9 +165,7 @@ class Scheduler
     ProcessList initList;
     ProcessList readyList;
 
-    void evaluate();
-    void update();
-    void delta();
+    ChannelList updateList;
 };
 
 extern Scheduler scheduler;
index 2348f453d969443acd14742b83f88da4c943bb94..106489280224b021ef413fcdcf5a59404fcfb7c0 100644 (file)
 #include "sc_object.hh"
 #include "sc_time.hh"
 
+namespace sc_gem5
+{
+
+class Channel;
+
+} // namespace sc_gem5
+
 namespace sc_core
 {
 
@@ -43,12 +50,12 @@ class sc_event_or_list;
 class sc_prim_channel : public sc_object
 {
   public:
-    virtual const char *kind() const;
+    virtual const char *kind() const { return "sc_prim_channel"; }
 
   protected:
     sc_prim_channel();
     explicit sc_prim_channel(const char *);
-    virtual ~sc_prim_channel() {}
+    virtual ~sc_prim_channel();
 
     void request_update();
     void async_request_update();
@@ -93,6 +100,9 @@ class sc_prim_channel : public sc_object
     // Disabled
     sc_prim_channel(const sc_prim_channel &);
     sc_prim_channel &operator = (const sc_prim_channel &);
+
+    friend class sc_gem5::Channel;
+    sc_gem5::Channel *_gem5_channel;
 };
 
 } // namespace sc_core