AMS Modeling Style for Virtual Platforms
How to combine SystemC AMS with a VP without turning a software platform model into a slow analog simulation.
AMS Modeling Style for Virtual Platforms
SystemC AMS can enrich a Virtual Platform (VP), but it should not accidentally change the purpose of the VP. Virtual platforms are primarily designed for fast software execution, whereas analog simulations often require fine-grained time steps that slow down simulation significantly.
When AMS Belongs in a VP
According to the SystemC AMS standard (IEEE 1666.1), you should use AMS when software-visible behavior depends on analog or signal-processing effects:
- ADC sample streams
- Sensor thresholds
- PLL lock approximation
- Power or thermal trends
- Filters
- Motor-control feedback
Do not use AMS merely to make the model look more advanced.
Good VP Boundary
A practical mixed VP usually has:
- A TLM register block for software programming.
- An AMS cluster (TDF or LSF) for signal behavior.
- Converter ports (e.g.,
sca_tdf::sca_in,sca_tdf::sca_outconnected tosc_core::sc_signal) for control and status between the AMS and discrete-event worlds. - Interrupts or status registers for software-visible results.
The software should still see registers, memory, and interrupts, modeled via standard TLM-2.0 or Simple Bus abstraction.
Complete AMS to SystemC Boundary Example
Below is a fully compilable sc_main program demonstrating how to interface an AMS TDF (Timed Data Flow) model representing an ADC with a standard SystemC discrete-event module representing a simple Virtual Platform peripheral register block.
#include <systemc>
#include <systemc-ams>
// 1. AMS TDF Module (The Analog / Continuous Part)
SCA_TDF_MODULE(adc_sensor) {
// Converter port: Continuous output to Discrete Event (DE) domain
sca_tdf::sca_out<double> analog_out;
// Internal state
double current_val;
SCA_CTOR(adc_sensor) : analog_out("analog_out"), current_val(0.0) {}
void set_attributes() override {
// Set a coarse timestep so we don't slow down the VP unnecessarily
set_timestep(1.0, sc_core::SC_MS);
}
void processing() override {
// Simulate a slowly changing analog value (e.g., a temperature sensor)
current_val += 0.5;
if (current_val > 100.0) {
current_val = 0.0;
}
// Write out the analog value to the converter port
analog_out.write(current_val);
}
};
// 2. VP Peripheral (The Discrete Event / Software Visible Part)
SC_MODULE(vp_adc_peripheral) {
// Input from the AMS domain
sc_core::sc_in<double> analog_in;
// Interrupt output to the CPU
sc_core::sc_out<bool> irq_out;
// A simple threshold register programmable by software
double threshold_reg;
SC_CTOR(vp_adc_peripheral) : analog_in("analog_in"), irq_out("irq_out"), threshold_reg(50.0) {
SC_METHOD(monitor_threshold);
sensitive << analog_in; // Trigger whenever the AMS converter writes a new value
dont_initialize();
}
void monitor_threshold() {
double current = analog_in.read();
// If the analog value crosses the software-programmed threshold, trigger an interrupt
if (current >= threshold_reg) {
irq_out.write(true);
std::cout << "@ " << sc_core::sc_time_stamp()
<< " VP ADC: Threshold crossed! Value: " << current
<< ", raising IRQ." << std::endl;
} else {
irq_out.write(false);
}
}
};
// 3. Top-Level Integration
int sc_main(int argc, char* argv[]) {
// Signals
sc_core::sc_signal<double> analog_sig("analog_sig");
sc_core::sc_signal<bool> irq_sig("irq_sig");
// Instantiation
adc_sensor ams_block("ams_block");
vp_adc_peripheral vp_block("vp_block");
// Binding
ams_block.analog_out(analog_sig);
vp_block.analog_in(analog_sig);
vp_block.irq_out(irq_sig);
// Run simulation
std::cout << "Starting mixed AMS/VP simulation..." << std::endl;
sc_core::sc_start(200.0, sc_core::SC_MS);
std::cout << "Simulation finished." << std::endl;
return 0;
}Performance Rule
Keep AMS timesteps as coarse as the use case allows. A VP that needs to boot firmware should not spend most of its time solving unnecessary high-resolution analog detail. In the example above, a 1.0 ms timestep was used to minimize context switches between the AMS solver and the SystemC kernel.
Documentation Rule
For each AMS block in a VP, document:
- Model of computation (e.g., TDF, LSF, ELN)
- Timestep and rates
- Delays
- Boundary ports (Converter type)
- Numerical approximations
- Software-visible effects (IRQs, specific register behaviors)
This lets users understand what is accurate, approximate, and intentionally ignored.
Comments and Corrections