Deprecated since 0.14

This article is deprecated. The described features are no longer available in current releases.

Simulation of Models in KIELER


Overview

After a model has been created, it is reasonable to test if the model does what is expected. This can be achieved by simulating the model. The simulation must

  • Receive inputs for the next tick
  • Execute a tick
  • Send generated outputs

Thus the simulation can be seen as a black box, which receives a state for the model, somehow computes a reaction, and communicates its new state to the outside. In KIELER the communication for receiving and sending the state of the model is done using JSON. When starting the executable file of a simulation in KIELER, the JSON communication is done on stdin and stdout of the running process.

Within KIELER a single state of a simulation is represented as a Data Pool. A data pool can have multiple models. Each model can have multiple variables. Thus a representation of a complete run of a simulation can be implemented as list of data pools.

Executables for simulation are created using the incremental project builder that is part of the project management. The typical steps to create an executable for simulation are:

  • Compiling a model using the KIELER compiler
  • Generating the simulation wrapper code for the model using template processing
  • Compiling the resulting code using, e.g., gcc.

For more insight of the simulation generation, please take a look at the Project Management.


Using the Simulation

Besides the explicit configuration of a simulation using a kisim file, it is possible to start simulations directly on models, executables or trace files. This will start a pre-defined configuration depending on the selected files. The following table shows which files can be used to start a simulation and what simulation configuration is created for it.

Selection

Example Selection

Macro Tick Configuration of Simulation

1 executable

Sim_ModelA.exe

Performs a single tick and updates the pool with the received data from the process

2 executables

Sim_ModelA.exe, Sim_ModelB.exe

Starts two executable data handlers with bidirectional redirection of inputs/outputs between the models. So the performed steps are:

Execute tick of A, redirect A→B, execute tick of B, redirect B → A

1 kisim file

ComplexSimulation.kisim

Uses the explicit configuration from the file

1 executable, 1 trace file

Sim_ModelA.exe, TraceOfModelA.eso

The trace will first set inputs for the model that are read from the trace file. Then the tick is performed. Afterwards the generated outputs are compared to the outputs of the trace file and events are fired in case of a mismatch.

1 simin file

process_output.simin

The simin file must contain a JSON object for some model. The data pool of the simulation is then updated with its contents.

1 simout file

simulation_output.simout

A model of the simulation is written as JSON object to the simout file.

Playing the Simulation

One can step through the simulation tick after tick. Furthermore it is possible to let the simulation step automatically. This is the play mode, in which a macro tick is performed after a given time, which can be defined in the data pool view (e.g. to perform a tick every 200ms).

Stepping Back in the Simulation

When clicking the Step Back button, the values of a former tick are set in the data pool view as user values, which will be assigned to the model before the next tick is executed. Thus it is possible to revert the simulation to a previous state if all variables that define this state are recorded in the data pool.

When stepping back and forth in the simulation history, the position in the history is shown next to the current tick count in the Data Pool View. For example, when the simulation is after tick 5 and one steps two ticks back in the simulation history, this will be indicated as the tick #5 (-2). If a tick is performed now using the old state, the values of tick 5 - 2 = 3 are applied and the new outputs are computed so that the simulation is now after tick #4.

The Data Pool View

The current data pool can be seen in the Data Pool View (Window > Show View > Other > KIELER Simulation > Data Pool View).

In the view, the variable values can be modified by the user via clicking the column User Value. If a user value is specified for a variable, the corresponding row is highlighted and marked with an asterisk ( * ) . The value is applied to the variable and send to the model before the next tick is performed.

When using traces in the simulation, a trace mismatch of a variable will be highlighted in the data pool view. A tooltip on the Current Value column shows details about the mismatch. The trace mismatch is kept between ticks. To clear a mismatch, use the menu of the view and select Clear Trace Mismatches from the view's menu.

When the data pool view is selected, stepping through the simulation can be done using the RIGHT arrow on the keyboard, which is often more useful than clicking the corresponding button in the toolbar. Furthermore the SPACE key will play/pause the simulation and with CTRL+LEFT (respectively CTRL+RIGHT) one can step back (step forward) in the simulation history.


Data Handlers

A simulation consists of a list of data handlers. These perform actions on the data pool. When the actions of all data handlers for a simulation have been executed, then this is a single full macro tick. In contrast performing only a single action on one data handler is called a sub tick and typically not necessary when using the simulation. However stepping through the data handler actions one by one can be useful to see the effect of each action on the data pool.

Which handlers are available are explained in the following.

Executable

There is a data handler for the simulation of executables. This data handler will send the inputs of the corresponding model in the simulation as JSON object to stdin of the process. Afterwards the tick is computed by the process. Finally the data pool in the current simulation is updated with the JSON object received from stdout of the running process.

