Simer - Simulation Runner

Synopsis

Containerised simulation run-time.

# Run a simulation.
$ simer path/to/simulation -stepsize 0.0005 -endtime 0.04

Simulation Setup

Structure

The structure of a simulation is flexible and can be arranged based on individual project needs. All paths used within a simulation configuration should be relative to the root of the simulation folder (i.e. the simulation path). The simer tool will search for YAML files contained within the simulation path and automatically configure, and then run, the contained simulation.

The following example simulation layout is generated by the SDP Builder.

Example Simulation Structure
path/to/simulation                  <-- simulation path
└── data
    └── simulation.yaml             <-- Simulation definition 
└── model
    └── input                       <-- Model 'input'
        └── data
            └── model.yaml          <-- Model definition
                signalgroup.yaml    <-- Signal definitions
                input.csv           <-- Data used by the model
        └── lib/libcsv.so           <-- Model library
    └── linear                      <-- Model 'linear'
        └── data/signalgroup.yaml   <-- Signal definitions
        └── lib/libfmimcl.so        <-- FMIMCL library (FMU loader)
            lib/fmu3linear.so       <-- FMU library

Simulation Stacks

A simulation can be further structured by using several Stack definitions in the simulation.yaml file. This enables parts of the simulation to be partitioned according to either structural, deployment or operational constraints. Simer can then be used to run the appropriate stacks (i.e. those that will use a Linux/Container runtime) while the remaining stacks are run in their appropriate ‘remote’ systems.

32-Bit Models

The Simer runtime supports two 32-bit Linux architectures:

  • linux-x86 - model runtime flag x32, compiler flags: -mx32
  • linux-i386 - model runtime flag i386, compiler flags: -m32

Models which should run with either of these architectures can be configured in a stack via either the runtime.x32 or runtime.i386 property of the model. Simer will then select the correct ModelC runtime to run these models.

Note: Simulation stacks configured with either a stacked or sequential runtime are run by Simer in a single ModelC instance. Therefore all models in such a simulation stack must have the same runtime properties.

Example Linux-x86 Stack
simulation.yaml
---
kind: Stack
metadata:
  name: simulation
spec:
  models:
    - name: x32_model_instance
      uid: 45
      model:
        name: X32_Model
      runtime:
        x32: true
      channels:
        - name: signal_channel
          alias: signal
Example Linux-i386 Stack with ‘stacked’ Runtime
simulation.yaml
---
kind: Stack
metadata:
  name: simulation
runtime:
  stacked: true
spec:
  models:
    - name: foo
      uid: 1
      model:
        name: I386_Model_Foo
      runtime:
        i386: true
      channels:
        - name: signal_channel
          alias: signal
    - name: bar
      uid: 2
      model:
        name: I386_Model_Bar
      runtime:
        i386: true
      channels:
        - name: signal_channel
          alias: signal

Remote Models

Simulations which contain remote models, such as gateway models running in foreign simulation environments, or Windows based models, can be configured in a separate stack(s). When the simulation is run by the simer tool, only a selected list of stacks/models can be started. The remaining stacks and/or gateway models are then started in their own environment, and once started they can connect to the simulation running in the simer tool.

Hint: Models which need to be run with an older version of the simer tool can be defined in their own stack and run independently (i.e. using an older version of Simer).

Example Remote Stack with Gateway Model
simulation.yaml
---
kind: Stack
metadata:
  name: linux
spec:
  models:
    - name: simbus
      model:
        name: simbus
      channels:
        - name: signal_channel
          expectedModelCount: 2
    - name: model_instance
      uid: 1
      model:
        name: Model
      channels:
        - name: signal_channel
          alias: signal
---
kind: Stack
metadata:
  name: remote
spec:
  connection:
    transport:
      redispubsub:
        uri: redis://somehost:6379
        timeout: 60
  models:
    - name: gateway_instance
      uid: 2
      model:
        name: GatewayModel
      channels:
        - name: signal_channel
          alias: signal
# Start the simulation (excluding Remote models).
$ simer path/to/simulation -stack linux -endtime 0.1

# Now start the Remote models ...

Stacked Models

Several models may be run stacked into a single ModelC runtime instance by setting the runtime:stacked property of their stack to true. The simer tool will start all models in that stack in a single instance of the ModelC runtime.

Example Stacked Simulation with Loopback/Local SimBus
simulation.yaml
---
kind: Stack
metadata:
  name: simulation
spec:
  connection:
    transport:
      loopback:
        uri: loopback
  runtime:
    stacked: true
  models:
    - name: simbus
      model:
        name: simbus
      channels:
        - name: signal_channel
          expectedModelCount: 2
    - name: foo
      uid: 1
      model:
        name: Foo_Model
      channels:
        - name: signal_channel
          alias: signal
    - name: bar
      uid: 2
      model:
        name: Bar_Model
      channels:
        - name: signal_channel
          alias: signal

