32a33,35
> #include <functional>
> #include <map>
> #include <set>
35a39
> #include "sim/core.hh"
39a44
> #include "systemc/core/sched_event.hh"
84c89
< * The readyEvent runs the first two steps of the delta cycle. It first goes
---
> * The readyEvent runs all three steps of the delta cycle. It first goes
94,96c99,100
< * 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.
---
> * the evaluate or update phase above. Those will have been accumulated in the
> * scheduler, and are now all executed.
99,101c103,104
< * 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.
---
> * readyEvent will have been scheduled and will be waiting and ready to run
> * again, effectively starting the next delta cycle.
106,110c109,113
< * 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.
---
> * events until it comes across an event which represents all the timed
> * notifications which are supposed to happen at a particular time. The object
> * which tracks them will execute all those notifications, and then destroy
> * itself. If the readyEvent is now ready to run, the next delta cycle will
> * start.
144a148,160
> typedef std::set<ScEvent *> ScEvents;
>
> class TimeSlot : public ::Event
> {
> public:
> TimeSlot() : ::Event(Default_Pri, AutoDelete) {}
>
> ScEvents events;
> void process();
> };
>
> typedef std::map<Tick, TimeSlot *> TimeSlots;
>
187a204,210
> Tick
> delayed(const ::sc_core::sc_time &delay)
> {
> //XXX We're assuming the systemc time resolution is in ps.
> return getCurTick() + delay.value() * SimClock::Int::ps;
> }
>
190c213
< schedule(::Event *event, Tick tick)
---
> schedule(ScEvent *event, const ::sc_core::sc_time &delay)
192c215,216
< pendingTicks[tick]++;
---
> Tick tick = delayed(delay);
> event->schedule(tick);
194,197c218,234
< if (initReady)
< eq->schedule(event, tick);
< else
< eventsToSchedule[event] = tick;
---
> // Delta notification/timeout.
> if (delay.value() == 0) {
> deltas.insert(event);
> scheduleReadyEvent();
> return;
> }
>
> // Timed notification/timeout.
> TimeSlot *&ts = timeSlots[tick];
> if (!ts) {
> ts = new TimeSlot;
> if (initReady)
> eq->schedule(ts, tick);
> else
> eventsToSchedule[ts] = tick;
> }
> ts->events.insert(event);
202c239
< deschedule(::Event *event)
---
> deschedule(ScEvent *event)
204,206c241,246
< auto it = pendingTicks.find(event->when());
< if (--it->second == 0)
< pendingTicks.erase(it);
---
> if (event->when() == getCurTick()) {
> // Remove from delta notifications.
> deltas.erase(event);
> event->deschedule();
> return;
> }
208,211c248,264
< if (initReady)
< eq->deschedule(event);
< else
< eventsToSchedule.erase(event);
---
> // Timed notification/timeout.
> auto tsit = timeSlots.find(event->when());
> panic_if(tsit == timeSlots.end(),
> "Descheduling event at time with no events.");
> TimeSlot *ts = tsit->second;
> ScEvents &events = ts->events;
> events.erase(event);
> event->deschedule();
>
> // If no more events are happening at this time slot, get rid of it.
> if (events.empty()) {
> if (initReady)
> eq->deschedule(ts);
> else
> eventsToSchedule.erase(ts);
> timeSlots.erase(tsit);
> }
214d266
< // Tell the scheduler than an event fired for bookkeeping purposes.
216c268
< eventHappened()
---
> completeTimeSlot(TimeSlot *ts)
218,223c270,271
< auto it = pendingTicks.begin();
< if (--it->second == 0)
< pendingTicks.erase(it);
<
< if (starved() && !runToTime)
< scheduleStarvationEvent();
---
> assert(ts == timeSlots.begin()->second);
> timeSlots.erase(timeSlots.begin());
237,240c285
< if (!readyList.empty() || !updateList.empty())
< return true;
< return pendingTicks.size() &&
< pendingTicks.begin()->first == getCurTick();
---
> return !readyList.empty() || !updateList.empty() || !deltas.empty();
247,251c292
< switch (pendingTicks.size()) {
< case 0: return false;
< case 1: return pendingTicks.begin()->first > getCurTick();
< default: return true;
< }
---
> return !timeSlots.empty();
258c299
< if (!readyList.empty() || !updateList.empty())
---
> if (pendingCurr())
260,263c301,303
< else if (pendingTicks.size())
< return pendingTicks.begin()->first - getCurTick();
< else
< return MaxTick - getCurTick();
---
> if (pendingFuture())
> return timeSlots.begin()->first - getCurTick();
> return MaxTick - getCurTick();
291d330
< std::map<Tick, int> pendingTicks;
292a332,334
> ScEvents deltas;
> TimeSlots timeSlots;
>
306,308c348,349
< return (readyList.empty() && updateList.empty() &&
< (pendingTicks.empty() ||
< pendingTicks.begin()->first > maxTick) &&
---
> return (readyList.empty() && updateList.empty() && deltas.empty() &&
> (timeSlots.empty() || timeSlots.begin()->first > maxTick) &&
339a381,388
> inline void
> Scheduler::TimeSlot::process()
> {
> for (auto &e: events)
> e->run();
> scheduler.completeTimeSlot(this);
> }
>