7.7.3 sg::SchedulerInterfaceForComponents class

This section describes the main scheduler interface class.

About sg::SchedulerInterfaceForComponents

The modeling components use this interface class, which gives access to all other parts of the Scheduler API, directly or indirectly. The scheduler must implement this class.

// Main scheduler interface class
class sg::SchedulerInterfaceForComponents
    static eslapi::if_name_t IFNAME() { return "sg.SchedulerInterfaceForComponents"; }
    static eslapi::if_rev_t IFREVISION() { return 1; }
    virtual eslapi::CAInterface * ObtainInterface(eslapi::if_name_t, eslapi::if_rev_t, eslapi::if_rev_t *) = 0;
    virtual sg::Timer * createTimer(const char *, sg::TimerCallback *) = 0;
    virtual sg::SchedulerThread * createThread(const char *, sg::SchedulerRunnable *) = 0;
    virtual sg::SchedulerThread * currentThread();
    virtual sg::ThreadSignal * createThreadSignal(const char *) = 0;
    virtual void wait(sg::ticks_t);
    virtual void wait(sg::ThreadSignal *) = 0;
    virtual void setGlobalQuantum(sg::ticks_t);
    virtual sg::ticks_t getGlobalQuantum(sg::Tag<sg::ticks_t> *);
    virtual double getGlobalQuantum();
    virtual void setMinSyncLatency(sg::ticks_t);
    virtual sg::ticks_t getMinSyncLatency(sg::Tag<sg::ticks_t> *);
    virtual double getMinSyncLatency();
    virtual void addSynchronisationPoint(sg::ticks_t);
    virtual sg::ticks_t getNextSyncPoint(sg::Tag<sg::ticks_t> *);
    virtual double getNextSyncPoint();
    virtual void getNextSyncRange(sg::ticks_t &, sg::ticks_t &);
    virtual void getNextSyncRange(double&, double&);
    virtual void addCallback(sg::SchedulerCallback *) = 0;
    virtual void removeCallback(sg::SchedulerCallback *) = 0;
    virtual sg::ticks_t getCurrentSimulatedTime(sg::Tag<sg::ticks_t> *);
    virtual double getCurrentSimulatedTime();
    virtual double getSimulatedTimeResolution();
    virtual void setSimulatedTimeResolution(double resolution);
    virtual void stopRequest() = 0;
    virtual void stopAcknowledge(sg::SchedulerRunnable *) = 0;


Pass a null pointer to the extra Tag<> argument in getGlobalQuantum(), getMinSyncLatency(), getNextSyncPoint(), and getCurrentSimulatedTime().

Arm deprecates these API functions:

virtual void wait(sg::ticks_t, sg::FrequencySource *)
virtual void setGlobalQuantum(sg::ticks_t, sg::FrequencySource *)
virtual void setMinSyncLatency(sg::ticks_t, sg::FrequencySource *)
virtual void addSynchronisationPoint(sg::ticks_t, sg::FrequencySource *)

Arm deprecates classes sg::FrequencySource and sg::FrequencyObserver. Modeling components must not use these classes to directly communicate with the Scheduler API. Use the sg::Time class instead.

Modeling components use this interface to create threads, asynchronous and timed events, system synchronization points, and to request a simulation stop. Examples of components that access this interface are:

  • CT core models.
  • Timer peripherals.
  • Peripheral components with timing or that indicate system synchronization points.
  • Peripheral components that can stop the simulation for certain conditions (external breakpoints).
  • GUI components.

Passive components that do not interact with the scheduler (and that do not need explicit scheduling) usually do not access this interface.

eslapi::CAInterface and eslapi::ObtainInterface

The CAInterface base class and the ObtainInterface() function make the interface discoverable at runtime through a runtime mechanism. All interfaces in Fast Models that must be discoverable at runtime derive from CAInterface.

The functions IFNAME(), IFREVISION(), and ObtainInterface() belong to the base class eslapi::CAInterface. IFNAME() and IFREVISION() return static information (name and revision) about the interface (not the interface implementation). An implementation of the interface cannot re-implement these functions. To access this interface, code must pass these two values to the ObtainInterface() function to acquire the SchedulerInterfaceForComponents.

Use ObtainInterface() to access the interfaces that the scheduler provides. As a minimum requirement, the implementation of ObtainInterface() must provide the SchedulerInterfaceForComponents interface itself and also the eslapi::CAInterface interface. The easiest way to provide these interfaces to use the class eslapi::CAInterfaceRegistry and register these two interfaces and forward all ObtainInterface() calls to this registry. See the default implementation of the Scheduler API over SystemC for an example.


CAInterface and ObtainInterface() are not part of the scheduler functionality but rather of the simulation infrastructure. The information here is what is necessary to understand and implement ObtainInterface(). For more details on the eslapi::CAInterface class, see the header file $PVLIB_HOME/include/fmruntime/eslapi/CAInterface.h.


This method schedules a callback in the simulation thread. AsyncSignal uses it.

virtual void addCallback(SchedulerCallback *callback)=0;
Callback object to call. If callback is NULL, the call has no effect.

Any host thread can call this method. It is thread safe. It is always the simulation thread (host thread which runs the simulation) that calls the callback function (callback->schedulerCallback()). The scheduler calls the callback function when it can respond to the addCallback() function.

Multiple callbacks might be pending. The scheduler can call them in any order. Do not call addCallback() or removeCallback() from a callback function.

Callbacks automatically vanish once called. Removing them deliberately is not necessary unless they become invalid, for example on the destruction of the object implementing the callback function.


This method adds synchronization points.

virtual void addSynchronisationPoint(ticks_t ticks);
Simulated time for synchronization relative to the current simulated time, in ticks relative to simulated time resolution.

Modeling components can call this function to hint to the scheduler when a potentially useful system synchronization point will occur. The scheduler uses this information to determine the quantum sizes of threads.

Calling this function again adds another synchronization point.

Synchronization points automatically vanish when reached.


CT core models and modeling components call this method to create threads. This method returns an object implementing SchedulerThread. (Not NULL except when runnable is NULL.)

virtual SchedulerThread *createThread(const char *name, SchedulerRunnable *runnable)=0;
Instance name of the thread. Ideally, the hierarchical name of the component that owns the thread is included in the name. If name is NULL, it receives the name '(anonymous thread)'. The function makes a copy of name.
Object that implements the SchedulerRunnable interface. This object is the one that contains the actual thread functionality. The returned thread uses this interface to communicate with the thread implementation in the modeling component. If runnable is NULL, the call returns NULL, which has no effect.

Having created the thread, start it with a call to SchedulerThread::start().

Destroying the returned object with the SchedulerThread destructor might not kill the thread.


CT core models use this method to create thread signals. A thread signal is a nonschedulable event that threads wait for. Giving the signal schedules all waiting threads to run.

virtual ThreadSignal* createThreadSignal(const char* name)=0;
Instance name of the thread. Ideally, the hierarchical name of the component that owns the thread is included in the name. If name is NULL, it receives the name '(anonymous thread signal)'. The function makes a copy of name.

Destroying the returned object while threads are waiting for it leaves the threads unscheduled.


Modeling components call this method to create objects of class Timer. They use timers to trigger events in the future (one-shot or repeating events).

virtual Timer* createTimer(const char* name, TimerCallback* callback)=0;


This method returns the currently running scheduler thread, which createThread() created, or null if not in any threadProc() call.

virtual SchedulerThread* currentThread();


This method returns the simulated time in ticks relative to simulated time resolution, since the creation of the scheduler. ClockDivider and MasterClock(ClockSignalProtocol::currentTicks()) use it.

virtual ticks_t getCurrentSimulatedTime(Tag<ticks_t>*);

This clock accurately reflects the time on the last timer callback invocation or the last return from SchedulerThread::wait(), whichever was last. The return values monotonically increase over (real or simulated) time.


This method returns the global quantum in ticks relative to simulated time resolution.

virtual ticks_t getGlobalQuantum(Tag<ticks_t>*);


This method returns the minimum synchronization latency in ticks relative to simulated time resolution.

virtual ticks_t getMinSyncLatency(Tag<ticks_t>*);


This method returns the next synchronization point relative to the current simulated time. The next synchronization point is expressed in ticks relative to simulated time resolution.

virtual ticks_t getNextSyncPoint(Tag<ticks_t>*);

Modeling components can call this function for a hint about when a potentially useful system synchronization point will occur. Core threads use this information to determine when to synchronize.


This method returns the simulated time resolution in seconds.

virtual double getSimulatedTimeResolution();


This method removes all callbacks that are scheduled using addCallback() for this callback object. AsyncSignal uses it.

virtual void removeCallback(SchedulerCallback *callback)=0;
The callback object to remove. If callback is NULL, an unknown callback object, or a called callback, then the call has no effect.

Any host thread can call this method. It is thread safe.

The scheduler will not call the specified callback after this function returns. It can, however, call it while execution control is inside this function.

Callbacks automatically vanish after being called. Removing them deliberately is not necessary unless they become invalid, for example on the destruction of the object implementing the callback function.


This method sets the global quantum.

virtual void setGlobalQuantum(ticks_t ticks);
Global quantum value, relative to simulated time resolution. The global quantum is the maximum time that a thread can run ahead of simulation time.

All threads must synchronize on timing points that are multiples of the global quantum.


This method sets the minimum synchronization latency.

virtual void setMinSyncLatency(ticks_t ticks);
Minimum synchronization latency value, relative to simulated time resolution.

The minimum synchronization latency helps to ensure that sufficient simulated time has passed between two synchronization points for synchronization to be efficient. A small latency increases accuracy but decreases simulation speed. A large latency decreases accuracy but increases simulation speed.

The scheduler uses this information to set the minimum synchronization latency of threads with sg::SchedulerRunnable::setThreadProperty(), and to compute the next synchronization point as returned by getNextSyncPoint().


This method sets the simulated time resolution in seconds.

virtual void setSimulatedTimeResolution(double resolution);
Simulated time resolution in seconds.

Setting simulated time resolution after the start of the simulation or after setting timers is not possible.


This function blocks the simulation thread until being told to resume.

virtual void stopAcknowledge(SchedulerRunnable *runnable)=0;
Pointer to the runnable instance that called this function, or NULL when not called from a runnable instance. If not NULL this function calls runnable->clearStopRequest() once it is safe to do so (with respect to non-simulation host threads).

CT core models call this function from within the simulation thread in response to a call to stopRequest() or spontaneously (for example, breakpoint hit, debugger stop). The call must always be from the simulation thread. The scheduler must block inside this function. The function must return when the simulation is to resume.

The scheduler usually implements a thread-safe mechanism in this function that allows blocking and resuming of the simulation thread from another host thread (usually the debugger thread).

Calling this function from a nonsimulation host thread is wrong by design and is forbidden.

This function must clear the stop request that led to calling this function by calling runnable->clearStopRequest().

This function must have no effects other than blocking the simulation thread.


This function requests the simulation of the whole system to stop (pause).

virtual void stopRequest()=0;

You can call this function from any host thread, whether the simulation is running or not. The function returns immediately, possibly before the simulation stops. This function will not block the caller until the simulation stops. The simulation stops as soon as possible, depending on the syncLevel of the threads in the system. The simulation calls the function stopAcknowledge(), which blocks the simulation thread to pause the simulation. This function must not call stopAcknowledge() directly. It must only set up the simulation to stop at the next sync point, defined by the syncLevels in the system. Reset this state with stopAcknowledge(), which calls SchedulerRunnable::clearStopRequest().

Debuggers and modeling components such as CT cores and peripherals use this function to stop the simulation from within the simulation thread (for example for external breakpoints) and also asynchronously from the debugger thread. Calling this function again (from any host thread) before stopAcknowledge() has reset the stop request, using SchedulerRunnable::clearStopRequest() is harmless. The simulation only stops once.


The simulation can stop (that is, call stopAcknowledge()) spontaneously without a previous stopRequest(). This stop happens for example when a modeling component hits a breakpoint. A stopRequest() is sufficient, but not necessary, to stop the simulation.

The scheduler implementation of this function is to forward this stopRequest() to the running runnable object, but only for stopRequest() calls from the simulation thread. When the runnable object accepts the stopRequest() (SchedulerRunnable::stopRequest() returns true), the scheduler need do nothing more because the runnable object will respond with a stopAcknowledge() call. If the runnable object did not accept the stopRequest() (SchedulerRunnable::stopRequest() returns false) or if this function call is outside of the context of a runnable object (for example, from a call-back function) or from a non-simulation host thread, then the scheduler is responsible for handling the stopRequest() itself by calling stopAcknowledge() as soon as possible.

The stop handling mechanism should not change the scheduling order or model behavior (non-intrusive debugging).


This method waits on a thread signal.

virtual void wait(ThreadSignal* threadSignal)=0;
Thread signal object to wait for. A call with threadSignal of NULL is valid, but has no effect.

wait() blocks the current thread until it receives ThreadSignal::notify(). This function returns when the calling thread can continue to run.

Only call this method from within a SchedulerRunnable::threadProc() context. Calling this method from outside of a threadProc() context is valid, but has no effect.


This method blocks the running thread and runs other threads for a specified time.

virtual void wait(ticks_t ticks);
Time to wait for, in timebase units. ticks can be 0.

Only call this method from within a SchedulerRunnable::threadProc() context. Calls from outside of a threadProc() context are valid, but have no effect.

This method blocks a thread for a time while the other threads run. It returns when the calling thread is to continue, at the co-routine switching point. Typically, a thread calls wait(ticks) in its loop when it completes ticks ticks of work. ticks is a "quantum".

Non-ConfidentialPDF file icon PDF version100965_1180_00_en
Copyright © 2014–2019 Arm Limited or its affiliates. All rights reserved.