Environment & Files

Environment variables may be specified in either the runtime:env property of a stack or model, or with the -env CLI option of the simer tool. Environment variables set by the -env CLI option of the simer tool can be set for all models in the simulation, or targeted to a specific model.

# Set the SimBus transport to `redis` for all models in the simulation.
$ simer path/to/simulation -env SIMBUS_TRANSPORT=redis

# Set the log level for the 'simbus' model _only_.
$ simer path/to/simulation -env simbus:SIMBUS_LOGLEVEL=2

Environment variables are passed by the simer tool to the ModelC runtime in the order that they are defined: stack environment variables first, and then model environment variables, and lastly those specified via the -env flag(s). Values set later will overwrite those set earlier.

Additional Files may be specified in the runtime:files property of a model. The path of each listed file should be relative to the simulation path or an absolute path.

Example Stack with Environment & Files Specified
simulation.yaml
---
kind: Stack
metadata:
  name: simulation
spec:
  runtime:
    env:
      SIMBUS_LOGLEVEL: 4
  models:
    - name: simbus
      model:
        name: simbus
      channels:
        - name: data_channel
          expectedModelCount: 2
    - name: counter_A
      uid: 1
      model:
        name: Counter
      runtime:
        env:
          COUNTER_NAME: counter_A
          COUNTER_VALUE: 100
        files:
          - data/signalgroup.yaml
      channels:
        - name: data_channel
          alias: data
    - name: counter_B
      uid: 2
      model:
        name: Counter
      runtime:
        env:
          SIMBUS_LOGLEVEL: 3
          COUNTER_NAME: counter_B
          COUNTER_VALUE: 200
        files:
          - data/signalgroup.yaml
      channels:
        - name: data_channel
          alias: data

In this example the SIMBUS_LOGLEVEL is set to 4 for all models with the exception of the ‘counter_B’ model where this value is overridden and set to 3. Both models are configured to reference the same file data/signalgroup.yaml. This file will be located relative to the simulation path.

Simer Tool

Setup

Simer is a containerised simulation run-time which can be operated using a number of techniques. The container is suitable for use in automated workflows.

Container images are available and released with each new version of the ModelC project.

# Latest Simer Container:
$ docker pull ghcr.io/boschglobal/dse-simer:latest

# Specific versions of the Simer Container
$ docker pull ghcr.io/boschglobal/dse-simer:2.0.7
$ docker pull ghcr.io/boschglobal/dse-simer:2.0
Shell Function
# Define a shell function (or add to .profile file).
$ export SIMER_IMAGE=ghcr.io/boschglobal/dse-simer:latest
$ simer() { ( if test -d "$1"; then cd "$1" && shift; fi && \ 
    docker run -it --user $(id -u):$(id -g) --rm \
      -v $(pwd):/sim \
      -p 2159:2159 -p 6379:6379 \ 
      $SIMER_IMAGE "$@"; ) }

# Run the simulation.
$ simer path/to/simulation -endtime 0.04
Alias File / Function
function simer() {
    ( if test -d "$1"; then cd "$1" && shift; fi && \
      docker run -it --user $(id -u):$(id -g) --rm \ 
        -v $(pwd):/sim \
        -p 2159:2159 -p 6379:6379 \ 
        $SIMER_IMAGE "$@"; \ 
    )
}
export -f simer
# Run the simulation.
$ simer path/to/simulation -endtime 0.04
Makefile
SIMER_IMAGE ?= ghcr.io/boschglobal/dse-simer:latest
SIM_PATH := path/to/simulation
SIM_ENDTIME := 0.04

.PHONY: simer
simer:
	docker run -it --user $$(id -u):$$(id -g) --rm \
		-v $$(pwd)/$(SIM_PATH):/sim \
		$(SIMER_IMAGE) -endtime $(SIM_ENDTIME)
# Run the simulation.
$ make simer 
GitHub Workflow Action
jobs:
  simulation:
    runs-on: ubuntu-latest
    steps:
      - name: Simer
        uses: boschglobal/dse.sdp/actions/simer
        with:
          path: path/to/simulation
          endtime: '0.04'

Options

$ simer -h

SIMER (SIMulation runnER)
  
  Containerised simulation run-time. 
  Part of the Dynamic Simulation Environment Core Platform.
  
  repo: https://github.com/boschglobal/dse.modelc
  doc:  https://boschglobal.github.io/dse.doc/docs/user/simer

Examples:
  simer -endtime 0.1
  simer -stack minimal_stack -endtime 0.1 -logger 2
  simer -stepsize 0.0005 -endtime 0.005 -transport redis -uri redis://redis:6379
  simer -tmux -endtime 0.02
  simer -gdb simbus -tmux -endtime 0.004 -logger 2 -timeout 5

