The Execution Phases
A deep dive into the SystemC execution model: Elaboration, Initialization, Evaluation, Update, and advancing time.
The Execution Phases
The SystemC Language Reference Manual (IEEE 1666) defines a strict execution model that governs how your C++ code behaves like parallel hardware. Understanding these phases is the key to mastering SystemC.
1. Elaboration Phase
Before the simulation clock even starts ticking, SystemC builds the hierarchy.
- Module Instantiation: The constructors (
SC_CTORor custom constructors) of allsc_modulederived classes are executed. - Port Binding: Ports (
sc_in,sc_out,sc_port) are bound to channels or interfaces. - Process Registration:
SC_METHOD,SC_THREAD, andSC_CTHREADare registered with the kernel.
[!WARNING] You cannot bind ports after the elaboration phase has completed. Once
sc_start()is called, the hierarchy is locked.
2. Initialization Phase
When sc_start() is invoked, the kernel enters initialization:
- Every registered
SC_METHODandSC_THREADis executed exactly once, unlessdont_initialize()was explicitly called on it during elaboration. - The processes run until they yield (e.g., hit a
wait()) or return.
3. The Evaluation Phase
This is the core of the simulation loop.
- The scheduler selects a runnable process from the runnable queue.
- The process executes. If it writes to a signal (
sc_signal::write), the new value is not immediately visible. Instead, the signal is added to the update queue. - The evaluation phase continues until the runnable queue is entirely empty.
4. The Update Phase
Once all processes have suspended, the kernel processes the update queue.
- All primitive channels (like
sc_signal) apply their pending writes. The "next" value becomes the "current" value. - If the value changed, any process sensitive to that channel's events is pushed back onto the runnable queue.
5. Delta Cycles
If the update phase caused new processes to become runnable, the kernel returns to the Evaluation Phase without advancing the simulation time. This loop (Evaluate -> Update -> Evaluate) is called a Delta Cycle. It allows zero-delay combinational logic to settle deterministically.
6. Advancing Time
If the runnable queue and update queue are both empty, the kernel looks at the event queue for pending timed events (e.g., wait(10, SC_NS)).
- The simulation time is advanced to the timestamp of the earliest pending event.
- The processes waiting on that event are moved to the runnable queue.
- The cycle repeats.
Complete Execution Example
Below is a complete, compilable sc_main example that demonstrates the elaboration, initialization, evaluation, and update phases in action.
#include <systemc>
#include <iostream>
SC_MODULE(phase_demo) {
sc_core::sc_signal<int> sig;
SC_CTOR(phase_demo) : sig("sig") {
std::cout << "1. Elaboration Phase: Constructor running." << std::endl;
SC_THREAD(stimulus_thread);
// We do NOT use dont_initialize() here, so it runs during initialization.
SC_METHOD(monitor_method);
sensitive << sig;
dont_initialize(); // Only run when 'sig' actually changes
}
void stimulus_thread() {
std::cout << "2. Initialization Phase: Thread running for the first time." << std::endl;
// Wait for some time to pass
sc_core::wait(10, sc_core::SC_NS);
std::cout << "3. Evaluation Phase (@" << sc_core::sc_time_stamp()
<< "): Thread writing to signal." << std::endl;
// This schedules an update, but does not change the value immediately
sig.write(42);
std::cout << " Immediate read after write (old value): " << sig.read() << std::endl;
// Yield to allow the update phase and subsequent delta cycle to run
sc_core::wait(sc_core::SC_ZERO_TIME);
std::cout << "6. Evaluation Phase (Next Delta): Value is now updated to: "
<< sig.read() << std::endl;
}
void monitor_method() {
std::cout << "5. Evaluation Phase (Delta Cycle): Monitor triggered! Signal value is: "
<< sig.read() << std::endl;
}
};
int sc_main(int argc, char* argv[]) {
std::cout << "Starting Elaboration..." << std::endl;
phase_demo demo("demo");
std::cout << "Starting Simulation..." << std::endl;
sc_core::sc_start();
return 0;
}Running this program clearly illustrates how the SystemC kernel defers signal updates until the evaluation phase completes, ensuring deterministic hardware-like behavior in a sequential software environment.
Comments and Corrections