Chapter 8: SystemC AMS

SystemC AMS (Analog/Mixed-Signal)

An introduction to the SystemC AMS standard, Timed Data Flow (TDF), and modeling continuous-time signals.

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.

The Three Models of Computation in AMS

SystemC AMS introduces three mathematically distinct Models of Computation (MoC) that interoperate with the discrete SystemC kernel:

  1. 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.
  2. Linear Signal Flow (LSF): Used to model continuous-time behavior using primitive blocks like integrators, differentiators, and adders.
  3. 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

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().

Complete AMS Interoperability Example

This 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 SystemC sc_signal<T> from within the TDF processing() method.
  • sca_tdf::sca_de::sca_out<T>: Writes to a standard SystemC sc_signal<T>, scheduling standard delta-cycle updates in the discrete-event kernel.

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, you achieve extremely fast simulation speeds while maintaining enough accuracy for architectural exploration, power modeling, and mixed-signal verification.

Comments and Corrections