Normal executables and executable jar files can be used simply by providing the path to the file. For other file types, e.g., a python script, the shell command to start the process has to be specified explicitly.

Attribute

Domain

Example

Description

executable

String, absolute workspace path or project relative path

/MyProject/kieler-gen/sim/bin/Sim_MyModel.exe

The path to the executable

command

String, the shell command that is used to start the process

python -i "${executable_path}"

The shell command to start the executable

Redirect

Multiple models may interact with each other as some can have inputs that are generated as outputs of other models. To implement this behaviour in the simulation, the redirect data handler has been created. It sets the inputs of a model to the outputs of some other model in the data pool. Thus the outputs of a some model A can be used as inputs of some model B.

Per default inputs and outputs are matched by name. However it is also possible to provide an explicit mapping of which output should be mapped to which input variable.

Attribute

Domain

Example

Description

from

String, name of a model in the simulation

Sim_ModelA.exe
MyModelA

The name of the model of which the outputs are read

to

String, name of a model in the simulation

Sim_ModelB.exe
MyModelB

The name of the model of which the inputs are set

mapping

Map, The key is an output variable and the value is an input variable

configure redirect A_to_B {
  from: A
  to: B
  mapping {
    someOutputOfA: someInputOfB
    other OutputOfA: otherInputOfB
  }
}

Defines which output variables should be mapped to which input variables

Trace

A trace data handler can read a trace file. The inputs of a model can be set to corresponding inputs from the trace and outputs of a model can be compared with corresponding outputs in the trace. Therefore the trace data handler has the methods write (inputs), check (outputs), loadNextTick (to go to the next tick in the trace).
If the outputs of the trace do not match the outputs of the current simulation, an event is fired and the data pool view will display a trace mismatch.

Thus the typical simulation setup to use a trace data handler for a model A is:

  • Set the input of the model to the inputs from the trace (write)
  • Perform the tick of the model A
  • Compare the outputs of the trace and the model A (check)
  • Go to the next tick in the trace (loadNextTick)

Attribute

Domain

Example

Description

file

String, absolute workspace path or project relative path

MyTrace.eso

The trace file to be used

modelName

String, name of a model in the simulation

Sim_ModelA.exe

MyModelA

The model in the simulation for which the trace is for

traceNumber

Integer

0

In case there are multiple traces in the eso file, determines which trace should be used.
Default is 0

tickNumber

Integer

0

The tick of which the input is set. This can be used to skip some ticks of the trace.
Default is 0

checkInterface

Boolean

true

Determines if the interface of the trace and model should be compared.
If this is true and for example there is an additional input or output in the model that is not recored in the trace, a TraceMismatchEvent is fired.
If this is false and for example the trace contains a variable that does not exist in the model, this issue is ignored.

Simulation Input Files

The simulation can communicate with executables via stdin and stdout. To use this, the executable has to be started from within KIELER.

To get information about a model that is running outside of KIELER, simulation input files can be used. A simin file contains a single JSON object with the state of a model that can be used to feed the simulation with data. Thus any program that can write a JSON object to a file can interact with the simulation.

In combination with redirects, a simin file can be used to set the inputs of a model with data that is produced from another application.

Simulation input files can also be used to feed the simulation with data to be visualized via the simulation visualization.

Attribute

Domain

Example

Description

file

String, absolute file system path or
absolute workspace path or project relative path

/home/myuser/process_output.simin

The target file

modelName

String, name of a model

MyModel

Name of the model in the simulation that the data in the simin file is for.

Simulation Outputs Files

This data handler writes the output of the model in the simulation to the specified file.

Attribute

Domain

Example

Description

file

String, absolute file system path or
absolute workspace path or project relative path

myFolder/myFile.simout

The target file

modelName

String, name of a model

MyModel

Name of the model in the simulation that will be written as JSON object to the simout file

Variable Setter

This data handler is only used for easier debugging and setting up simulations for different test runs. It sets the variables in the data pool to constant values, typically once for the simulation in the initialization part of a kisim file.

Attribute

Domain

Example

Description

variables

Map, The key is the variable name, the value is the value for this variable

configure setter S {
  variables {
    I: true
    O: 5
    MyModel.MyVar: -1
  }
}

Sets the variables in to the given values.

This way different setters can be defined for different simulation runs or manual testing.


KiSim

Which data handlers are used and which actions are performed on them for each macro tick can be configured using a DSL, namely KiSim.

A kisim file contains two main parts:

  • Configuration of data handlers
  • Actions to be performed on the data handlers for each a macro tick

