Source Deep Dive: SC_METHOD, SC_THREAD, and wait()
How process registration, static sensitivity, runnable queues, and wait-based suspension work conceptually.
SC_METHOD and SC_THREAD look like simple macros, but they create very different process objects inside the kernel.
The implementation work behind those lines is the heart of SystemC execution according to the LRM.
What Registration Must Capture
When a process is registered, the kernel needs the owning module, the member function pointer, the process kind, sensitivity, and execution state.
To prove how the kernel manages these different process types and runnable queues, here is a complete compilable example demonstrating static sensitivity and wait dynamics.
#include <systemc>
using namespace sc_core;
SC_MODULE(ProcessInternalsDemo) {
sc_event trigger_event;
SC_CTOR(ProcessInternalsDemo) {
// 1. SC_METHOD: A non-resumable callback
SC_METHOD(method_process);
sensitive << trigger_event;
dont_initialize();
// 2. SC_THREAD: A resumable coroutine with execution state
SC_THREAD(thread_process);
}
// Conceptually similar to:
// void run_once() { (owner->*callback)(); }
void method_process() {
std::cout << "[METHOD] Executing at " << sc_time_stamp() << "\n";
// wait(); // ILLEGAL: Methods cannot suspend!
}
// Conceptually similar to a fiber context switch
void thread_process() {
std::cout << "[THREAD] Started at " << sc_time_stamp() << "\n";
// Transfers control back to scheduler, removing process from runnable queue
wait(10, SC_NS);
std::cout << "[THREAD] Resumed at " << sc_time_stamp() << ". Firing event.\n";
trigger_event.notify(SC_ZERO_TIME);
}
};
int sc_main(int argc, char* argv[]) {
ProcessInternalsDemo demo("demo");
sc_start(50, SC_NS);
return 0;
}SC_METHOD vs SC_THREAD Internals
An SC_METHOD process runs to completion. It cannot call wait(), because the kernel does not preserve a suspended stack for it. It is merely a C++ callback function invoked by the kernel.
An SC_THREAD process can suspend. The kernel must resume this process after the wait condition is satisfied. That requires process state beyond a simple callback. Depending on the platform, the implementation uses coroutine or fiber-like mechanisms.
wait() Changes Process State
wait() does not sleep the host OS thread. It tells the SystemC scheduler: this process is no longer runnable until a condition is met.
Each call to wait() installs a wait condition, removes the process from the runnable set, and transfers control back to the scheduler.
Runnable Queues
At simulation time, the scheduler keeps track of runnable processes. A simplified view:
- Pop process from runnable queue.
- Transfer control to the process (
run()or context switch). - Process returns or yields (
wait()). - Once runnable queue is empty, trigger the update phase.
When you know the internal shape, the rules stop feeling arbitrary. SystemC lets you write ordinary-looking C++, but the kernel is building a small event-driven operating environment around your objects.
Comments and Corrections