SystemC AMS (Analog/Mixed-Signal)
An introduction to the SystemC AMS standard, Timed Data Flow (TDF), and modeling continuous-time signals.
How to Read This Lesson
SystemC AMS (Analog/Mixed-Signal)
Standard SystemC is a discrete-event simulator. It evaluates state changes at specific, discrete points in time.
However, modern SoCs interact heavily with continuous-time physical systems (RF transceivers, sensors, power grids). To model these systems efficiently without resorting to cycle-heavy, numerically intense SPICE-level simulations, Accellera standardized the SystemC AMS 2.0 Language Reference Manual.
Standard and source context
The Three Models of Computation in AMS
SystemC AMS introduces three mathematically distinct Models of Computation (MoC) that interoperate with the discrete SystemC kernel:
- Timed Data Flow (TDF): The most common MoC. It uses a static schedule and fixed time steps. Best for signal processing, communication algorithms, and behavioral analog modeling.
- Linear Signal Flow (LSF): Used to model continuous-time behavior using primitive blocks like integrators, differentiators, and adders.
- Electrical Linear Networks (ELN): Models electrical circuits using passive components (resistors, capacitors, inductors) and sources. Solved via nodal analysis matrices.
This guide focuses on TDF, as it bridges the gap between digital discrete control and continuous analog waveforms efficiently.
Writing a TDF Module & Accellera Kernel Details
In AMS TDF, you inherit from sca_tdf::sca_module and define a fixed-time calculation in the processing() callback.
Unlike discrete SystemC, TDF modules do not wait on events (no sc_event). They are statically scheduled by the AMS solver to execute at exact, regular intervals dictated by set_timestep().
Under the Hood (Accellera systemc-ams repository):
sca_tdf::sca_module registers itself with an internal synchronization layer (sca_core::sca_implementation::sca_sync_obj and sca_solver_base). During elaboration, the AMS kernel identifies all connected TDF modules and forms a "cluster." It performs a static scheduling algorithm to determine the exact order in which processing() must be called to satisfy data dependencies without deadlocks.
When sc_start() is called, the AMS solver actually registers a standard SC_METHOD within the standard SystemC sc_simcontext. This hidden method computes the next time the TDF cluster needs to run and issues a sc_core::next_trigger(sc_time) to sleep the continuous-time solver until the discrete-event time matches the next TDF time step.
Complete AMS Interoperability Example
Here is a complete sc_main example models an Analog-to-Digital Converter (ADC). It reads an analog sine wave generated in TDF, converts it to a discrete digital signal, and triggers a standard SystemC thread when the voltage crosses a threshold.
#include <systemc>
#include <systemc-ams.h>
// 1. TDF Sine Wave Generator (Purely Analog)
SCA_TDF_MODULE(SineGenerator) {
sca_tdf::sca_out<double> analog_out;
double amplitude;
double frequency;
SCA_CTOR(SineGenerator) : amplitude(3.3), frequency(1000.0) {}
// Defines the strict execution interval for the solver
void set_attributes() {
set_timestep(10, sc_core::SC_US);
}
void processing() {
double current_time = get_time().to_seconds();
double value = amplitude * std::sin(2.0 * M_PI * frequency * current_time);
analog_out.write(value);
}
};
// 2. TDF ADC (Mixed-Signal: Analog In, Digital Out)
SCA_TDF_MODULE(ADC_Model) {
sca_tdf::sca_in<double> analog_in;
// sca_de denotes Discrete-Event (standard SystemC) output
sca_tdf::sca_de::sca_out<bool> threshold_alert;
SCA_CTOR(ADC_Model) {}
void set_attributes() {
set_timestep(10, sc_core::SC_US);
}
void processing() {
double voltage = analog_in.read();
// If voltage exceeds 3.0V, trigger the digital alert
if (voltage > 3.0) {
threshold_alert.write(true); // Schedules a SystemC delta update!
} else {
threshold_alert.write(false);
}
}
};
// 3. Standard SystemC Digital Monitor
SC_MODULE(DigitalMonitor) {
sc_core::sc_in<bool> alert_in;
SC_CTOR(DigitalMonitor) {
SC_THREAD(monitor_thread);
sensitive << alert_in.pos(); // Wake up exactly when the AMS model crosses 3.0V
}
void monitor_thread() {
while(true) {
wait();
std::cout << "@" << sc_core::sc_time_stamp()
<< " [Digital Domain] WARNING: Voltage crossed 3.0V threshold!" << std::endl;
}
}
};
int sc_main(int argc, char* argv[]) {
// Standard SystemC signal bridging the two domains
sc_core::sc_signal<bool> alert_sig("alert_sig");
// AMS continuous-time signal (using sca_tdf::sca_signal)
sca_tdf::sca_signal<double> analog_wire("analog_wire");
// Instantiate modules
SineGenerator sine("sine");
sine.analog_out(analog_wire);
ADC_Model adc("adc");
adc.analog_in(analog_wire);
adc.threshold_alert(alert_sig);
DigitalMonitor monitor("monitor");
monitor.alert_in(alert_sig);
std::cout << "Starting Mixed-Signal Simulation..." << std::endl;
// Simulate for 2 milliseconds
sc_core::sc_start(2, sc_core::SC_MS);
return 0;
}Bridging the Gap: Converter Ports
The magic in the example above lies in sca_tdf::sca_de::sca_out<bool>.
To cross domains, SystemC AMS provides specialized converter ports:
sca_tdf::sca_de::sca_in<T>: Reads a standard SystemCsc_signal<T>from within the TDFprocessing()method.sca_tdf::sca_de::sca_out<T>: Writes to a standard SystemCsc_signal<T>.- Under the Hood: When
sca_tdf::sca_de::sca_out::write(val)is called inside theprocessing()callback, the AMS solver delegates the call to the boundsc_signal<T>::write(val). Because this standard SystemCwrite()operates normally, it triggers anrequest_update()in the SystemC discrete-event kernel. In the next discrete-event Update Phase, standard SystemC processes sensitive to that signal are made runnable.
- Under the Hood: When
Summary
SystemC AMS allows you to model RF, power, and analog subsystems within the same executable as your digital RTL and TLM firmware. By leveraging TDF and understanding how the AMS cluster scheduling integrates natively with the sc_simcontext time queue, you achieve extremely fast simulation speeds while maintaining enough accuracy for architectural exploration, power modeling, and mixed-signal verification.
Can you answer these clearly?
Keep moving when you can answer each question without looking back at the lesson.
Comments and Corrections