Flags:
  -endtime *flag.float64Value
        simulation end time (0.002)
  -env *simer.listFlag
        environment modifier, in format '-env MODEL:NAME=VAL'
  -gdb *flag.stringValue
        run this model instance via GDB, use CSL in format '-gdb simbus,model'
  -gdbserver *flag.stringValue
        attach this model instance to GDB server
  -logger *flag.intValue
        log level (select between 0..4) (3)
  -modelcI386 *flag.stringValue
        path to ModelC i386 executable (/usr/local/bin/modelc32_i386)
  -modelcX32 *flag.stringValue
        path to ModelC x32 executable (/usr/local/bin/modelc32_x86)
  -stack *flag.stringValue
        run the named simulation stack(s)
  -stepsize *flag.float64Value
        simulation step size (0.0005)
  -timeout *flag.float64Value
        timeout (60)
  -tmux *flag.boolValue
        run simulation with TMUX user interface (false)
  -transport *flag.stringValue
        SimBus transport (redispubsub)
  -uri *flag.stringValue
        SimBus connection URI (redis://localhost:6379)
  -valgrind *flag.stringValue
        run this model instance via Valgrind, use CSL in format '-valgrind simbus,model'

Tmux Interface

$ simer path/to/simulation -endtime 0.04 -tmux

The terminal multiplexer tmux is a technical CLI interface which makes it easy to observe the output of simulations which are comprised of several models. When using the tmux interface each Model is represented in its own terminal window, and it is possible to switch between terminal windows using tmux keyboard shortcuts. Some of these shortcuts are listed below.

Tmux Keyboard Shortcuts

Ctrl+b c
Create new window.
Ctrl+b p
Select previous window.
Ctrl+b n
Select next window.
Ctrl+b 0..9
Switch between tmux windows.
Ctrl+b w
List windows.
Ctrl+b [
Enter copy mode. Use VI keys to move cursor around the window (q to quit copy mode).
Ctrl+b PgUp
Enter copy mode and scroll up. Use VI keys to move cursor around the window (q to quit copy mode).

In copy mode use:

Spacebar
Start selection.
Esc
Clear selection.
Enter
Copy selection.
/
Search forwards.
?
Search backwards.

Finally, use:

Ctrl+b d
Detach from the tmux session (and exit the simulation!).

GDB Debug

GDB

Models (and the SimBus) running in the simer tool can be interactively debugged using GDB. This method of debugging requires the use of the Tmux interface.

# Start the simulation with the SimBus running under GDB.
$ simer path/to/simulation -tmux -gdb model_inst -endtime 0.04  -timeout 5

# Start the simulation with a model and the SimBus running under GDB.
$ simer path/to/simulation -tmux -gdb simbus,model_inst -endtime 0.04  -timeout 5

GDB Server (remote)

Models running in a simulation can be debugged with GDB by indicating which model is being debugged via the option -gdbserver, and then connecting a GDB instance to that model running “remotely” in the Simer simulation.

# Start the simulation and indicate the Model being debugged.
$ simer path/to/simulation -endtime 0.04 -tmux -gdbserver gdb_inst

# Start GDB (in a second terminal), and connect to the simulation.
$ gdb dse/modelc/build/_out/bin/modelc
(gdb) set solib-search-path path/to/simulation/lib
(gdb) target remote localhost:2159
(gdb) continue
(gdb) bt

Definitions

Channel
Represents a grouping of signals which are exchanged between models.
GDB
A tool for debugging software and investigating bugs (typically segmentation faults).
Model (Definition)
The definition of a model, specifying the location of libraries (for all supported os/arch combinations) as well as possible channel configurations.
Model (distribution/binary)
A packaged version of a model (including binaries and related artifacts).
Model Instance
An instance of a particular Model. Will include runtime properties.
ModelC
An implementation of a Model Runtime (i.e. Importer).
Redis
A data service used by ModelC instances to communicate with a SimBus. Redis is packaged in the Simer Container and started automatically (disabled by setting hidden parameter -redis to "").
Remote Model
A model configured in a simulation but which runs on a remote system.
Signal Group
A set, or subset, of signals which belong to a channel.
SimBus (Simulation Bus)
An implementation of a data exchange mechanism for scalar and binary signals.
Simulation
The structural arrangement of several Models, which, when connected via a Simulation Bus, form a simulation. Typically defined in a file simulation.yaml.
Simulation Package (simulation path/folder)
This folder contains all configuration, models and artifacts necessary to run a simulation.
Stack
Defines a list of models which should be run as a part of a simulation. Simulations may be defined by one or more stacks.
Stacked Models
A list/collection of models which are stacked into a single ModelC runtime instance.
Valgrind
A tool used to detect memory leaks. Run with valgrind as a part of a model QA strategy (i.e. as a part of E2E tests).
x32
The linux x32 ABI architecture specifier, for models which must run as 32bit processes.
i386
The linux i386 ABI architecture specifier, for models which must run as 32bit processes.