Sinelabore Homepage

Generating C++ code from SysML v2 textual models#

New: For guidance on structuring models for simulation and testing see the Modeling Guide for Simulation and Testing.

SysML logo

SysML® v2 is a newer version of SysML that is more flexible and powerful. An important aspect is that it now allows you to write textual models. This lowers the barrier to model-based systems engineering considerably, because no special tools are needed to write the models. For example, a Visual Studio Code plugin is available to write SysML v2 models. The Sinelabore Code Generator supports code generation from SysML v2 models. Unlike the current Sinelabore capabilities, the code generation also supports the generation of structural code and not just the generation of state machine code.

Code for parts, interactions between parts, and so on is also generated. This can be used to quickly generate mock-ups and simulations of an intended system.

To generate C++ code from a SysML model call the code generator with the command line flag -p Sysml2Text.

Visual Studio Code with SysML plugin

A fully functional example is available on our GitHub site.

Introduction#

The SysML v2 backend focuses on executable models: state machines in parts, ports and connections between parts, and action behavior you can simulate in C++. Not every SysML v2 language feature is covered yet; support grows with each release. For how to structure models for simulation and testing see the Modeling Guide. Release highlights are in the news (e.g. 7.1, 7.2, 7.2.6).

To execute the generated code a small header-only runtime environment is provided. It contains some base classes and implements inter-part communication via ports and timeout handling — the minimum needed to run a model.

In case a part contains a state machine the code generator also generates additional files for the state machine. This code follows the structure that is already used by the cppx backend.

  • Parts: Parts are the main building blocks of a system. They can contain other parts, attributes, a state machine, actions, enums, connections and ports. Parts are realized as C++ classes in the generated code. Part usages may have multiplicity (e.g. part a[4] : A;). If a part contains other parts you are responsible to create them in the init method. Create a subclass of the part class and override the init method. Then call the base class init method. Example: part def P1{part p2:P3;}
  • Items: An item definition is a kind of occurrence definition for identifiable objects that may flow through a system or be acted on over time, such as data, signals, or fluids. A part is a specialized kind of item. Item definitions are translated to C++ structs or classes in the generated code. Item and attribute usages may use multiplicity (e.g. item scenario : WayPoint[0..5];). Example: item def Fuel { attribute volume : Integer; } See Items.
  • Attributes: Parts can have attributes. Attributes can have a base type, a default value, and multiplicity. Attributes can contain other attributes. Attributes are translated to C++ member variables. Depending on the type of the attribute it is realized as a basic data type or a class. Example: attribute a:bool;
  • Enums: Basic enums with their enum values can be defined. Enums are directly translated to C++ enums in the generated code. Example: enum def Color{RED; GREEN; BLUE;}
  • Ports: Ports are communication points between parts. The framework has some helper classes to realize ports. A port marked as in has a receive method, a port marked as out has a send method in the generated C++ code. Example: port def p {attribute x : Integer;}
  • Connections: Connections are the way to connect ports of parts in order to share data. Connections are realized as queues in the generated code. Only ports of the same type can be connected. One part must be marked as in, one as out. If you need bidirectional communication you can add two other ports in opposite direction. All attributes in a port share the same direction. Example: connect p1.sendPort to p2.recvPort;
  • State Machines: A part can have a state machine. Supported features include hierarchical states, timed and guarded transitions, history, final states, and parallel (orthogonal) regions (state def SM parallel { … }). Example: {state def sm { ... }}
  • Packages and imports: Packages map to C++ namespaces. Several packages may live in one model file. Same-file membership and wildcard imports (e.g. import Types::Sensor; / import Types::*;) are resolved for code generation. Splitting a model across multiple files is not supported yet.
  • Specialization: Parts and attributes can specialize and redefine features (:>, :>> / redefines). Usages may use ref, abstract, and subsets where needed for structure and collections.

Recent releases#

  • 7.1: Actions as structs, action control flow, part multiplicity, history.
  • 7.2: State machine improvements, items, attribute arrays, for … in.
  • 7.2.6: Same-file imports, parallel regions, ref / subsets / :>>, package-level actions.

In the sub-pages that describe the supported features of the code generator text references are made to: OMG Systems Modeling Language™ (SysML®), Version 2.0 Part 1: Language Specification. OMG Document Number: formal/2026-03-02 Date: March 2026, Standard document URL: https://www.omg.org/spec/SysML/2.0/

The following listing shows an example for a small traffic light control system model. It consists of three parts with some attributes and actions. The TrafficManagementCenter part represents a central control system that can control TrafficLightController parts connected via ports.

In this simple model the TrafficManagementCenter just enables traffic light controllers to operate by sending a start event. The TrafficLightController then changes state from OutOfService to Operational and performs expected traffic light operations. In a real system, this simulation would certainly be much more complex. But the example is rich enough to show the available possibilities. The TrafficLightSystem part weaves together the TrafficManagementCenter and the TrafficLightController parts.

private import ScalarValues::*;

package TrafficLight {


    // definition of events for the traffic light controller
    enum def TRAFFICLIGHTCONTROLLERSM_EVENT_T {
        //@TrafficLightController
        evOperational;
        evError;
    }

    //@TrafficManagementCenter
    enum def TRAFFICMANAGEMENTCENTERSM_EVENT_T {
    }

    port def ControlPortData {
        attribute msg : TRAFFICLIGHTCONTROLLERSM_EVENT_T;
        attribute test:Integer;
    }

    part def Test{}

    // traffic management center
    part def TrafficManagementCenter{
        out port sendPort : ControlPortData;
        part test1 : Test;

        state def tmcStateMachine {
            entry; then PreOperational;

            state PreOperational;
            accept after 2[SI::second] do send new ControlPortData(TRAFFICLIGHTCONTROLLERSM_EVENT_T::evOperational,5) via sendPort then Operational;

            state Operational {

            }

        }
    }

    part def TrafficLightController{

        in port recvPort : ~ControlPortData;
        part test1 : Test;

        action def setRedLED{}
        action def resetRedLED{}
        action def setYellowLED{}
        action def resetYellowLED{}
        action def setGreenLED{}
        action def resetGreenLED{}
        action def setRedAndYellowLED{}
        action def resetRedAndYellowLED{}

        state def tlcStateMachine {
            ...
        }
    }
    // Main system composition
    part def TrafficLightSystem {
        doc /*
        * Main system that contains the parts
        */
        part tmc : TrafficManagementCenter;
        part tlc : TrafficLightController;

        // Connect the parts
        connect tmc.sendPort to tlc.recvPort;
    }
}

The SysML code generation is work in progress#

SysML v2 is a very rich modeling language. The features listed in the introduction and on the sub-pages are supported for C++ generation. The following are still limited or unsupported (list is not exhaustive). Take a look at the GitHub examples to see what is used in practice.

  • Absolute-time transitions (accept at …) — timed transitions use accept after only
  • Inner transitions
  • Multi-file models — the complete model must reside in a single file (multiple packages and same-file imports in that file are fine)
  • Standard library types beyond basic scalar mapping — import ScalarValues::* and similar mainly satisfy editors; full ISQ/SI library stubs are not generated
  • Keywords such as ordered / unique on attributes are not fully tracked for codegen
  • Additional enum features beyond a basic definition
  • Inter-part communication beyond ports and connections as shown above
  • Many other SysML features not shown in the examples

See also the Modeling Guide supported-features summary.