L = list of all non sequenced nodes of the program
while (L not empty){
oneSequenced = false
4 foreach n in L {
if (all the inputs of node n have been computed) { sequence n remove n from L oneSequenced = true 9 } } if (not oneSequenced){ signal a DEADLOCK ERROR }
14 }
Listing 4.3: Example of sequencing algorithm for dataflow models
the execution cycle enters the final execution phase where nodes containing memories see their memories values updated. Memories update is done without a specific order.
If a value of a block cannot be calculated for a clock tick, its value is set to⊥ (bottom) if its previous value was never set otherwise it stays at the same value.
Dataflow model sequencing
As data produced by a node execution are to be consumed immediately, it is thus mandatory to find the order in which the nodes must be executed prior to the execution of the network. This is referred to as the sequencing of the dataflow model. If sequencing of the dataflow model is not possible – for example if a model is not well founded (Section 4.3) – then the dataflow model will be considered as being incorrect. There are multiple algorithms for the computation of this sequencing among which is the one presented in [98]. These are topological ordering algorithms. Sequencing a dataflow model is the process of finding an execution order for all its nodes. An example algorithm is provided in Listing 4.3 that is based on the worklist algorithm: a generic conceptual algorithm used for the application of an activity (the execution order assignment) on a set of elements until it has been successfully applied to all elements or the algorithm detects an impossibility to go on further with the activity application.
Izerrouken [77] provides a formal definition and implementation for such a variant of the worklist algo- rithm for the sequencing of the Simulink variant of dataflow models. The algorithm proof is done using the Coq theorem prover in the context of the GeneAuto project.
4.2 Dataflow model structure
Dataflow models are sets of equations that describe elementary computations. Each equation reads and writes sets of variables. A block of the dataflow model is an equation. It is therefore possible to extract data dependencies between equations. An equation can be computed as soon as the data that it depends on becomes available – i.e. as soon as they have been computed in other equations. The order of the equation writing is not important as their execution order is resolved statically. As an example, we provide a Lustre [71] program in Listing 4.4. This program is composed of one node: Average taking as input two integers X and Y (line 1). The computation result is an integer: A (line 2). A variable: S is declared as a local variable of the node (line 3), it can only be used inside this node. Finally, two equations are expressed providing the required activities for the computation of the average value of the two provided inputs (lines 5 and 6). In a Lustre program, a variable contains potentially infinite dataflows (data streams) that must satisfy the equations. This is denoting a fix-point semantics.
4.2. DATAFLOW MODEL STRUCTURE
1 node Average(X, Y : int) 2 returns (A : int); 3 var S : int; 4 let 5 S = X + Y; 6 A = S / 2; 7 tel
Listing 4.4: A simple Lustre program
4.2.1 Graphical dataflow model structure High level structure
A metamodel for dataflow models, derived from GeneAuto, is provided in Figure 4.5. In graphical dataflow models, we refer to blocks (metaclass Block) having inputs (metaclass InputPort) and outputs (meta- class OutputPort) ports, parameters (metaclass Parameter) and memories (metaclass Memory). Dataflow between blocks are modeled using signals (metaclass Signal) that links one output port to one input port.
Each element of a dataflow model is named – through the inheritance to the metaclass NamedElement – as it should be possible to refer to them. Blocks names should be unique within a SystemBlock.
Block element structure
When it is activated, each block performs an operation on its input ports according to its parameters, mem- ories and special input ports trigger and enable. Memories grant a block with the ability to store one or more values that will be used during its following activations.
Blocks are categorized according to their capabilities, this is referred to as its category. Categories are: COMBINATORIAL if the block outputs only depend on the current values of its inputs and current values of its parameters; SEQUENTIAL if its outputs also depend on its input values from the past stored in its memo- ries and thus the computation of the block inputs is independent of the current block inputs; SOURCE if the block has no input and thus reads data from outside of the system or from shared memories; or SINK if the block has no output and thus stores or sends data outside of the model or in shared memories. Block are ei- ther atomic (opaque) – computing a simple operation; or hierarchical – a composition of other blocks and signals (metaclass SystemBlock). Hierarchical blocks interest are used first to structure a model accord- ing to system engineering principles (virtual sub-systems), and second to tag a group of blocks and signals as being executed atomically with respect to the other sub-systems (non-virtual/atomic sub-systems). Blocks ports
Port elements have an attribute named kind. It allows to characterise the port and define its use in the block specification. We emphasis four different kinds for a port: DATA ports carrying data. These are the most classical ports that receive the data from a signal and provides it to the block to compute its results and memories (for input ports) and receive the data computed by the block and transmit it to the signal (for an output port). ENABLE and EDGE_ENABLE ports are ports which according to the value they carry will activate or not the block and thus make it compute and update its output values and memories. In the ENABLE case, the block will be activated if the port value is interpreted as a boolean having a True value. In the EDGE_ENABLE case, the block activation will be conducted if a rising or a falling edge is detected on the input. This implies to compare the actual value of the input with its previous value. This port can be replaced by an enable port and a sub-system that detects edges. Only one of the ENABLE and EDGE_ENABLE input ports are allowed in one block instance. Finally EVENT ports carry events allowing to explicitly sequence the blocks when the event is produced instead of following the computed sequencing. These events are provided internally by the model or by other models. For example in a Simulink model,
4.2. DATAFLOW MODEL STRUCTURE
Figure 4.5: Metamodel for dataflow models
events might be sent by Stateflow models or by specific blocks like control flow logic blocks (if-else, for, switch, while, enable, …) and can be used to provide different orders for blocks throughout the execution. The dual use of EVENT ports might be to drive a Stateflow model execution from a Simulink block execution.
Dataflow model values
Block parameters, memories and ports are carrying values, a value needs to have a data type. This is done through the inheritance of the metaclass TypedElement. Every TypedElement instance owns a DataType value and a string value attribute containing the literal value for the TypedElement that should be parsed according to the TypedElement data type. A possible hierarchy of data types derived from Simulink is provided in Figure 4.6.
This type system has been derived from the GeneAuto project results. It provides classical numeric types specification TRealInteger, TComplexInteger, TRealDouble. Standard programming lan- guages data types such as TString, TBoolean, TPointer, TEnum are also provided. Finally, structured types like TArray are present.
The TArray data type has an attribute named dimensions, this vector of positive or null integers val- ues contains the number and the size of the dimensions of the TArray (the number is the size of the vector). A TArray conforming element with a dimensions attribute equal to [4,5] will model a ma- trix value with 4 rows and 5 columns. It is allowed to set the size of a dimension to zero, in this case the dimension is set to be unbounded.
Some dataflow languages like Simulink allow to apply operations on values with different dimensions and datatypes. This is allowed only if the values are compatible which means that there is an allowed con- version between the values. Allowed dimension conversions are those transforming a scalar value into a vector or a matrix having all their values set to the value of the scalar. Allowed datatypes conversion are those transforming a value to a datatype whose definition includes the original value datatype definition
4.2. DATAFLOW MODEL STRUCTURE
Figure 4.6: GeneAuto DataTypes metamodel
domain. The dimension conversion is often referred to as the expansion mechanism in Simulink and will be referred as such in this PhD.
4.2.2 Dataflow languages
Among successful textual dataflow languages we can cite Lustre [71], Lucid-Synchrone [36], Signal [22] or Prelude [122]. These languages are mostly used for the development of real-time embedded con- trol systems. They have been developed by research teams and formally specified. Their initial end users were in the academic world but their qualities made them very useful as semantics backend for the model based development of concrete industrial systems. Some of these languages have been given a graphical syntax and interface in order to simplify their adoption by industrial users. We can cite the Scade¹ tool and language which is based on Lustre and Polychrony/SME² or RT-Builder/Sildex based on Signal. Both of these graphical front-ends have been widely used in critical embedded system development.
Simulink³ is another commercial tool largely adopted in the industry and Scicos/Xcos⁴ is a simi- lar open source alternative in the Scilab⁵ community. These graphical languages have been developed for control and command engineers and their formal definition does not rely on the same dataflow syn- chronous language background. They have been widely used for control systems development in the last years. To our knowledge, the first one is the de-facto standard for such developments.
As an example, we provide in Figure 4.7 a Simulink model for a modulo-three counter. It is composed of one Input block – reset; one Output block – active; five LogicalOperator blocks – LO and two Unit Delay blocks – UD. Two variants of the same block are used: the AND LogicalOperator block variant (i.e. LO1) and its NOT variant (i.e. LO). Every signal value in this model has a boolean value evaluated at this precise execution time. The LO block is a logical not block. The UD block outputs the value of their input at the previous clock tick. This block can only output an undefined value at the first clock tick, this is handled
¹http://www.esterel-technologies.com/products/scade-suite/
²http://www.irisa.fr/espresso/Polychrony/
³http://fr.mathworks.com/products/simulink
⁴http://www.scicos.org/