Gabe Black has submitted this change and it was merged. ( https://gem5-review.googlesource.com/c/public/gem5/+/12032 )

Change subject: systemc: Implement pending activity related functions
......................................................................

systemc: Implement pending activity related functions

Track the number of notifications/timeouts that are scheduled at any
given time. This lets us implement sc_pending_activity_at_current_time,
sc_pending_activity_at_future_time, and sc_time_to_pending_activity.

Change-Id: Ia3fcd29bdbfe1a6c77eb52ce4836982d4705263c
Reviewed-on: https://gem5-review.googlesource.com/12032
Reviewed-by: Gabe Black <[email protected]>
Maintainer: Gabe Black <[email protected]>
---
M src/systemc/core/event.cc
M src/systemc/core/event.hh
M src/systemc/core/process.cc
M src/systemc/core/process.hh
M src/systemc/core/sc_main.cc
M src/systemc/core/scheduler.cc
M src/systemc/core/scheduler.hh
7 files changed, 110 insertions(+), 30 deletions(-)

Approvals:
  Gabe Black: Looks good to me, approved; Looks good to me, approved



diff --git a/src/systemc/core/event.cc b/src/systemc/core/event.cc
index 5008074..1623cf9 100644
--- a/src/systemc/core/event.cc
+++ b/src/systemc/core/event.cc
@@ -43,7 +43,7 @@
 Event::Event(sc_core::sc_event *_sc_event) : Event(_sc_event, "") {}

 Event::Event(sc_core::sc_event *_sc_event, const char *_basename) :
-    _sc_event(_sc_event), _basename(_basename), delayedNotify(this)
+    _sc_event(_sc_event), _basename(_basename), delayedNotifyEvent(this)
 {
     Module *p = currentModule();

@@ -121,28 +121,34 @@
 }

 void
+Event::delayedNotify()
+{
+    scheduler.eventHappened();
+    notify();
+}
+
+void
 Event::notify(const sc_core::sc_time &t)
 {
     //XXX We're assuming the systemc time resolution is in ps.
-    Tick new_tick = t.value() * SimClock::Int::ps +
-        scheduler.eventQueue().getCurTick();
-    if (delayedNotify.scheduled()) {
-        Tick old_tick = delayedNotify.when();
+    Tick new_tick = t.value() * SimClock::Int::ps + scheduler.getCurTick();
+    if (delayedNotifyEvent.scheduled()) {
+        Tick old_tick = delayedNotifyEvent.when();

         if (new_tick >= old_tick)
             return;

-        scheduler.eventQueue().deschedule(&delayedNotify);
+        scheduler.deschedule(&delayedNotifyEvent);
     }

-    scheduler.eventQueue().schedule(&delayedNotify, new_tick);
+    scheduler.schedule(&delayedNotifyEvent, new_tick);
 }

 void
 Event::cancel()
 {
-    if (delayedNotify.scheduled())
-        scheduler.eventQueue().deschedule(&delayedNotify);
+    if (delayedNotifyEvent.scheduled())
+        scheduler.deschedule(&delayedNotifyEvent);
 }

 bool
diff --git a/src/systemc/core/event.hh b/src/systemc/core/event.hh
index a9d3183..6d2f46d 100644
--- a/src/systemc/core/event.hh
+++ b/src/systemc/core/event.hh
@@ -105,7 +105,8 @@
     sc_core::sc_object *parent;
     EventsIt parentIt;

-    EventWrapper<Event, &Event::notify> delayedNotify;
+    void delayedNotify();
+    EventWrapper<Event, &Event::delayedNotify> delayedNotifyEvent;

     mutable std::set<Sensitivity *> sensitivities;
 };
diff --git a/src/systemc/core/process.cc b/src/systemc/core/process.cc
index 7ed187f..ad297a2 100644
--- a/src/systemc/core/process.cc
+++ b/src/systemc/core/process.cc
@@ -37,16 +37,23 @@
 {

 SensitivityTimeout::SensitivityTimeout(Process *p, ::sc_core::sc_time t) :
-    Sensitivity(p), timeoutEvent(this), timeout(t)
+    Sensitivity(p), timeoutEvent(this), time(t)
 {
-    Tick when = scheduler.eventQueue().getCurTick() + timeout.value();
-    scheduler.eventQueue().schedule(&timeoutEvent, when);
+    Tick when = scheduler.getCurTick() + time.value();
+    scheduler.schedule(&timeoutEvent, when);
 }

 SensitivityTimeout::~SensitivityTimeout()
 {
     if (timeoutEvent.scheduled())
-        scheduler.eventQueue().deschedule(&timeoutEvent);
+        scheduler.deschedule(&timeoutEvent);
+}
+
+void
+SensitivityTimeout::timeout()
+{
+    scheduler.eventHappened();
+    notify();
 }

 SensitivityEvent::SensitivityEvent(
diff --git a/src/systemc/core/process.hh b/src/systemc/core/process.hh
index 7c75d62..afdbb37 100644
--- a/src/systemc/core/process.hh
+++ b/src/systemc/core/process.hh
@@ -66,8 +66,10 @@
 class SensitivityTimeout : virtual public Sensitivity
 {
   private:
-    EventWrapper<Sensitivity, &Sensitivity::notify> timeoutEvent;
-    ::sc_core::sc_time timeout;
+    void timeout();
+    EventWrapper<SensitivityTimeout,
+        &SensitivityTimeout::timeout> timeoutEvent;
+    ::sc_core::sc_time time;

   public:
     SensitivityTimeout(Process *p, ::sc_core::sc_time t);
@@ -98,7 +100,7 @@
             Process *p, const ::sc_core::sc_event_and_list *list);
     ~SensitivityEventAndList();

-    virtual void notifyWork(Event *e) override;
+    void notifyWork(Event *e) override;
 };

 class SensitivityEventOrList : virtual public Sensitivity
diff --git a/src/systemc/core/sc_main.cc b/src/systemc/core/sc_main.cc
index 120bbf9..103b303 100644
--- a/src/systemc/core/sc_main.cc
+++ b/src/systemc/core/sc_main.cc
@@ -140,7 +140,7 @@
 void
 sc_start()
 {
-    Tick now = curEventQueue() ? curEventQueue()->getCurTick() : 0;
+    Tick now = ::sc_gem5::scheduler.getCurTick();
     sc_start(sc_time::from_value(MaxTick - now), SC_EXIT_ON_STARVATION);
 }

@@ -156,7 +156,7 @@
 {
     _status = SC_RUNNING;

-    Tick now = curEventQueue() ? curEventQueue()->getCurTick() : 0;
+    Tick now = ::sc_gem5::scheduler.getCurTick();
     ::sc_gem5::scheduler.start(now + time.value(), p == SC_RUN_TO_TIME);

     if (::sc_gem5::scheduler.paused())
@@ -200,7 +200,7 @@
 sc_time_stamp()
 {
     static sc_time tstamp;
-    Tick tick = sc_gem5::scheduler.eventQueue().getCurTick();
+    Tick tick = ::sc_gem5::scheduler.getCurTick();
     //XXX We're assuming the systemc time resolution is in ps.
     tstamp = sc_time::from_value(tick / SimClock::Int::ps);
     return tstamp;
@@ -221,15 +221,13 @@
 bool
 sc_pending_activity_at_current_time()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return false;
+    return ::sc_gem5::scheduler.pendingCurr();
 }

 bool
 sc_pending_activity_at_future_time()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return false;
+    return ::sc_gem5::scheduler.pendingFuture();
 }

 bool
@@ -242,8 +240,7 @@
 sc_time
 sc_time_to_pending_activity()
 {
-    warn("%s not implemented.\n", __PRETTY_FUNCTION__);
-    return sc_time();
+    return sc_time::from_value(::sc_gem5::scheduler.timeToPending());
 }

 sc_status
diff --git a/src/systemc/core/scheduler.cc b/src/systemc/core/scheduler.cc
index e3d275bb..eab6f48 100644
--- a/src/systemc/core/scheduler.cc
+++ b/src/systemc/core/scheduler.cc
@@ -37,8 +37,7 @@
 {

 Scheduler::Scheduler() :
-    eq(nullptr), _pendingCurr(0), _pendingFuture(0),
-    readyEvent(this, false, ReadyPriority),
+    eq(nullptr), readyEvent(this, false, ReadyPriority),
     pauseEvent(this, false, PausePriority),
     stopEvent(this, false, StopPriority),
     scMain(nullptr), _started(false), _paused(false), _stopped(false),
diff --git a/src/systemc/core/scheduler.hh b/src/systemc/core/scheduler.hh
index 5db5556..3ac7f41 100644
--- a/src/systemc/core/scheduler.hh
+++ b/src/systemc/core/scheduler.hh
@@ -179,8 +179,75 @@
     // Set an event queue for scheduling events.
     void setEventQueue(EventQueue *_eq) { eq = _eq; }

-    // Retrieve the event queue.
-    EventQueue &eventQueue() const { return *eq; }
+    // Get the current time according to gem5.
+    Tick getCurTick() { return eq ? eq->getCurTick() : 0; }
+
+    // For scheduling delayed/timed notifications/timeouts.
+    void
+    schedule(::Event *event, Tick tick)
+    {
+        pendingTicks[tick]++;
+        eq->schedule(event, tick);
+    }
+
+    // For descheduling delayed/timed notifications/timeouts.
+    void
+    deschedule(::Event *event)
+    {
+        auto it = pendingTicks.find(event->when());
+        if (--it->second == 0)
+            pendingTicks.erase(it);
+        eq->deschedule(event);
+    }
+
+    // Tell the scheduler than an event fired for bookkeeping purposes.
+    void
+    eventHappened()
+    {
+        auto it = pendingTicks.begin();
+        if (--it->second == 0)
+            pendingTicks.erase(it);
+    }
+
+    // Pending activity ignores gem5 activity, much like how a systemc
+ // simulation wouldn't know about asynchronous external events (socket IO
+    // for instance) that might happen before time advances in a pure
+ // systemc simulation. Also the spec lists what specific types of pending
+    // activity needs to be counted, which obviously doesn't include gem5
+    // events.
+
+    // Return whether there's pending systemc activity at this time.
+    bool
+    pendingCurr()
+    {
+        if (!readyList.empty() || !updateList.empty())
+            return true;
+        return pendingTicks.size() &&
+            pendingTicks.begin()->first == getCurTick();
+    }
+
+    // Return whether there are pending timed notifications or timeouts.
+    bool
+    pendingFuture()
+    {
+        switch (pendingTicks.size()) {
+          case 0: return false;
+          case 1: return pendingTicks.begin()->first > getCurTick();
+          default: return true;
+        }
+    }
+
+ // Return how many ticks there are until the first pending event, if any.
+    Tick
+    timeToPending()
+    {
+        if (!readyList.empty() || !updateList.empty())
+            return 0;
+        else if (pendingTicks.size())
+            return pendingTicks.begin()->first - getCurTick();
+        else
+            return MaxTick - getCurTick();
+    }

     // Run scheduled channel updates.
     void update();
@@ -205,6 +272,7 @@
     static Priority MaxTickPriority = DefaultPriority + 3;

     EventQueue *eq;
+    std::map<Tick, int> pendingTicks;

     void runReady();
     EventWrapper<Scheduler, &Scheduler::runReady> readyEvent;

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/12032
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: Ia3fcd29bdbfe1a6c77eb52ce4836982d4705263c
Gerrit-Change-Number: 12032
Gerrit-PatchSet: 7
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-Reviewer: Andreas Sandberg <[email protected]>
Gerrit-Reviewer: Gabe Black <[email protected]>
Gerrit-Reviewer: Jason Lowe-Power <[email protected]>
Gerrit-Reviewer: Matthias Jung <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to