Skip to content

Streaming Approach

To connect the external SystemC component to FERAL, it is necessary to create a C-fcapi-client that includes the FERAL Gateway library described in the FCAPI component. Further, the external SystemC code must include the SystemC FERAL library, and the control of the simulation needs to be done in a Java class.

The following is an example, where the user SystemC code basically receives data from FERAL and sends back to FERAL.

To start, you need to create a directory that contains your external SystemC component and a cpp file containing the C-fcapi-client configuration. The name of this cpp file is used to find the counterpart in FERAL. In this illustrative example, the name is {"ExampleSendReceive.cpp"}, and the fcapi-client is configured to have two ports, a receiver and a sender.

External SystemC component

The external SystemC Module must include the systemc library and the socket headers. For this send/receive application, the external SystemC code can be written as:

SystemCModule.h
#include <systemc.h>
#include "tlm_utils/simple_initiator_socket.h"
#include "tlm_utils/simple_target_socket.h"

SC_MODULE(SystemCModule) {
public:
// Declare communication sockets
tlm_utils::simple_initiator_socket<SystemCModule> iSocket;
tlm_utils::simple_target_socket<SystemCModule> tSocket;


    SC_CTOR(SystemCModule):iSocket("iSocket"), tSocket("tSocket") {

        tSocket.register_b_transport(this, &SystemCModule::b_transport);

    }

    ~SystemCModule() {
    }
    // In this function you can include or call data processes functions!
    void b_transport(tlm::tlm_generic_payload& trans, sc_time& delay){
        delay = delay + sc_time(0, SC_US);
        iSocket->b_transport(trans, delay);
    }

FCAPI-C Client

The following cpp file contains the FERAL connection setup.

ExampleSendReceive.cpp
#include <systemc.h>
#include "systemcferal.h"
#include "feralcapi.h"

#include "SystemCModule.h" // This is the user specific SystemC code

int sc_main(int __attribute__((unused)) argc, char __attribute__((unused)) *argv[])
{

    fcapi_init();
    fcapi_logAllToStdOut();

    {
        // Setup FERAL Connection:
        Connection_t conn;
        fcapi_connectionInit(&conn, UDP, NULL, 44444, NULL, 0);

        sc_time stepSize = sc_time(10, SC_US); // Define the time step for the events

        FERALControl ctrl("Sync", &conn, stepSize); //

        // Setup SystemC Side:
        SystemCModule module("module"); 

        Connection_t txConn; // Send port
        fcapi_connectionInit(&txConn, UDP, NULL, 44444, NULL, 0);
        Connection_t rxConn; // Receive port
        fcapi_connectionInit(&rxConn, UDP, NULL, 44444, NULL, 0);

        uint32_t dataInputSize = stoi(argv[1]);
        uint32_t dataOutputSize = stoi(argv[2]);

        LTDataPortInitiator dpIni("dataportIni", &rxConn, "apple", dataInputSize);
        LTDataPortTarget dpTgt("dataportTgt", &txConn, "banana", dataOutputSize);

        // Connect all components:
        dpIni.iSocket.bind(module.tSocket);
        module.iSocket.bind(dpTgt.tSocket);

        ctrl.syncPort.bind(dpTgt);
        ctrl.syncPort.bind(dpIni);

        sc_start();

    }

    fcapi_terminate();
    return 0;
}

Simulation scenario

Ones defines the SystemC part, the simulation scenario must be created in a java class. The scenario is based on the Gateway implementation, and it is included as a nested class of our example class. Thus:

ExampleSendReceive.java
class ExampleSendReceive {
static class ScenarioWithGateway extends GatewayExampleBaseScript implements Runnable {

        public ScenarioWithGateway() {
            // Simulation setup
            // - create scenario
            scenario = new SimulationScenario();
            // - create root
            director = new DiscreteEventMOCC(scenario);

            // Gateway setup
            // - Create FERAL gateway for a given backend message protocol
            createGatewayFERAL(director, TransmissionBackend.UDP, 1, 44444);

            // - create ports for TX, RX, and synchronization
            createFERALGatewayPorts(gateway, "banana", "apple", "Sync");

            // - Create sender
            ByteArrayProvider provider = new ByteArrayProvider(director);
            // - Create receiver
            ByteArrayReceiver receiver = new ByteArrayReceiver(director);

            // - Setup links from/to C modul
            new Link(provider.getOutputPort("output"), gateway.getInputPort("apple"));
            new Link(gateway.getOutputPort("banana"), receiver.getInputPort("input"));
        }

        // Initialize simulation scenario
        @Override
        public void run() {
            scenario.startSimulation(SimulationDuration.us (100));
        }
    }
    public static void main{
        ScenarioWithGateway scenario = new ScenarioWithGateway();
        new Thread(scenario).start();

        inputSize = "2";
        List<String> inputs = new ArrayList<>(Arrays.asList(inputSize,inputSize));
        // launch system c
        List<String> stdOut = new ArrayList<>();
        final int exitCode = ExecutableRunner.runExecutableSync
        ("target/path_to_the_compiled/C-fcapi-client_file/ExampleSendReceive", inputs, stdOut, false);

    }
}

Note

The ByteArrayProvider and ByteArrayReceiver are defined as is indicated in the Create a Simulation section.