2. ESL Manual¶
Welcome to the Elephant Specification Language manual. This manual will introduce you to the reasoning behind and concepts within the Elephant Specification Language, or ESL for short. For a more in-depth explanation of ESL’s foundations check out the ESL Reference Manual.
System Engineers play a vital role in the development of complex systems. Coordinating the design and production of thousands of components across modules, teams, departments and even companies is an immense challenge! Currently, the design documentation or “specs” of a system are often communicated in the form of PDF, Word, and Excel files. Several solutions exist that try to organize these files and tie them to the components they are supposed to describe.
Although this document organization is helpful, the documents themselves form a huge blind spot as they are often inconsistent, incomplete, and out-of-date. Enter ESL! A highly structured though human-readable specification language that introduces a fixed syntax while allowing the expression of any design requirement or constraint. Since its syntax is fixed, the ESL documents can be checked and analyzed automatically for their consistency and completeness.
Moreover, all relations, dependencies and links of requirements to components and variables are automatically derived from the specification instead of having to be maintained manually. Even for simple projects the number of dependencies quickly exceeds the 100 or even 1,000 mark! The automated dependency derivation reduces the risk of human error drastically, as dependencies cannot be forgotten to be added by definition.
Naturally, not every System Engineer you come across will work with ESL specifications, which is where the generated PDF output comes in. Nicely formatted documents, generated right from your ESL specification, which once more guarantees their consistency!
Furthermore, as ESL documents are written in plain text, they are exceptionally suitable for Version Control Systems such as Git and SVN amongst others.
2.2. Language concepts¶
The different concepts in the ESL language will be explained using an example specification. We are going to specify a water pump, that consists of a centrifugal pump driven by an electromotor, with several requirements to the subcomponents, dimensions, and performance.
Note that we use a certain spacing style when writing ESL for readability purposes, although the compiler itself ignores any indents.
2.2.1. Hello world!¶
We start by specifying the modelling boundary. We do so by specifying the
The absolute minimal ESL specification you can write is therefore:
Thus introducing two new keywords:
world: The modelling boundary, can only occur once in a ESL specification. We assume nothing exists outside of the
empty: When we want to specify something without any further information, we write
emptyto signal this.
Components are at the core of ESL specifications. Typically, your (to be developed)
systems will live as a
component within the
world. Components are introduced
using a definition such that they can be instantiated in the
world. In case of our
water pump, this becomes:
1 2 3 4 5 6 7 8 9 10 11 12
world components pump is a centrifugal-pump drive-mechanism is an electrical-drive-mechanism define component centrifugal-pump empty define component electrical-drive-mechanism empty
Where each component definition is defined using the
define component keyword
combination followed by the component
[name], which cannot have any spaces. Dashes
world definition, we instantiate defined components by given them a
local name and referring to their definition with
[name] is a
We can refer to the defined components before their written definitions.
The ESL compiler is smart that way and resolves later
define component [name]
statements by default.
Note the difference between definition and instantiation. Definitions are similar to classes or templates in other programming languages and instantiations are similar to the actual instances or objects.
2.2.3. Nested components¶
Components can be defined with any number of subcomponents. This allows for a hierarchical layout of your specification. As such, you can start with your top-level components and work your way down as more details become available.
Let’s say that our
electrical-drive-mechanism consists of a
battery to power it and a
switch to turn it on. We then have to add those
component definitions and can add them as subcomponents to the drive mechanism like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
world components pump is a centrifugal-pump drive-mechanism is an electrical-drive-mechanism define component centrifugal-pump empty define component electrical-drive-mechanism components electric-motor is a brushless-motor power-source is a battery power-swith is a swtich define component brushless-motor empty define component battery empty define component swtich empty
2.2.4. Types, variables, and verbs¶
With components and subcomponents, the specification merely lays out the hierarchical component structure, but tells us little about what needs to go on inside the system. We would like to start expressing this using requirements and constraints on various variables in our design space, but we need to define those first! Let us say we want to specify the torque that our drive mechanism has to supply to the pump:
1 2 3 4 5 6 7 8 9 10 11
define type mechanical-energy-flow is a real with unit Nm define verb provide to world variables torque is a mechanical-energy-flow
Where we first define a
mechanical-energy-flow type that will only allow values
with the Newton meter (
Nm) unit, and instantiate a variable on the global
(world) level of that type named
torque. Similar to components, we use a
a [defined type] to describe this. There are several base types built in, being:
Boolean values (true or false)
integer valued numbers (1, 2, 3, etc.)
real valued numbers (1.0, -2.6234, etc.)
literals (“running”, “blue”, etc.)
We also define a verb that we would like to use when we start expressing
requirements. It consists of a verb
provide and a preposition
to. By having
to stick to a defined set of verbs and prepositions, the ambiguity in your
specifications can be kept to an absolute minimum!
2.2.5. Goal requirements¶
Great! With the groundwork set, we can start adding our first requirement! A
goal-requirement defines the goal of a component with respect to another. In case of
our pump, we would like to specify that it is the
drive-mechanism that provides
torque to the
We express this using the sentence:
drive-mechanism must provide torque to pump,
thus following the format
[active component] must [verb] [variable] [preposition]
world definition illustrating this becomes:
1 2 3 4 5 6 7 8 9 10
world variables torque is a mechanical-energy-flow components pump is a centrifugal-pump drive-mechanism is an electrical-drive-mechanism goal-requirements provide-torque: drive-mechanism must provide torque to pump
Note how the goal requirement has a label
need to have a label for easy identification. This label only has to be unique in the
definition of that single component (or the world) and can thus be re-used elsewhere.
2.2.6. Transformation requirements¶
goal-requirements are great to express the purpose of a component with respect
to another, components often transform their inputs to their outputs internally, which
we specify using
For instance, our
brushless-motor is the component that converts
torque. We describe this using the sentence
must convert power into torque.
Lets review its definition:
1 2 3 4 5 6 7 8 9 10 11
define verb provide to convert into define component brushless-motor variables power is an electrical-energy-flow torque is a mechanical-energy-flow transformation-requirements convert-power: must convert power into torque
And so, we defined a new verb and specified the internal transformations using
must [verb] [variable in] [preposition] [variable out].
Note the instantiation of variables within the
component definition. These variables are only available within this definition and
can only be referenced directly by requirements within this definition.
2.2.7. Design requirements¶
To express requirements on the values of variables we use
These are, for instance, useful if you want to specify a component’s size, or set the
key performance indicator.
For instance, we can express a minimum required water flow of the pump:
1 2 3 4 5 6 7 8 9 10 11 12 13
define type liquid-material-flow is a real with unit L/s world variables water-flow is a liquid-material-flow components pump is a centrifugal-pump drive-mechanism is an electrical-drive-mechanism design-requirements min-water-flow: water-flow must be at least 1.0 [L/s]
Note that the minimum water flow is not coupled to any specific component at this point and only is a general statement for now. Tying this requirement to the pump’s water flow is explained in Parameters & properties.
Note that the specified unit
[L/s] must match the unit that is
specified for the variable type.
188.8.131.52. Design rule¶
Design requirements amongst other concepts utilize the design rule syntax.
(In)equalities can be expressed using the syntax
[subject variable] must be
[comparison] [bound variable] or
[subject variable] must be ([comparison] [value]
[[optional unit]] | [objective]). Where the comparison may be one of:
not equal to
and the objective may be one of:
The logic may be extended using
or within a single rule. Adding multiple
‘and’ like statements is done using multiple parallel requirements, which is equivalent
and more readable. Bracketing logic is not supported for the same reason.
The values that quantify design requirements are often subject to discussion
within a design process. There ESL has the built-in special value
indicate that the exact value of a bound within a design-requirement should be
determined at a later point in time. That is, one is allowed to write:
design-requirement dr-1: x must be at most t.b.d. [-]
2.2.8. Behavior requirements¶
You can specify all static behavior using goal, transformation, and design
requirements. That is, the workings of a system that are (desired to be) present at all
times. Specifying dynamic behavior requires an additional construct. Enter
behavior-requirements. Let’s review one:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
define type control-signal is a boolean define component electrical-drive-mechanism variables power-potential is an energy-potential power is an electrical-energy-flow torque is a mechanical-energy-flow motor-control-signal is a control-signal components motor is a brushless-motor power-source is a battery power-switch is a switch goal-requirements provide-power: power-source must provide power to motor behavior-requirements toggle-power: case on: when * c1: motor-control-signal is equal to True [-] then * r1: power must be at least 300 [W] case off: when no other case applies then * r2: power must be equal to 0 [W]
Here, we specified a
goal-requirement that states that
power must be provided to
the motor. Using the
toggle-power, we specify which values
this power should assume under different circumstances or a set of
case clauses. It
requires that it must be at least
300 [W] when the conditions for case
motor-control-signal is true). Furthermore, it includes a fallback case
off using the
when no other case applies sequence, stating it must then be
Note that both the lists following
then are all design rules.
They follow the syntax as in Design rule.
We define requirements as that what is desired for the system. However, some
parts may be already present or are to be treated as given. That what is given can
be expressed using constraints.
design-constraints exist, and are identical to their
counterparts, apart from the change from the
does verb when expressing
constraints instead of requirements.
For instance, let us assume that our
battery power source will always convert the
power regardless of our requirements:
1 2 3 4 5 6 7
define component battery variables power-potential is an energy-potential power is an electrical-energy-flow transformation-constraints convert-potential: does convert power-potential into power
So with minimal changes, we can signal that this transformation is non-negotiable and universally is so.
Sometimes you cannot quantify a requirement and must state something qualitatively. For
example, you may want to refer to an externally defined standard. This can be specified
need, which should be used with caution. Needs serve a documentation
purpose, but are mostly ignored by the compiler as far as any checks can go.
Let’s say our
drive-mechanism needs to be waterproof up to IP68
1 2 3 4 5
variables pump is a centrifugal-pump goal-requirements IP68: drive-mechanism must be IP68 compliant
There are no further constraints on need lines than that it needs to start with a
variable or a component-name as in
[variable | component-name] [free text],
which is why they are some form of ‘escape’ in the specifications. Use this wisely!
When client specifications are too vague (yet) to be implemented in a quantitative manner, it may be wise to document them using a need for the time being. These can serve as action points to reduce the neediness of the specification and support the transition from qualitative to quantitative requirements later on.
2.2.11. Parameters & properties¶
Goals, transforms and needs give us the expressiveness to build a complete
specification. However, sometimes, variables need to be available outside a
component’s own definition. For instance, when we imposed the
requirement, we could not yet link it to the water-flow inside the
Just as well, we would like both the
drive-mechanism to work with the
torque variable, instead of each having their own unique variables. That way we
can check whether the requirements that all components impose on a variable are
carefully captured and coordinated.
To indicate the owner of a certain design variable, you can add the
keyword to the parameter declaration.
For instance, let us review the updated interplay between the
drive-mechanism with the parameters and properties:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
# Specification of a drive-mechanism driving a pump. define type electrical-energy-flow is a real with unit W spatial-measure is a distance of at least 0.0 [m] send to world variables water-flow is a liquid-material-flow pump-length is a spatial-measure components pump is a centrifugal-pump with arguments * torque * water-flow * pump-length drive-mechanism is an electrical-drive-mechanism with arguments * torque * drive-length define component centrifugal-pump parameters torque is a mechanical-energy-flow water-flow is a liquid-material-flow length is a spatial-measure property define component electrical-drive-mechanism parameters torque is a mechanical-energy-flow length is a spatial-measure property
Here, the both the
drive-length variables are passed on from the
world level to the
electrical-drive-mechanism component definition using the
arguments followed by an ordered list of arguments using a bullet point syntax (
[argument]). The ordering has to match the parameter declaration of the component
definition. This way, we can make statements regarding the same variable instance both
on the top (world) and component level.
We also declare that the
length is actually a
property of that component definition. Therefore, as soon as we pass the
drive-length as an argument, it will be owned by that component. A variable
instance can only be owned by one component at most.
with arguments syntax also works when declaring sub-components.
Note that we do have to specify the
spatial type both at the world level
and in the component definition. The type checker will alert you if any type
mismatches are found (or in case you forgot to add them).
Note that by definition flows cannot be properties of components as
they flow through the system. As such, no single component owns a flow. Flows are
variables that are involved in
constraints. An example of such a flow variable is
Variables are powerful in themselves, but they can be interdependent, too. They may be coupled via mathematical equations, models, laws of physics, or any other means of interdependency. We signal this by defining relations between them. Relations can have names and arguments. The explicit math or implementation is not covered in ESL. This is intentional, as the language is not designed to replace all kinds of complex computation environments and languages. Instead, we provide means to accurately capture the dependencies.
Lets say we want to describe the battery’s efficiency as a relation between power potential (chemical) and the output power (electrical):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
define relation battery-efficiency-model relating parameters * potential is an energy-potential * output is an electrical-energy-flow define component battery parameters power-potential is an energy-potential power is an electrical-energy-flow relations efficiency-model: battery-efficiency-model relating arguments * power-potential * power
Here we define an undirected relation using the syntax
[name] relating parameters
followed by an ordered parameter list using
* [name] is a [type]. This relation is
then instantiated in the
relations section of the battery, which means you can use a
relation definition multiple times.
For directed relations (a specific input-output mapping), see ESL0002 - Relation syntax modification.
The requirements are meant to be clear and concise, but can often do with a little hardening or additional measures. That is where subclauses come in. Essentially subclauses are design rules (similar to design-requirements), but attached to another goal-, transformation- or design-requirement.
Say we want to state that the brushless motor has a conversion efficiency of at least 80%. You can add that like so:
1 2 3 4 5 6 7 8 9 10 11
define component brushless-motor parameters power is an electrical-energy-flow torque is a mechanical-energy-flow variables conversion is an efficiency transformation-requirements convert-power: must convert power into torque with subclauses * s1: conversion must be at least 0.8
Thus by simply adding
with subclauses at the end of a requirement line, we can
enumerate design rules. Design rules follow
the Design rule syntax.
2.2.15. Nuancing requirements and constraints¶
Up until now, every requirement and subclause has been defined using
must as the
requirement specifier. One can add nuance by varying between any of the following
2.3. Water pump specification¶
Finally, we can combine all the outlined concepts into a single specification:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
# Specification of a drive-mechanism driving a pump. define type mechanical-energy-flow is a real with unit Nm electrical-energy-flow is a real with unit W liquid-material-flow is a real with unit L/s energy-potential is a real with unit Wh control-signal is a boolean distance is a real with unit m spatial-measure is a distance of at least 0.0 [m] efficiency is a real of at least 0.0 and at most 1.0 define verb provide to convert into send to define relation battery-efficiency-model relating parameters * potential is an energy-potential * output is an electrical-energy-flow world variables torque is a mechanical-energy-flow #< Comments on variable torque. water-flow is a liquid-material-flow drive-length is a spatial-measure pump-length is a spatial-measure components pump is a centrifugal-pump with arguments * torque * water-flow * pump-length drive-mechanism is an electrical-drive-mechanism with arguments * torque * drive-length comments pump #< Can be sourced by manufacturer XYZ. #< Part number CFG.PMP.0.1 goal-requirements provide-torque: drive-mechanism must provide torque to pump design-requirements min-water-flow: water-flow must be at least 1.0 [L/s] design-constraints dc-drive-length: drive-length must be equal to pump-length need IP68: drive-mechanism must be IP68 compliant define component centrifugal-pump parameters torque is a mechanical-energy-flow water-flow is a liquid-material-flow length is a spatial-measure property transformation-requirements convert-torque: must convert torque into water-flow define component electrical-drive-mechanism parameters torque is a mechanical-energy-flow length is a spatial-measure property variables power-potential is an energy-potential power is an electrical-energy-flow motor-control-signal is a control-signal transformation-requirements convert-power-potential: must convert power-potential into torque components power-source is a battery with arguments * power-potential * power motor is a brushless-motor with arguments * power * torque power-switch is a switch with arguments * motor-control-signal goal-requirements provide-power: power-source must provide power to motor send-control-signal: power-switch must send motor-control-signal to power-source behavior-requirements toggle-power: case on: when * c1: motor-control-signal is equal to True [-] then * r1: power must be at least 300 [W] case off: when no other case applies then * r2: power must be equal to 0 [W] define component brushless-motor parameters power is an electrical-energy-flow torque is a mechanical-energy-flow variables conversion is an efficiency transformation-requirements convert-power: must convert power into torque with subclauses * s1: conversion must be at least 0.8 define component battery parameters power-potential is an energy-potential power is an electrical-energy-flow transformation-constraints convert-potential: does convert power-potential into power relations efficiency-model: battery-efficiency-model relating arguments * power-potential * power define component switch parameters motor-control-signal is a control-signal
2.4. Generated dependency graphs¶
One of the major benefits of using ESL is that dependencies between components, variables, function, behavior, design, and relation specifications can automatically be derived. This information is stored within a graph which is the output of the ESL compiler. The resulting graph is the basis for many system architecture models.
Check the Dependency derivations section of the ESL reference manual for the formal dependency derivation rules.
Many conventional requirement management and system architecting tools require a user to manually identify, create, define, and maintain dependencies between elements of a system specification or system architecture model. With the use of ESL one this is fully automated!
Figure 2.1 shows all dependencies that are derived from the final pump specification at the second decomposition. The rows are labelled with components, function-specifications, behavior-specifications, design-specifications, variables, needs, and relations specifications.
The tree structure at the top left of the figure denotes the system decomposition structure as specified. Here we find the components pump, power-source, motor, and power-switch to be the leaf components of the specified decomposition tree.
The pie-charts within the matrix denote the derived dependencies between elements of the specification. The colors of the wedges denote the different labels that are attached to each dependency. The labels are based on the variable types that are used within the specification.
In total the MDM shows 105 different dependencies between 26 elements. Imagine how much time it would take and how error prone it is to identify, define and maintain these dependencies by hand!
Note that the compiler derives multiple dependency kinds, being functional, logical, design, coordination, traceability and mapping dependencies. Figure 2.1 shows all these dependency kinds between all ESL elements which makes it difficult to interpret (Especially if one would specify a real system). Hence in the next sections we will create several views on the system.
In the user manual we use multi-domain-matrices to visualize the resulting dependency structures.
2.4.1. Functional dependencies¶
In engineering design one often uses functional dependency models of a system. Figure 2.2 and Figure 2.3 show the functional and mapping dependencies between components, function specs, and variables at decomposition levels 1 and 2, respectively.
Figure 2.2 contains components pump and drive-mechanism (rows 1-2) which have a mechanical-energy dependency (green). This dependency is derived from goal-function specification provide-torque. This can be seen within the component-function spec mapping matrix (rows 3-6, cols 1-2). That is, in row 6 one can see that both components relate to the function specification provide-torque which states that drive-mechanism must provide torque (mechanical-energy) to pump. The mapping matrix shows which transformation functions are fulfilled by which components as well.
The function specification dependency structure matrix (rows 3-5, cols 3-5) shows the functional dependencies between function specifications. Within this matrix one can identify the function chain convert-power-potential \(\rightarrow\) provide-torque \(\rightarrow\) convert-torque. That is, first power-potential needs to be convert into torque before it can be provided and converted into a water-flow.
In rows 5-10 and columns 1-5 one can find the mapping dependencies between components and variables, between function specifications and variables. The variable DSM (rows 5-10, cols 5-10) shows the functional dependencies between variables. That is, the variable water-flow depends on the variable torque.
In Figure 2.3 component drive-mechanism has been decomposed into its subcomponents power-source, motor, and power-switch. As a consequence, transformation-function convert-power-potential, which is to be fulfilled by drive-mechanism, has been replaced by its sub-ordinate functions convert-potential, provide-power, and convert-power. These functions have to be fulfilled by power-source and motor.
The goal-function specification provide-torque (row 10) is still part of the matrix but is now allocated to motor. Goal-function specifications automatically migrate through the decomposition tree. Contrary to transformation-function specifications that are replaced by sub-ordinate functions.
The function DSM (rows 5-10, cols 5-10) now shows a longer function chain: convert-potential \(\rightarrow\) provide-power \(\rightarrow\) convert-power \(\rightarrow\) provide-torque \(\rightarrow\) convert-torque. Within the variable DSM (rows 11-16, cols 11-16) this increase in the length of the function can be seen as well in the form of a longer dependency path between variables. That is, one can identify a dependency path starting at power-potential \(\rightarrow\) power \(\rightarrow\) torque \(\rightarrow\) water-flow.
In systems engineering literature one often encounters function traceability trees. That is, one aims to visualize how top-level functions are fulfilled by low-level functions. The ESL compiler derives such traceability dependencies as well.
In Figure 2.2 and Figure 2.3 we could see that function specifications convert-potential, provide-power, and convert-power are sub-ordinate to transformation specification convert-power-potential. In Figure 2.4 this is made explicit by visualizing traceability dependencies between function specifications.
2.4.2. Logical dependencies¶
The functional dependencies visualized in the previous sections related to the (physical) exchange and transformations of flows between components of the system.
From a (supervisory) control perspective however one is more interested in the dependencies that relate to the behavior of components. For example, the relation between the output of a sensor and the output of an actuators. Such dependencies are often embedded within the (control) software of a system. The ESL compiler can derive such dependencies from ESL behavior specifications.
Figure 2.5 shows an MDM listing the components, function specifications, and behavior specifications relevant at the second decomposition level of the final specification. Within the matrix logical dependencies and mapping dependencies are shown. For example, power-source has a logical dependency with power-switch. This dependency is derived from behavior-requirement toggle-power that logically relates the value of motor-control-signal, send by power-switch, to the value of power, produced by power-source
Similarly, function specifications send-control-signal and convert-potential have a logical dependency. Since the output of convert-potential is defined by the value of motor-control-signal. Note that in Figure 2.3 the functions specifications send-control-signal and convert-potential do not have a functional dependency as motor-control-signal is not (physically) converted into power.
The bottom row of Figure 2.5 shows which components and function specifications are affected by behavior specification toggle-power.
2.4.3. Design dependencies¶
Besides functional and behavior dependencies as discussed in the previous sections, engineers have to account for design dependencies. For example, a geometrical dependency between two components that have to fit within a predefined space.
The ESL compiler drives design dependencies from design and relations specifications. Figure 2.6 shows for example an MDM containing components, variables, design specifications, a relation, and a need.
The component DSM (rows 1-2, cols 1-2) shows a design dependency between pump and drive-mechanism. This dependency is derived from design specification dc-drive-length that states that drive-length and pump-length must be equal.
Design specification dc-drive-length yields a design dependency between the variables drive-length and pump-length as well. This dependency is shown within the variable DSM (rows 3-8, cols 3-8).
Within the variable DSM one can see an additional dependency between power-potential and power. This dependency is derived from relation specification efficiency-model (row 11).
2.5. Generated documents¶
As mentioned before, not every system engineer you come across will work with ESL. Moreover, establishing a culture change within a company from document-driven-engineering to model-drive-engineering is not a small feat. Therefore, ESL specifications can be converted into seemingly natural language PDF documents.
For example, check out the
generated PDF document of the example pump specification. You can add epilogue
and prologue chapters written in Markdown to provide additional context with the
specification. In this case, an Introduction chapter and a Conclusion chapter is added.
All other chapters are generated based on the ESL specification. At the start of each of these chapters one can find a component-function-spec multi-domain matrix that shows the dependencies between the components and function-specifications discussed within that chapter. This figures are by definition consistent with the written text. This eliminates inconsistencies between text and dependency figures as often encountered within manually written documents.