Chapter 14: SystemC

CCI Overview & Architecture

Introduction to IEEE 1666.1 Configuration, Control, and Inspection for IP configuration.

Configuration, Control & Inspection (CCI)

SystemC Virtual Platforms integrate dozens of IP blocks from different vendors. Configuring the memory map, clock speeds, and debug verbosities of these independent blocks traditionally required proprietary C++ macro hacks or custom text parsers.

The IEEE 1666.1 Configuration, Control, and Inspection (CCI) standard eliminates this fragmentation by providing a unified, LRM-compliant configuration API.

Core CCI Architecture

CCI relies on three foundational pillars:

  1. The Parameter (cci_param): A wrapper around standard data types that exposes them to the CCI subsystem.
  2. The Broker: A central, hierarchical registry where all parameters are automatically registered.
  3. The Originator: An identifier tracking who or what created or modified a parameter (crucial for debugging large SoCs).

Complete CCI Top-Level Example

This sc_main example demonstrates how a system integrator configures a third-party IP block using the Global CCI Broker before the hardware is even elaborated.

#include <systemc>
#include <cci_configuration>
 
// 1. Third-Party IP Block
SC_MODULE(UART_Controller) {
    // Expose parameters to the CCI broker
    cci::cci_param<int> baud_rate;
    cci::cci_param<bool> debug_enable;
 
    SC_CTOR(UART_Controller) 
        // Parameters take a name, a default value, and an optional description
        : baud_rate("baud_rate", 9600, "UART Baud Rate")
        , debug_enable("debug_enable", false, "Enable verbose UART debug")
    {
        SC_METHOD(run);
    }
 
    void run() {
        if (debug_enable.get_value()) {
            std::cout << "@" << sc_core::sc_time_stamp() 
                      << " [UART] Booting at baud rate: " << baud_rate.get_value() << std::endl;
        }
    }
};
 
// Top Level VP Wrapper
SC_MODULE(TopVP) {
    UART_Controller uart;
    SC_CTOR(TopVP) : uart("uart") {}
};
 
int sc_main(int argc, char* argv[]) {
    // 1. Acquire the Global CCI Broker
    cci::cci_broker_handle broker = cci::cci_get_broker();
 
    // 2. Set "Preset" Values BEFORE Elaboration
    // These hierarchical strings must match the SystemC elaboration tree exactly.
    broker.set_initial_preset_value("top.uart.baud_rate", cci::cci_value(115200));
    broker.set_initial_preset_value("top.uart.debug_enable", cci::cci_value(true));
 
    // 3. Elaborate the Virtual Platform
    // As the UART constructor runs, its cci_params will query the broker 
    // and adopt the preset values (115200 and true) instead of their defaults!
    TopVP top("top");
 
    // 4. Start Simulation
    sc_core::sc_start(10, sc_core::SC_NS);
 
    return 0;
}

By standardizing on cci_param, IP providers ensure their models can be configured seamlessly in any IEEE 1666.1 compliant simulation environment, allowing for pure data-driven (JSON/XML) configuration scripts rather than hardcoded C++.

Comments and Corrections