SysML v2 - First Experiments

A new release of SysML is upcoming. The latest version is v2.0 beta 1 - it's a modeling language that helps you design also complex systems.

The standard is developed by the OMG (https://www.omg.org/spec/SysML) and its member companies. While SysML v1 has been around for several years and is based on UML, SysML v2 represents a significant evolution.

I wanted to explore the current status of SysML v2 and understand what it would mean to support it as another input or output format for code generation.

A really nice feature of SysML v2 is that it specifies both a textual representation of a model as well as a graphical one. You can work either on text or graphically and can switch between one or the other view – whatever is more convenient for you. Of course, the modeling tool must support this.

What to expect from this post

A practical introduction to SysML v2 concepts through a familiar example

Code examples that show how SysML v2 syntax works

Note: I'm still learning SysML v2 myself, so this is from a practitioner's perspective

Selecting a tool

To get started, it is highly recommended to use a tool. I found and the following tools:

Visual Studio Code plugins: Provides syntax highlighting, error hints, and navigation features. Great for learning the syntax (e.g. SysIDE).

Eclipse project: Similar features to the VSC plugin, plus it supports a new PlantUML version that can directly render selected model parts. This is nice for visualization, but doesn't work well for larger models. You'll find many small code snippets with their graphical representations online, but complex models aren't rendered as nicely.

SysOn browser-based tool: Available as a Docker image and based on the Eclipse Sirius Web platform. Offers a promising user interface and can import/export textual models. Still in development and probably too much for the first steps.

More is available here: https://mbse4u.com/mbse-tools/

Getting started using the Eclipse plugin

A microwave oven is the example used in all the SinelaboreRT manuals and examples. I wanted to model that too in SysML v2. This is a perfect example because it's a familiar embedded system that combines hardware and software components.

My approach was to break down the oven into its parts (similar to how you might break down a software system into classes or modules) and model the interactions via ports (think of these as interfaces) and the main behavior with a state machine.

Defining parts

This step was quite simple and feels very natural. The physical parts of the oven became model parts . I organized everything in a package .

The language also supports formal documentation, so tools can extract the “doc” parts later for generating documentation. Here's what the basic structure looks like:

private import ScalarValues::*; package OvenPackage { part def MicrowaveController{ doc /* * The controller interacting with all the peripheral parts */ } part def Motor{ doc /* * Motor driving the rotating plate */ } part def CountDownTimer{ doc /* * Timer that once started counts down to zero and stops the oven * Can be paused and changed any time. */ } part def Door{ doc /** * Representing the door that emits events if closed or opened */ } part def Display{ doc /** * General display to show oven status */ } part def LedDisplay :> Display{ doc /** * Specialization of generic display that has only some LEDs to show the oven status */ } part def TimeWheel{ doc /** * Rotary wheel that can increment and decrement the cooking time. */ } }

The graphical view shows the parts as expected. Notice how each part is represented as a box, similar to a class diagram in UML.

{{:wiki:sysml2:oven-part1.png|[Oven Parts - The basic structure showing all the parts of the microwave oven]

How parts can interact

This is where it gets interesting but also more complex. SysML v2 has many concepts for modeling interactions, and it can feel overwhelming at first. I'm still learning which concepts work best for different scenarios. But others seem to have similar questions (see https://mbse4u.com/2024/12/02/which-sysml-v2-element-to-choose/) One preferred approach is to let parts interact using ports (I think of these as interfaces or connection points). Ports can transfer events and data flows. Given my background in state-based, event-triggered systems, it felt natural to first model the events I could identify.

My design approach was to let the MicrowaveController receive events from the Door and the CountDownTimer, while it sends events to the Motor and Radiator. This creates a clear flow of information and control.

For modeling events, I found several approaches in examples. I ended up modeling them as enums, though attributes and item-based concepts also seem possible.

// definition of events from door sensor enum def DoorSensorEvents{ evDoorOpened; evDoorClosed; } // definition of events to control motor enum def BinaryCommands{ On; Off; } // events from the time selection interface enum def TimerEvents{ evTimeout; } enum def TickEvents{ evTick; }

Now let's define the ports. Think of these as the interfaces that define how parts communicate. The OnOffPort can be reused for both the Radiator and the Motor since they both respond to simple on/off commands.

// ports to connect parts port def TimerPort{ out timeEvent : TimerEvents; out attribute timeInSec : Positive; } port def DoorEventsPort { out doorEvt : DoorSensorEvents; } port def OnOffPort{ in motorCmd:BinaryCommands; } port def TickPort{ out tick:TickEvents; }

Now let's add the ports to the parts. Here's an example showing how to add ports to parts. The ~ symbol indicates a “conjugate” port (the opposite direction - if sometinng is `in` on one side, the conjugate is `out` on the other side).

part def Radiator{ doc /* * Element generating the micro waves */ in port onOffPort : OnOffPort; } part def MicrowaveController{ doc /* * The controller interacting with all the peripheral parts */ in port doorPort : ~DoorEventsPort; // receive in port timerPort: ~TimerPort; out port motorPort : OnOffPort; // send out port radiatorPort : OnOffPort; // send }

The generated graphical representation now shows the ports on each part.

Oven Part 2 - Parts with their ports showing the interface connections

Now let's connect the parts together. SysML allows modeling connections in different ways - you can use explicit interfaces, or connect parts directly. Here's how to define the complete `Oven` with all its internal connections:

part oven:Oven{ part controller : MicrowaveController; part motor : Motor; part cdTimer : CountDownTimer; part display : LedDisplay; part door: Door; part radiator: Radiator; part tick:Ticker; connect door.doorPort to controller.doorPort; connect cdTimer.timerPort to controller.timerPort; connect tick.tickPort to cdTimer.tickPort; connect controller.motorPort to motor.motorPort; connect controller.radiatorPort to radiator.onOffPort; }

The generated diagram shows the complete system structure. Unfortunately, there's no way yet to control the image layout to make port names more readable - more powerful tools will realize this in a better way for sure. However, the overall structure is clear at first glance. You can also see that the display isn't connected yet (a task for you:-)).

Oven Part III - Complete system showing all connections between parts

Adding attributes to parts

SysML allows adding attributes of various complexity to parts. Attributes can have units, and SysML v2 comes with a comprehensive standard library that defines SI units and much more.

This makes it possible to model real-world properties like power consumption for key parts. Many practical use cases come to mind here - think of reasoning battery life, thermal management, or resource requirements.

Radiator with an attribute - Showing power consumption in watts

Adding state machine behavior to parts

This was the most interesting part for me to understand what capabilities the new SysML v2 language offers. State machines are familiar to most embedded software developers - they help model how a system responds to events and changes its behavior over time.

Let's add a state machine to the MicrowaveController. Initially, the syntax looks clear and easy. The default state is expressed with entry; then Off; - this means “start in the Off state.”

part def MicrowaveController { state MicrowaveControllerStateMachine{ entry; then Off; state Off{ } state Run{ } state Pause{ } } }

The generated PlantUML image shows a simple state machine with three states, which looks promising for modeling behavior.

Statemachine first step - Basic state machine with Off, Run, and Pause states

Now let's add transitions to the state machine. Here's how the syntax works:

first Run means “from the Run state”

accept DoorSensorEvents via doorPort means “listen for events on the doorPort”

The if statement specifies which specific event triggers the transition

then Pause defines the target state

A nice new feature is that transitions can be triggered at defined points in time or after a certain duration. Due to the textual specification option it is now easy to write down. This was always a weak point in UML tools.

Entry/Do/Exit actions are also possible. In the example, we use Do actions to send events (the payload) via ports to connected parts. You can also use action calls with input and output parameters.

state MicrowaveControllerStateMachine{ entry; then Off; transition first Run accept DoorSensorEvents via doorPort if (doorPort.doorEvt==DoorSensorEvents::evDoorOpened) then Pause ; transition first Pause accept DoorSensorEvents via doorPort if (doorPort.doorEvt==DoorSensorEvents::evDoorClosed) then Run ; transition first Off accept DoorSensorEvents via doorPort if (doorPort.doorEvt==DoorSensorEvents::evDoorClosed) then Run ; transition first Run accept TimerEvents via timerPort if (timerPort.timeEvent==TimerEvents::evTimeout) then Off ; transition first Pause accept TimerEvents via timerPort if (timerPort.timeEvent==TimerEvents::evTimeout) then Off ; state Off{ do send BinaryCommands::Off via motorPort; } state Run{ do send BinaryCommands::On via motorPort; } state Pause{ do send BinaryCommands::Off via motorPort; } }

The state machine can be visualized, though automatic layout engines have their limitations in creating optimal diagrams.

Statemachine second step - Complete state machine with all transitions and actions

As we've seen, SysML v2 allows modeling nested state machines (parallel states are also possible) and defining transitions with relevant actions within states.

But wait - there's something missing

If you're familiar with UML state machines, you'll quickly notice that some features aren't (yet) available. For example, there are no Choice or Flat/Depp History. I'm not sure if this will be added later or was excluded by design. To make up your own mind checkout chapter 7.17 page 108ff of the present spec.

Summary and Next Steps

SysML v2 is very promising, especially because of its textual representation. This opens up many new use cases and makes them much easier to implement. Think about version controlling models in Git, making diffs, and collaborative development - all the practices software developers are familiar with.

Reasoning on models will also become normal. Consider the power consumption example above - you could automatically calculate total system power requirements. Or imagine using AI to ask questions about a model. (By the way, current AI tools make many errors when answering questions about SysML v2 syntax - I guess there simply isn't enough training material yet, or it's too new.)

Why should software developers care?

Requirements management: SysML v2 helps bridge the gap between system requirements and software implementation

Architecture documentation: Models serve as living documentation that stays in sync with your code

Team communication: Visual models help communicate complex system designs across teams

Code generation: While not perfect, models can generate skeleton code and interfaces

Code generation considerations

Does it make sense to directly generate C/C++ or any other language code from SysML models? The pure model won't be sufficient. For example, the interaction of parts via ports can be realized in very different ways depending on the targeted system. So a mapping between the model and implementation is required, and that mapping should be flexible to adapt to concrete needs (e.g., using OS signals in one case or queues in another).

Next steps for learning more

Explore the [OMG SysML v2 specification](https://www.omg.org/spec/SysML)

Try the tools mentioned in this post

Start with a simple system you're familiar with

Consider how SysML v2 could fit into your existing development workflow

What do you think? How could you benefit from using SysML v2?

Feedback Welcome!

I'm still learning SysML v2 myself, so if you're an experienced SysML practitioner and have suggestions for modeling this example more naturally or effectively, I'd love to hear from you!

Feel free to share:

Better approaches to modeling the microwave oven system

Alternative ways to structure the parts and their interactions

Improvements to the state machine design

Any SysML v2 best practices I might have missed

Thanks in advance for your insights!