From 743a1b5cdd8e607f2e1bb5ad182047c512eae3f8 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 18 Jul 2018 20:59:56 -0700 Subject: 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 Maintainer: Gabe Black --- src/systemc/core/scheduler.hh | 72 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) (limited to 'src/systemc/core/scheduler.hh') diff --git a/src/systemc/core/scheduler.hh b/src/systemc/core/scheduler.hh index 5db5556ae..3ac7f419f 100644 --- a/src/systemc/core/scheduler.hh +++ b/src/systemc/core/scheduler.hh @@ -179,8 +179,75 @@ class Scheduler // 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 @@ class Scheduler static Priority MaxTickPriority = DefaultPriority + 3; EventQueue *eq; + std::map pendingTicks; void runReady(); EventWrapper readyEvent; -- cgit v1.2.3