Besides these, an optional initialization part can be used to perform actions on data handlers once at startup.

Examples

The following shows examples of kisim files.

Configuration to simulate a single executable:

Single Executable
configure sim Test {
  executable: kielger-gen/sim/bin/Sim_Test
}

execution {
 write sim Test
}

Configuration for two executables with redirection between both:

configure sim A {
  executable: kielger-gen/sim/bin/Sim_Test
}
configure sim B {
  executable: kielger-gen/sim/bin/Sim_Test2
}

configure redirect A_to_B{
 from: A
 to: B
}

configure redirect B_to_A{
 from: B
 to: A
}

execution {
 write sim A
 write redirect A_to_B
 write sim B
 write redirect B_to_A
}

Using a trace for a model:

configure sim A {
  executable: kielger-gen/sim/bin/Sim_Test
}

configure trace A {
  file: MyTrace.eso
  modelName: A
}

execution {
 write trace A // Set inputs of model to values from trace
 write sim A   // Perform tick of model
 read trace A  // Compare outputs of model with values from trace
}

Feeding inputs of a model from a simin file:

configure sim A {
  executable: kielger-gen/sim/bin/Sim_Test
}

configure simin SimInput {
  file: process_output.simin
}

configure redirect SimInput_to_A{
 from: SimInput
 to: A
}

execution {
 write simin SimIn
 write redirect SimInput_to_A
 write sim A
}

Sets the variables for manual testing:

configure sim A {
  executable: kieler-gen/sim/bin/Sim_Test.exe
}

configure setter S {
  variables {
    x: 100
    y: 100
 }
}

initialization {
 write setter S
}

execution {
 write sim A
}

Implementation Details

The following are details about the implementation of the simulation and the JSON format that is used to communicate the variables in the models.

As said above the simulation is seen as black box which takes inputs on stdin, computes a reaction, and sends outputs stdout. Thus an executable simulation is a normal program that communicates in a specific JSON format and can also be used from command line.
 

The JSON Format

The JSON format is designed to communicate the state of a simulation. In KIELER such a state is saved as a single data pool. This means the JSON format for the communication with running simulations is also the JSON format for data pools.

It mainly consists of a list of models and a map of models. The models consist mainly of a map of their variables. The most important field of a variable is their value.

{ "MODEL_NAME0" : {
   "VAR0":{"value": "VAR0_VALUE"}, "VAR1":{"value":"VAR1_VALUE"}, ...
 }
 "MODEL_NAME1" : {
   "VAR0":{"value": "VAR0_VALUE"}, "VAR1":{"value":"VAR1_VALUE"}, ...
 }
  ...
 "actionIndex" : "ACTION_INDEX_AFTER_WHICH_THE_DATA_POOL_WAS_CREATED"
}

Besides these core informations, an additional field "actionIndex" can be set for the data pool. In the simulation the actions of data handlers are executed to create a macro tick. Therefore the action index takes the task of a program counter. It determines the next action to be executed. Thus in the JSON format the field "actionIndex" can be set to store when the data pool was created in the simulation.

There are also additional fields for variables than their value. However these only need to be communicated once after the initialization of the model and are explained in the table below.

Field Name

Example Values

Description

type

int

bool

pure

float

double

string

The type of the variable in the source model.

Because this information is lost in general in the compilation (for instance a bool is compiled to a char in C code), the simulation can communicate the intended variable type in the source model.

interface

0

1

2

3

4

5

6

Bitmask, that determines how the variable is used in the source model's interface (e.g. input, output, internal, other).
A bitmask has been choosen because a mixture of a variables interface types is possible (e.g. input, output, input output)

Interface Type

Binary Bitmask

Decimal Number

Other

0000

0

Internal

0001

1

Output

0010

2

Input

0100

4

Input Output

0110

6

Note that internal is intended for variables that are neither input nor output but still part of the source model, in contrast to variables that are created in the compilation (e.g. register flags).
Anyway an input and output is also a internal variable normally.

Python Example

The following shows a tiny python script, that will write a Data Pool containing an output variable x to stdout.

prog.py
import sys

x = 0
while True:
    json = """{"x":{"value":""" + str(x) + ""","interface":2}}"""
   print(json)   # Send output to simulation
   raw_input("") # Wait for input from simulation
    x = x + 1

This script can be executed from within KIELER to start a simulation because it uses the JSON communication on stdin and stdout. Note however that the input coming from the simulation is not handled in the script. An example kisim configuration to start such a scipt is given below.

RunProg.kisim
configure sim A {
  executable: prog.py
  command: "python -i ${executable_path}"
}

execution {
  write sim A
}
Tags: