Core Library¶
The core library (schedsim::core) provides the simulation engine, hardware
model, and foundational types. It has no dependencies on scheduling algorithms
or I/O formats.
Types¶
The core type system uses strong wrappers for physical quantities.
Duration and TimePoint store nanosecond-precision values as int64_t;
construction goes through named bridge functions rather than public constructors.
Duration¶
-
class Duration¶
Time interval represented as an integer nanosecond count.
Duration wraps an
int64_tnanosecond value with a private constructor. All construction goes through named factories or bridge functions, ensuring explicit conversions between seconds (double) and nanoseconds (int64_t).Arithmetic between two Durations yields a Duration; dividing Duration by Duration yields a
double(viaduration_ratio), not an integer.See also
duration_from_seconds, duration_from_nanoseconds, duration_to_seconds
See also
Public Functions
-
inline constexpr Duration() noexcept¶
Default constructor: zero duration.
Needed for aggregate initialization and container value types.
-
inline double seconds() const noexcept¶
Convert to seconds (double).
See also
duration_to_seconds
- Returns:
Duration value in seconds.
-
inline int64_t nanoseconds() const noexcept¶
Return the raw nanosecond count.
See also
duration_to_nanoseconds
- Returns:
Duration value in nanoseconds.
-
inline Duration operator+(Duration rhs) const noexcept¶
Add two durations.
- Parameters:
rhs – Duration to add.
- Returns:
Sum of the two durations.
-
inline Duration operator-(Duration rhs) const noexcept¶
Subtract a duration.
- Parameters:
rhs – Duration to subtract.
- Returns:
Difference of the two durations.
-
inline Duration &operator+=(Duration rhs) noexcept¶
Add a duration in place.
- Parameters:
rhs – Duration to add.
- Returns:
Reference to this.
-
inline constexpr Duration() noexcept¶
TimePoint¶
-
class TimePoint¶
Absolute simulation time as a Duration offset from epoch (time zero).
TimePoint supports arithmetic with Duration (TimePoint +/- Duration yields TimePoint) and differencing (TimePoint - TimePoint yields Duration). Two TimePoints cannot be added.
See also
time_from_seconds, time_to_seconds, Duration
Public Functions
-
inline constexpr TimePoint() noexcept¶
Default constructor: epoch (time zero).
Needed for containers like
std::mapandstd::unordered_map.
-
inline Duration time_since_epoch() const noexcept¶
Return the duration elapsed since epoch.
- Returns:
Duration from epoch to this time point.
-
inline TimePoint operator+(Duration d) const noexcept¶
Advance a time point by a duration.
- Parameters:
d – Duration to add.
- Returns:
New time point offset by
d.
-
inline TimePoint operator-(Duration d) const noexcept¶
Retreat a time point by a duration.
- Parameters:
d – Duration to subtract.
- Returns:
New time point offset backward by
d.
-
inline TimePoint &operator+=(Duration d) noexcept¶
Advance this time point in place.
- Parameters:
d – Duration to add.
- Returns:
Reference to this.
-
inline constexpr TimePoint() noexcept¶
Bridge Functions¶
-
Duration schedsim::core::duration_from_seconds(double s)¶
Create a Duration from a value in seconds (round to nearest ns).
See also
duration_from_seconds_ceil, duration_to_seconds
- Parameters:
s – Time interval in seconds.
- Returns:
Duration rounded to the nearest nanosecond.
-
Duration schedsim::core::duration_from_seconds_ceil(double s)¶
Create a Duration from a value in seconds (round up to next ns).
Ceiling rounding is used for completion timers where truncation could cause a timer to fire one nanosecond too early.
See also
duration_from_seconds
- Parameters:
s – Time interval in seconds.
- Returns:
Duration rounded up to the next nanosecond.
-
double schedsim::core::duration_to_seconds(Duration d)¶
Convert a Duration to seconds (double).
See also
duration_from_seconds
- Parameters:
d – Duration to convert.
- Returns:
Value in seconds.
-
Duration schedsim::core::duration_from_nanoseconds(int64_t ns)¶
Create a Duration from a raw nanosecond count.
See also
duration_to_nanoseconds
- Parameters:
ns – Nanosecond count.
- Returns:
Duration wrapping
ns.
-
int64_t schedsim::core::duration_to_nanoseconds(Duration d)¶
Extract the raw nanosecond count from a Duration.
See also
duration_from_nanoseconds
- Parameters:
d – Duration to convert.
- Returns:
Nanosecond count.
-
TimePoint schedsim::core::time_from_seconds(double s)¶
Create a TimePoint from a value in seconds since epoch.
See also
time_to_seconds
- Parameters:
s – Absolute time in seconds.
- Returns:
TimePoint at
sseconds from epoch.
-
double schedsim::core::time_to_seconds(TimePoint tp)¶
Convert a TimePoint to seconds since epoch (double).
See also
time_from_seconds
- Parameters:
tp – TimePoint to convert.
- Returns:
Absolute time in seconds.
-
Duration schedsim::core::scale_duration(Duration d, double factor)¶
Scale a Duration by a floating-point factor (round to nearest ns).
Useful for frequency/performance scaling of execution times.
See also
divide_duration, duration_ratio
- Parameters:
d – Duration to scale.
factor – Multiplicative factor.
- Returns:
Scaled duration, rounded to nearest nanosecond.
-
Duration schedsim::core::divide_duration(Duration d, double divisor)¶
Divide a Duration by a floating-point divisor (round to nearest ns).
Useful for computing remaining execution time at a different speed.
See also
scale_duration, duration_ratio
- Parameters:
d – Duration to divide.
divisor – Divisor (must not be zero).
- Returns:
Divided duration, rounded to nearest nanosecond.
-
double schedsim::core::duration_ratio(Duration a, Duration b)¶
Compute the ratio of two Durations as a double.
Returns
a / bas a floating-point value, not an integer truncation. This is the canonical way to compute utilization ratios (WCET/period).See also
scale_duration, divide_duration
- Parameters:
a – Numerator duration.
b – Denominator duration (must not be zero).
- Returns:
Floating-point ratio a/b.
Frequency¶
-
struct Frequency¶
Strong type for processor clock frequency in MHz.
Power¶
-
struct Power¶
Strong type for power consumption in milliwatts.
Energy¶
Engine¶
The Engine is the central event-driven simulation loop. It owns the event priority queue and the Platform, advancing simulation time by dispatching events in chronological order.
-
class Engine¶
Event-driven simulation engine.
The Engine is the central simulation loop. It owns an event priority queue and a Platform, and advances simulation time by dispatching events in chronological order. Within a single timestep, events are processed by priority, followed by all requested deferred callbacks.
The Engine is non-copyable and non-movable, designed for stack allocation. A typical usage pattern is:
core::Engine engine; auto& plat = engine.platform(); // ... add hardware and tasks to platform ... engine.finalize(); // ... set up scheduler ... engine.run();
See also
Public Types
Public Functions
-
Engine()¶
-
~Engine()¶
-
inline TimePoint time() const noexcept¶
Returns the current simulation time.
- Returns:
Current simulation time.
-
void run()¶
Run simulation until the event queue is empty.
-
void run(TimePoint until)¶
Run simulation until the given time point.
- Parameters:
until – Simulation stops after processing all events at this time.
-
void run(std::function<bool()> stop_condition)¶
Run simulation until the stop condition returns true.
- Parameters:
stop_condition – Evaluated between timesteps; simulation stops when it returns true.
-
void request_stop() noexcept¶
Request the engine to stop after the current timestep completes.
The current timestep finishes atomically; the flag is checked between timesteps. Auto-resets at the start of each run() call.
-
bool stop_requested() const noexcept¶
Returns true if a stop has been requested.
- Returns:
True if request_stop() has been called.
-
TimerId add_timer(TimePoint when, int priority, std::function<void()> callback)¶
Schedule a one-shot timer.
- Parameters:
when – Absolute simulation time to fire (must be > time()).
priority – Lower values fire first within the same timestep.
callback – Invoked when the timer fires.
- Throws:
InvalidStateError – if
when<= time().- Returns:
Identifier that can be passed to cancel_timer().
-
TimerId add_timer(TimePoint when, std::function<void()> callback)¶
Schedule a one-shot timer with default priority.
- Parameters:
when – Absolute simulation time to fire (must be > time()).
callback – Invoked when the timer fires.
- Returns:
Identifier that can be passed to cancel_timer().
-
void cancel_timer(TimerId &timer_id)¶
Cancel a pending timer.
- Parameters:
timer_id – Timer to cancel; reset to invalid on return.
-
DeferredId register_deferred(std::function<void()> callback)¶
Register a deferred callback.
Deferred callbacks execute at the end of the current timestep, after all events at that time have been processed. They are useful for batching rescheduling decisions.
- Parameters:
callback – Function to invoke when requested.
- Returns:
Identifier used with request_deferred().
-
void request_deferred(DeferredId deferred_id)¶
Request that a registered deferred callback fires this timestep.
- Parameters:
deferred_id – Identifier returned by register_deferred().
-
void set_trace_writer(TraceWriter *writer) noexcept¶
Set the trace writer for simulation event logging.
The Engine does not own the writer. Pass nullptr to disable tracing.
- Parameters:
writer – Pointer to a TraceWriter, or nullptr.
-
template<typename F>
void trace(F &&func)¶ Invoke a tracing callback only if a trace writer is set.
Zero overhead when tracing is disabled: the callback is not invoked and no TraceRecord is allocated.
- Template Parameters:
F – Callable with signature void(TraceWriter&).
- Parameters:
func – Callback that writes trace data.
-
void finalize()¶
Finalize the engine and its platform.
Must be called after all hardware and tasks have been added to the Platform and before run(). Locks the platform collections and schedules initial job arrivals.
-
inline bool is_finalized() const noexcept¶
Returns true if the engine has been finalized.
- Returns:
True after finalize() has been called.
-
void schedule_event(TimePoint when, int priority, Event event)¶
Insert a raw event into the event queue.
- Parameters:
when – Simulation time for the event.
priority – Priority within the timestep (lower = earlier).
event – The event payload.
-
const Platform &platform() const noexcept¶
Access the simulation platform (const).
- Returns:
Const reference to the platform.
-
void schedule_job_arrival(Task &task, TimePoint arrival_time, Duration exec_time)¶
Schedule a job arrival event for a task.
- Parameters:
task – The task that will receive the job.
arrival_time – When the job arrives.
exec_time – Actual execution time for this job instance.
-
void set_job_arrival_handler(JobArrivalHandler handler)¶
Set the global job arrival handler.
Exactly one handler may be set per engine. Typically set by the scheduler to receive new jobs for admission and dispatch.
- Parameters:
handler – Called on every job arrival event.
- Throws:
HandlerAlreadySetError – if called more than once.
-
inline void enable_context_switch(bool enabled) noexcept¶
Enable or disable context switch overhead modeling.
- Parameters:
enabled – True to enable, false to disable (default: disabled).
-
inline bool context_switch_enabled() const noexcept¶
Returns true if context switch overhead is enabled.
- Returns:
True if context switching is modelled.
-
void enable_energy_tracking(bool enabled)¶
Enable or disable energy tracking.
Must be called before finalize(). When enabled, the engine tracks energy consumption per processor, clock domain, and power domain.
- Parameters:
enabled – True to enable energy tracking.
-
bool energy_tracking_enabled() const noexcept¶
Returns true if energy tracking is enabled.
- Returns:
True if energy tracking was enabled before finalization.
-
Energy processor_energy(std::size_t proc_id) const¶
Returns cumulative energy consumed by a processor.
- Parameters:
proc_id – Processor index (0-based).
- Throws:
InvalidStateError – if energy tracking is disabled.
- Returns:
Cumulative energy for the processor.
-
Energy clock_domain_energy(std::size_t cd_id) const¶
Returns cumulative energy consumed by a clock domain.
- Parameters:
cd_id – Clock domain index (0-based).
- Throws:
InvalidStateError – if energy tracking is disabled.
- Returns:
Cumulative energy for the clock domain.
-
Energy power_domain_energy(std::size_t pd_id) const¶
Returns cumulative energy consumed by a power domain.
- Parameters:
pd_id – Power domain index (0-based).
- Throws:
InvalidStateError – if energy tracking is disabled.
- Returns:
Cumulative energy for the power domain.
-
Energy total_energy() const¶
Returns total energy consumed across all domains.
- Throws:
InvalidStateError – if energy tracking is disabled.
- Returns:
Sum of all domain energies.
-
Engine()¶
Platform¶
The Platform is the container for all hardware resources: processor types,
clock domains, power domains, processors, and tasks. Factory methods must
be called before Engine::finalize().
-
class Platform¶
Container for all hardware resources in the simulation.
The Platform owns processor types, clock domains, power domains, processors, and tasks. Factory methods (add_*) must be called before Engine::finalize(). After finalization, collections are locked and indexed access methods become valid.
Internally uses
vector<unique_ptr<T>>for contiguous pointer storage (good cache locality for iteration) with stable references (objects do not move when the vector grows).See also
Factory Methods
Add hardware components. Must be called before finalize().
-
ProcessorType &add_processor_type(std::string_view name, double performance, Duration context_switch_delay = duration_from_seconds(0.0))¶
Add a processor type.
- Parameters:
name – Display name (e.g. “Cortex-A15”).
performance – Relative performance factor (1.0 = reference).
context_switch_delay – Overhead per context switch.
- Returns:
Reference to the created ProcessorType.
-
ClockDomain &add_clock_domain(Frequency freq_min, Frequency freq_max, Duration transition_delay = duration_from_seconds(0.0))¶
Add a clock domain with frequency range.
- Parameters:
freq_min – Minimum operating frequency.
freq_max – Maximum operating frequency.
transition_delay – Time to complete a frequency change.
- Returns:
Reference to the created ClockDomain.
-
PowerDomain &add_power_domain(std::vector<CStateLevel> c_states)¶
Add a power domain with C-state levels.
- Parameters:
c_states – Vector of available C-state levels (C0, C1, …).
- Returns:
Reference to the created PowerDomain.
-
Processor &add_processor(ProcessorType &type, ClockDomain &clock_domain, PowerDomain &power_domain)¶
Add a processor assigned to a type, clock domain, and power domain.
-
Task &add_task(Duration period, Duration relative_deadline, Duration wcet)¶
Add a task with auto-assigned ID.
Collection Sizes
-
inline std::size_t processor_type_count() const noexcept¶
Return the number of processor types.
- Returns:
Processor type count.
-
inline std::size_t processor_count() const noexcept¶
Return the number of processors.
- Returns:
Processor count.
-
inline std::size_t clock_domain_count() const noexcept¶
Return the number of clock domains.
- Returns:
Clock domain count.
Indexed Access
-
inline ProcessorType &processor_type(std::size_t idx)¶
Access a processor type by index.
- Parameters:
idx – Zero-based index.
- Returns:
Reference to the ProcessorType.
-
inline Processor &processor(std::size_t idx)¶
Access a processor by index.
- Parameters:
idx – Zero-based index.
- Returns:
Reference to the Processor.
-
inline ClockDomain &clock_domain(std::size_t idx)¶
Access a clock domain by index.
- Parameters:
idx – Zero-based index.
- Returns:
Reference to the ClockDomain.
-
inline PowerDomain &power_domain(std::size_t idx)¶
Access a power domain by index.
- Parameters:
idx – Zero-based index.
- Returns:
Reference to the PowerDomain.
-
inline Task &task(std::size_t idx)¶
Access a task by index.
- Parameters:
idx – Zero-based index.
- Returns:
Reference to the Task.
-
inline const ProcessorType &processor_type(std::size_t idx) const¶
Access a processor type by index (const).
- Parameters:
idx – Zero-based index.
- Returns:
Const reference to the ProcessorType.
-
inline const Processor &processor(std::size_t idx) const¶
Access a processor by index (const).
- Parameters:
idx – Zero-based index.
- Returns:
Const reference to the Processor.
-
inline const ClockDomain &clock_domain(std::size_t idx) const¶
Access a clock domain by index (const).
- Parameters:
idx – Zero-based index.
- Returns:
Const reference to the ClockDomain.
-
inline const PowerDomain &power_domain(std::size_t idx) const¶
Access a power domain by index (const).
- Parameters:
idx – Zero-based index.
- Returns:
Const reference to the PowerDomain.
Public Functions
-
explicit Platform(Engine &engine)¶
Construct a Platform owned by the given engine.
- Parameters:
engine – The simulation engine that owns this platform.
-
inline double reference_performance() const noexcept¶
Returns the reference performance used for heterogeneous scaling.
- Returns:
Reference performance factor.
-
void finalize()¶
Finalize the platform, locking all collections.
-
inline bool is_finalized() const noexcept¶
Returns true if the platform has been finalized.
- Returns:
True after finalize() has been called.
-
ProcessorType &add_processor_type(std::string_view name, double performance, Duration context_switch_delay = duration_from_seconds(0.0))¶
Hardware Model¶
ProcessorType¶
-
class ProcessorType¶
Represents a category of processors sharing the same performance characteristics.
Performance is a relative value expressing how fast processors of this type execute work compared to other types. Normalization to the reference (highest-performance) type is performed by Platform.
ProcessorTypes are non-copyable but movable, following Decision 61.
Public Functions
-
ProcessorType(std::size_t id, std::string_view name, double performance, Duration context_switch_delay = duration_from_seconds(0.0))¶
Construct a new ProcessorType.
- Parameters:
id – Unique identifier for this processor type.
name – Human-readable name (e.g., “A15”, “A7”).
performance – Relative performance factor (higher is faster).
context_switch_delay – Overhead duration for a context switch on this type. Defaults to zero.
-
inline std::size_t id() const noexcept¶
Get the unique processor type identifier.
- Returns:
Processor type ID.
-
inline std::string_view name() const noexcept¶
Get the human-readable name of this processor type.
- Returns:
Name as a string_view.
-
inline double performance() const noexcept¶
Get the relative performance factor.
See also
Task::wcet(const ProcessorType&, double)
- Returns:
Performance value (higher means faster execution).
-
inline Duration context_switch_delay() const noexcept¶
Get the context switch delay for processors of this type.
See also
- Returns:
Context switch overhead as a Duration.
-
ProcessorType(const ProcessorType&) = delete¶
-
ProcessorType &operator=(const ProcessorType&) = delete¶
-
ProcessorType(std::size_t id, std::string_view name, double performance, Duration context_switch_delay = duration_from_seconds(0.0))¶
Processor¶
-
enum class schedsim::core::ProcessorState¶
Enumeration of the possible states of a Processor.
Each processor is in exactly one state at any given simulation time. State transitions are managed internally by Processor and triggered by scheduling decisions, DVFS operations, and C-state requests.
Values:
-
enumerator Idle¶
No task assigned; the processor is available for scheduling.
-
enumerator ContextSwitching¶
Transitioning to run a job (optional overhead modelling).
-
enumerator Running¶
Actively executing a job.
-
enumerator Sleep¶
In a low-power C-state (C1 or deeper).
-
enumerator Changing¶
A DVFS frequency transition is in progress.
-
enumerator Idle¶
-
class Processor¶
Models a single CPU core in the simulated platform.
A Processor tracks its execution state and the job currently running on it. It belongs to exactly one ClockDomain (shared frequency) and one PowerDomain (shared C-state management). Scheduling decisions are communicated through ISR-style callback handlers that the algo layer registers.
Processor is non-copyable but movable (Decision 61).
See also
Public Types
-
using JobCompletionHandler = std::function<void(Processor&, Job&)>¶
Callback type invoked when a job completes execution.
See also
-
using DeadlineMissHandler = std::function<void(Processor&, Job&)>¶
Callback type invoked when a job misses its absolute deadline.
See also
Public Functions
-
Processor(std::size_t id, ProcessorType &type, ClockDomain &clock_domain, PowerDomain &power_domain)¶
Construct a Processor with its hardware affiliations.
- Parameters:
id – Unique processor identifier within the platform.
type – Reference to the ProcessorType describing this core’s micro-architecture (performance factor, context-switch overhead, etc.).
clock_domain – The ClockDomain this processor belongs to.
power_domain – The PowerDomain this processor belongs to.
-
inline std::size_t id() const noexcept¶
Return the unique identifier of this processor.
- Returns:
Processor ID (zero-based index within the platform).
-
inline ProcessorType &type() const noexcept¶
Return the ProcessorType describing this core’s micro-architecture.
See also
- Returns:
Reference to the associated ProcessorType.
-
inline ProcessorState state() const noexcept¶
Return the current execution state of the processor.
See also
ProcessorState
- Returns:
The current ProcessorState.
-
inline ClockDomain &clock_domain() const noexcept¶
Return the ClockDomain this processor belongs to.
See also
- Returns:
Reference to the associated ClockDomain.
-
inline PowerDomain &power_domain() const noexcept¶
Return the PowerDomain this processor belongs to.
See also
- Returns:
Reference to the associated PowerDomain.
-
inline Job *current_job() const noexcept¶
Return the job currently assigned to this processor, if any.
See also
- Returns:
Pointer to the current Job, or nullptr if no job is assigned.
-
Task *current_task() const noexcept¶
Return the task that owns the current job, if any.
See also
- Returns:
Pointer to the current Task, or nullptr if no job is assigned.
-
double speed(double reference_performance) const noexcept¶
Compute the normalised execution speed of this processor.
Speed is defined as
(freq / freq_max) * (perf / reference_performance), wherefreqandfreq_maxcome from the ClockDomain,perffrom the ProcessorType, andreference_performancefrom the Platform.- Parameters:
reference_performance – The platform-wide reference performance factor used for normalisation.
- Returns:
Normalised speed in the range (0, 1] under typical configurations.
-
inline int current_cstate_level() const noexcept¶
Return the current C-state level of this processor.
See also
- Returns:
C-state level: 0 means active (C0); higher values indicate deeper sleep states.
-
void assign(Job &job)¶
Assign a job to this processor for execution.
If the processor is Idle, the job starts immediately (or after an optional context-switch delay). If the processor is in Sleep, a wake-up sequence is initiated; the job starts once the processor has woken up.
- Parameters:
job – The Job to execute on this processor.
- Throws:
InvalidStateError – if the processor is not in Idle or Sleep state (Decision 72).
-
void clear()¶
Remove the current job from this processor.
The exact behaviour depends on the current state:
Running: stops execution, returns to Idle.
ContextSwitching: cancels the transition; the job never runs.
Changing (DVFS in progress): sets a pending-clear flag; the processor returns to Idle once the DVFS transition completes.
See also
- Throws:
InvalidStateError – if the processor is already Idle (Decision 53).
-
void request_cstate(int level)¶
Request a transition to a low-power C-state.
The processor enters the specified C-state level. Level 0 represents the fully active state (C0).
See also
- Parameters:
level – The target C-state level (0 = C0/active, higher = deeper).
- Throws:
InvalidStateError – if the processor is Running, Changing, or ContextSwitching.
-
void set_job_completion_handler(JobCompletionHandler handler)¶
Register a handler called when a job finishes its work.
See also
- Parameters:
handler – The callback to invoke on job completion.
-
void set_deadline_miss_handler(DeadlineMissHandler handler)¶
Register a handler called when a job’s absolute deadline is missed.
See also
- Parameters:
handler – The callback to invoke on deadline miss.
-
void set_processor_available_handler(ProcessorAvailableHandler handler)¶
Register a handler called when the processor becomes available.
See also
- Parameters:
handler – The callback to invoke when the processor is ready.
-
using JobCompletionHandler = std::function<void(Processor&, Job&)>¶
ClockDomain¶
-
class ClockDomain¶
Groups processors that share a common frequency setting.
A ClockDomain models a voltage/frequency island: all processors within it operate at the same frequency. DVFS operations (set_frequency()) affect every processor in the domain simultaneously.
Optionally, a ClockDomain can be configured with discrete Operating Performance Points (OPPs) via set_frequency_modes(), and with a polynomial power model via set_power_coefficients() for energy tracking.
ClockDomain is non-copyable but movable (Decision 61).
See also
Public Functions
-
ClockDomain(std::size_t id, Frequency freq_min, Frequency freq_max, Duration transition_delay = duration_from_seconds(0.0))¶
Construct a ClockDomain with its frequency bounds.
- Parameters:
id – Unique identifier within the platform.
freq_min – Minimum allowed frequency for this domain.
freq_max – Maximum allowed frequency for this domain. The domain is initialised to this frequency.
transition_delay – Duration of an asynchronous DVFS transition. A zero duration means frequency changes are applied instantaneously.
-
inline std::size_t id() const noexcept¶
Return the unique identifier of this clock domain.
- Returns:
Clock domain ID.
-
inline Frequency frequency() const noexcept¶
Return the current operating frequency.
- Returns:
The active frequency of all processors in this domain.
-
inline Frequency freq_min() const noexcept¶
Return the minimum allowed frequency.
- Returns:
Lower bound of the frequency range.
-
inline Frequency freq_max() const noexcept¶
Return the maximum allowed frequency.
- Returns:
Upper bound of the frequency range.
-
inline Duration transition_delay() const noexcept¶
Return the DVFS transition delay.
- Returns:
Duration of an asynchronous frequency change. Zero means transitions are instantaneous.
-
inline bool is_locked() const noexcept¶
Check whether DVFS is permanently disabled for this domain.
See also
- Returns:
True if lock_frequency() has been called.
-
inline bool is_transitioning() const noexcept¶
Check whether an asynchronous DVFS transition is in progress.
- Returns:
True if a frequency change has been initiated but not yet completed.
-
std::span<Processor*const> processors() const noexcept¶
Return the processors belonging to this clock domain.
See also
- Returns:
A read-only span of processor pointers.
-
void set_frequency(Frequency freq)¶
Set the operating frequency of this clock domain.
If transition_delay is zero the change takes effect immediately and all processors are notified synchronously. Otherwise, an asynchronous DVFS transition is started: each processor enters the Changing state for the duration of the transition.
See also
- Parameters:
freq – The target frequency.
- Throws:
OutOfRangeError – if
freqis outside [freq_min, freq_max].InvalidStateError – if the domain is locked or already transitioning.
-
inline void lock_frequency() noexcept¶
Permanently disable DVFS for this domain.
After this call, set_frequency() will throw InvalidStateError.
See also
-
void set_frequency_modes(std::vector<Frequency> modes)¶
Define the set of discrete Operating Performance Points (OPPs).
When OPPs are set, set_frequency() only accepts values that exactly match one of the modes, and ceil_to_mode() can be used to round up.
See also
- Parameters:
modes – A list of valid frequencies, sorted ascending.
-
std::span<const Frequency> frequency_modes() const noexcept¶
Return the discrete OPP frequency list.
See also
- Returns:
A span of the configured frequency modes, or an empty span if continuous DVFS is in use.
-
bool has_frequency_modes() const noexcept¶
Check whether discrete OPPs have been configured.
See also
- Returns:
True if set_frequency_modes() has been called with a non-empty list.
-
Frequency ceil_to_mode(Frequency freq) const¶
Round a frequency up to the nearest configured OPP.
Returns the smallest frequency mode that is greater than or equal to
freq. Iffreqexceeds all modes, returns the highest mode.See also
- Parameters:
freq – The frequency to round up.
- Returns:
The ceiling OPP frequency.
-
inline void set_freq_eff(Frequency freq) noexcept¶
Set the efficient frequency threshold for DPM decisions.
Below this frequency it may be more energy-efficient to use C-states (race-to-idle) rather than running at a very low frequency.
See also
- Parameters:
freq – The efficient frequency threshold.
-
inline Frequency freq_eff() const noexcept¶
Return the efficient frequency threshold.
See also
- Returns:
The frequency below which DPM sleep may be preferable to DVFS.
-
void set_power_coefficients(std::array<double, 4> coeffs) noexcept¶
Set the polynomial power-model coefficients.
The power model is:
P(f) = a0 + a1*f + a2*f^2 + a3*f^3, where power is in milliwatts and frequency is in GHz.See also
- Parameters:
coeffs – Array of four coefficients {a0, a1, a2, a3}.
-
Power power_at_frequency(Frequency freq) const noexcept¶
Evaluate the power model at a given frequency.
See also
- Parameters:
freq – The frequency at which to compute power.
- Returns:
Estimated power consumption (mW) at the specified frequency.
-
ClockDomain(const ClockDomain&) = delete¶
-
ClockDomain &operator=(const ClockDomain&) = delete¶
-
ClockDomain(std::size_t id, Frequency freq_min, Frequency freq_max, Duration transition_delay = duration_from_seconds(0.0))¶
PowerDomain¶
-
enum class schedsim::core::CStateScope¶
Determines whether a C-state applies per-processor or domain-wide.
Shallow C-states are typically per-processor (each core can independently enter or exit them), while deeper C-states may require all cores in a power domain to coordinate.
Values:
-
enumerator PerProcessor¶
Each processor can enter and exit this C-state independently.
-
enumerator DomainWide¶
All processors in the power domain must coordinate to enter this C-state.
-
enumerator PerProcessor¶
-
struct CStateLevel¶
Describes a single C-state level and its hardware characteristics.
C-states form an ordered hierarchy: level 0 is the fully active state (C0), and increasing levels represent progressively deeper sleep states with lower power consumption but higher wake-up latency.
See also
PowerDomain, CStateScope
-
class PowerDomain¶
Groups processors that share C-state management.
A PowerDomain models a shared power rail or power-gating region. All processors in a power domain share the same set of available C-state levels. For domain-wide C-states, all processors must agree before the domain can enter a deeper sleep state.
PowerDomain is non-copyable but movable (Decision 61).
See also
Processor, CStateLevel, CStateScope, ClockDomain
Public Functions
-
PowerDomain(std::size_t id, std::vector<CStateLevel> c_states)¶
Construct a PowerDomain with its available C-state levels.
- Parameters:
id – Unique identifier within the platform.
c_states – Ordered list of C-state levels supported by this domain. Level 0 (C0/active) should typically be included.
-
inline std::size_t id() const noexcept¶
Return the unique identifier of this power domain.
- Returns:
Power domain ID.
-
inline std::span<const CStateLevel> c_states() const noexcept¶
Return the available C-state levels for this domain.
See also
- Returns:
A read-only span of CStateLevel descriptors.
-
inline std::span<Processor*const> processors() const noexcept¶
Return the processors belonging to this power domain.
See also
- Returns:
A read-only span of processor pointers.
-
int achieved_cstate_for_processor(const Processor &proc) const¶
Compute the effective C-state for a given processor.
For per-processor C-states, this returns the processor’s own requested level. For domain-wide C-states, the achieved level is the minimum of all processors’ requested levels, since every processor must agree before the domain can enter a deeper state.
See also
Processor::current_cstate_level, CStateScope
- Parameters:
proc – The processor to query.
- Returns:
The effective C-state level that the processor can achieve.
-
Duration wake_latency(int level) const¶
Return the wake-up latency for a given C-state level.
This is the time required to transition from the specified C-state back to the fully active state (C0).
See also
- Parameters:
level – The C-state level to query.
- Returns:
Wake-up latency duration. Returns a zero duration if
levelis 0 (C0) or if the level is not found.
-
Power cstate_power(int level) const¶
Return the power consumption for a given C-state level.
See also
- Parameters:
level – The C-state level to query.
- Returns:
Power consumption (mW). Returns zero if
levelis not found.
-
PowerDomain(const PowerDomain&) = delete¶
-
PowerDomain &operator=(const PowerDomain&) = delete¶
-
PowerDomain(std::size_t id, std::vector<CStateLevel> c_states)¶
Tasks and Jobs¶
Task¶
-
class Task¶
Represents a periodic or sporadic real-time task in the system.
WCET is specified in reference units, normalized to the highest-performance processor type in the platform. Actual wall-clock execution time depends on the processor speed and is obtained via the overloaded wcet(ProcessorType&, double) method.
Tasks are non-copyable but movable, following Decision 61.
See also
Public Functions
-
Task(std::size_t id, Duration period, Duration relative_deadline, Duration wcet)¶
Construct a new Task.
- Parameters:
id – Unique task identifier (1-based in scenario JSON).
period – Minimum inter-arrival time between consecutive jobs.
relative_deadline – Relative deadline from job arrival to completion.
wcet – Worst-case execution time in reference (normalized) units.
-
inline Duration relative_deadline() const noexcept¶
Get the relative deadline.
- Returns:
Relative deadline as a Duration from job arrival.
-
inline Duration wcet() const noexcept¶
Get the worst-case execution time in reference units.
See also
wcet(const ProcessorType&, double) for wall-clock WCET on a specific processor.
- Returns:
WCET as a Duration in normalized reference units.
-
Duration wcet(const ProcessorType &type, double reference_performance) const noexcept¶
Compute the wall-clock WCET for a specific processor type.
Scales the reference WCET by the ratio of reference performance to the target processor type’s performance: wall_clock_wcet = wcet / (type.performance() / reference_performance)
See also
- Parameters:
type – The target processor type.
reference_performance – The reference (highest) performance value in the platform.
- Returns:
Wall-clock WCET as a Duration for the given processor type.
-
Task(std::size_t id, Duration period, Duration relative_deadline, Duration wcet)¶
Job¶
-
class Job¶
Represents a single instance (release) of a Task.
A Job is created by the Engine at job arrival time and is owned by the allocator (Library 2). Work is tracked in reference units (normalized execution time), independent of the processor on which the job executes.
Jobs are non-copyable but movable, following Decision 73.
Public Functions
-
Job(Task &task, Duration total_work, TimePoint absolute_deadline)¶
Construct a new Job.
- Parameters:
task – Reference to the parent Task that spawned this job.
total_work – Total amount of work for this job in reference units.
absolute_deadline – Absolute deadline by which the job must complete.
-
inline Task &task() const noexcept¶
Get the parent task.
See also
- Returns:
Reference to the Task that this job belongs to.
-
inline Duration remaining_work() const noexcept¶
Get the remaining work for this job.
- Returns:
Remaining work as a Duration in reference units.
-
inline Duration total_work() const noexcept¶
Get the total work for this job.
- Returns:
Total work as a Duration in reference units.
-
inline TimePoint absolute_deadline() const noexcept¶
Get the absolute deadline.
- Returns:
Absolute deadline as a TimePoint.
-
inline bool is_complete() const noexcept¶
Check whether the job has completed all of its work.
- Returns:
True if remaining work is zero or less, false otherwise.
-
void consume_work(Duration amount)¶
Consume a given amount of work from this job.
Called by Processor during execution tracking. The amount is specified in reference units and is subtracted from the remaining work. The remaining work is clamped so it does not go below zero.
See also
- Parameters:
amount – Amount of work to consume, in reference units.
-
inline bool deadline_miss_reported() const noexcept¶
Check whether a deadline miss has already been reported for this job.
- Returns:
True after this job’s first deadline miss has been reported.
-
inline void set_deadline_miss_reported() noexcept¶
Mark that a deadline miss has been reported for this job.
-
Job(Task &task, Duration total_work, TimePoint absolute_deadline)¶
Events and Timers¶
EventKey¶
-
struct EventKey¶
Deterministic ordering key for events in the priority queue.
Events are ordered first by simulation time, then by priority (lower values fire first), then by insertion sequence number to guarantee determinism when time and priority are equal.
See also
EventPriority¶
-
struct EventPriority¶
Named constants for event dispatch priority.
Lower numeric values indicate higher priority (fire first within the same simulation timestep). The ordering ensures that completions are processed before deadline checks, which are processed before new arrivals, matching standard real-time scheduling semantics.
See also
Event Types¶
-
struct JobArrivalEvent¶
A new job instance arrives for a task.
Carries the task that generated the job and the actual execution time for this particular instance (may be less than the WCET).
-
struct JobCompletionEvent¶
A job has finished executing on its processor.
Fired when the processor completes all remaining work for the job. The scheduler should release the processor and update its ready queue.
-
struct DeadlineMissEvent¶
A job’s absolute deadline has been reached.
Fired when a job’s deadline expires. The scheduler’s deadline miss policy determines whether the simulation continues or aborts.
-
struct ProcessorAvailableEvent¶
A processor has become available for scheduling.
Fired when a processor transitions to an idle state (e.g., after completing a job or waking from a low-power C-state). The scheduler should check its ready queue for pending work.
See also
-
struct TimerEvent¶
A one-shot timer callback fires.
Created by Engine::add_timer(). The callback is invoked during event dispatch at the scheduled time and priority.
See also
Public Members
-
std::function<void()> callback¶
User-provided callback to invoke.
-
std::function<void()> callback¶
TimerId¶
-
class TimerId¶
Provides O(1) timer cancellation by wrapping a map iterator.
A TimerId is returned by Engine::set_timer() and stores an iterator into the engine’s ordered event map, enabling constant-time cancellation. Default-constructed instances are invalid; only the Engine may create valid identifiers.
Timer callbacks should call clear() at their entry point to prevent dangling-iterator issues when the callback itself cancels other timers.
See also
Engine::set_timer()
See also
See also
Public Functions
-
TimerId() = default¶
Default-construct an invalid timer identifier.
-
inline bool valid() const noexcept¶
Check whether this timer is still valid (not fired, not cancelled).
- Returns:
trueif the timer has not yet fired or been cancelled.
-
inline explicit operator bool() const noexcept¶
Allow contextual conversion to
boolforif (timer_id)checks.- Returns:
trueif valid.
-
inline void clear() noexcept¶
Mark the timer as no longer valid.
Call this at the start of timer callbacks to prevent dangling-iterator issues if the callback later tries to cancel this or another timer.
-
TimerId() = default¶
DeferredId¶
-
class DeferredId¶
Identifies a registered deferred callback.
A DeferredId is returned by Engine::defer() and wraps an index into the engine’s internal deferred-callback vector. Default-constructed instances are invalid; only the Engine may create valid identifiers.
See also
Engine::defer()
See also
Engine::cancel_deferred()
Public Functions
-
DeferredId() = default¶
Default-construct an invalid deferred callback identifier.
-
inline bool valid() const noexcept¶
Check whether this identifier refers to a valid deferred callback.
- Returns:
trueif the identifier was created by the Engine and has not been invalidated,falseotherwise.
-
inline explicit operator bool() const noexcept¶
Allow contextual conversion to
boolforif (deferred_id)checks.- Returns:
trueif valid.
-
DeferredId() = default¶
Trace Writer¶
-
class TraceWriter¶
Abstract interface for recording simulation trace events.
Implementations of TraceWriter serialise simulation events to a specific format (JSON, binary, socket, memory buffer, etc.). Each trace record is built incrementally:
begin() — opens a new record at a given simulation time
type() — sets the event type name
field() — (repeated) adds key/value data fields
end() — closes and optionally flushes the record
The Engine holds an optional pointer to a TraceWriter. When no writer is installed the overhead is a single null-pointer check (zero-cost).
See also
Subclassed by schedsim::io::JsonTraceWriter, schedsim::io::MemoryTraceWriter, schedsim::io::NullTraceWriter, schedsim::io::TextualTraceWriter
Public Functions
-
virtual ~TraceWriter() = default¶
Virtual destructor for safe polymorphic deletion.
-
virtual void begin(TimePoint time) = 0¶
Begin a new trace record at the given simulation time.
- Parameters:
time – The simulation time-point at which the event occurs.
-
virtual void type(std::string_view name) = 0¶
Set the event type name for the current record.
- Parameters:
name – A short identifier for the event category (e.g.
"dispatch","preempt","freq_change").
-
virtual void field(std::string_view key, double value) = 0¶
Add a floating-point field to the current record.
- Parameters:
key – Field name.
value – Field value.
-
virtual void field(std::string_view key, uint64_t value) = 0¶
Add an unsigned integer field to the current record.
- Parameters:
key – Field name.
value – Field value.
-
virtual void field(std::string_view key, std::string_view value) = 0¶
Add a string field to the current record.
- Parameters:
key – Field name.
value – Field value.
Energy Tracker¶
-
class EnergyTracker¶
Monitors power consumption and accumulates energy over time.
EnergyTracker listens for state-change notifications from Processor and ClockDomain objects and uses the configured power models to integrate instantaneous power into cumulative energy. It maintains per-processor accumulators that can be queried individually or aggregated by clock domain, power domain, or across the entire platform.
Typical usage:
Construct with a Platform reference and the simulation start time.
Wire up the
on_*hooks so that Processor and ClockDomain call them on every state change.At the end of the simulation (or at any point), call update_to_time() and then read energy via the query methods.
See also
ClockDomain::set_power_coefficients, PowerDomain::cstate_power, Processor, ProcessorState
Public Functions
-
explicit EnergyTracker(Platform &platform, TimePoint start_time)¶
Construct an EnergyTracker bound to a platform.
-
void on_processor_state_change(Processor &proc, ProcessorState old_state, ProcessorState new_state, TimePoint now)¶
Notify the tracker that a processor has changed execution state.
The tracker closes the previous power interval for the processor and opens a new one based on the new state.
See also
ProcessorState
- Parameters:
proc – The processor whose state changed.
old_state – The state the processor was in before the change.
new_state – The state the processor is now in.
now – The simulation time at which the change occurred.
-
void on_frequency_change(ClockDomain &cd, Frequency old_freq, Frequency new_freq, TimePoint now)¶
Notify the tracker that a clock domain has changed frequency.
The tracker closes the previous power interval for every processor in the clock domain and opens new intervals at the new frequency.
See also
- Parameters:
cd – The clock domain whose frequency changed.
old_freq – The frequency before the change.
new_freq – The frequency after the change.
now – The simulation time at which the change occurred.
-
void on_cstate_change(Processor &proc, int old_level, int new_level, TimePoint now)¶
Notify the tracker that a processor’s C-state level has changed.
The tracker adjusts the power model for the processor based on the new C-state’s power consumption.
See also
- Parameters:
proc – The processor whose C-state changed.
old_level – The C-state level before the change (0 = C0/active).
new_level – The C-state level after the change.
now – The simulation time at which the change occurred.
-
void update_to_time(TimePoint now)¶
Flush all accumulators up to the specified simulation time.
Computes the energy consumed between each processor’s last-update time and
now, then advances all last-update timestamps. Call this before reading energy values to ensure they reflect the latest state.- Parameters:
now – The simulation time to advance to.
-
Energy processor_energy(std::size_t proc_id) const¶
Return the accumulated energy for a single processor.
See also
- Parameters:
proc_id – The processor’s unique identifier.
- Returns:
Accumulated energy (mJ) from start_time to the last update.
-
Energy clock_domain_energy(std::size_t cd_id) const¶
Return the accumulated energy for all processors in a clock domain.
See also
- Parameters:
cd_id – The clock domain’s unique identifier.
- Returns:
Sum of accumulated energy (mJ) across all processors in the domain.
Errors¶
-
class SimulationError : public std::runtime_error¶
Base exception for all simulation errors.
All exceptions thrown by the core library derive from this class, allowing callers to catch simulation-specific errors separately from other
std::runtime_errorexceptions.Subclassed by schedsim::core::AlreadyFinalizedError, schedsim::core::HandlerAlreadySetError, schedsim::core::InvalidStateError, schedsim::core::OutOfRangeError
-
class InvalidStateError : public schedsim::core::SimulationError¶
Thrown when an operation is invalid for the current object state.
For example, calling a method that requires finalization before the engine has been finalized, or attempting to execute a job on a processor that is already busy.
See also
-
class OutOfRangeError : public schedsim::core::SimulationError¶
Thrown when a value is outside its valid range.
For example, requesting a processor by index when the index exceeds the number of processors in the platform.
See also
-
class AlreadyFinalizedError : public schedsim::core::SimulationError¶
Thrown when attempting to modify the platform after finalize().
Once Engine::finalize() has been called, hardware and task collections are locked. Any add_* call after that point raises this exception.
See also
-
class HandlerAlreadySetError : public schedsim::core::SimulationError¶
Thrown when setting a callback handler that has already been set.
Handlers such as Engine::set_job_arrival_handler() may only be registered once. A second call raises this exception.