Elephant Specification Language Manual

Welcome to the Elephant Specification Language manual. This manual will introduce you to the reason 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 Elephant Specification Language Reference.

Introduction

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!

Learning ESL

This tutorial touches the basic concepts of ESL and how to use them. 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. ESL will provide a fixed syntax to describe the requirements, constraints and needs of your system. Even though the syntax is fixed, the specification documents themselves are designed to be human readable.

Note

Note that we use a certain spacing style when writing ESL for readability purposes, although the compiler itself ignores any indents.

Hello world!

We start by specifying the modeling boundary. We do so by specifying the world. The absolute minimal ESL specification you can write is therefore:

world
  empty

Thus introducing two new keywords:

  • world: The modeling boundary, can only occur once in a ESL specification. We assume nothing exists outside of the world.

  • empty: When we want to specify something without any further information, we write empty to signal this.

Components

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:

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 are fine.

Within the world definition, we instantiate defined components by given them a local name and referring to their definition with [name] is a [defined component].

Note

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

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.

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 both a brushless electromotor as well as a battery to power it. We then have to add those component definitions and can add them as subcomponents to the drive mechanism like so:

define component electrical-drive-mechanism
  components
    electric-motor is a brushless-motor
    power-source is a battery

define component brushless-motor
  empty

define component battery
  empty

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, but we still miss a key element before we can do this: variables. They can be defined like so:

define type
  mechanical-energy-flow is a real

define verb
  provide to

world
  variables
    torque is a mechanical-energy-flow

Where we first define a mechanical-energy-flow type, and instantiate a variable on the global (world) level of that type named torque. Similar to components, we use a [name] is a [defined type] to describe this. There are several base types built in, being bool (Booleans), real (real valued numbers), integer``(integer valued numbers) and ``string (for literals).

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!

Note

Note how we define mechanical-energy-flow as a real, indicating that we would like to quantify this measure.

Goal requirements

Great! With the groundwork set, we can start adding actual requirements! The 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 pump.

We express this using the sentence: drive-mechanism must provide torque to pump, thus following the format [active component] must [verb] [variable] [preposition] [passive component].

So a world definition illustrating this becomes:

world
  variables
    torque is a mechanical-energy-flow

  components
    drive-mechanism is an electrical-drive-mechanism
    pump is a centrifugal-pump

  goal-requirements
    provide-torque: drive-mechanism must provide torque to pump

Note how the goal requirement has a label provide-torque. Requirements 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.

Transformation requirements

While 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 transformation-requirements.

For instance, our brushless-motor is the component that converts power into torque. We describe this using the sentence must convert power into torque. Lets review its definition:

define verb
  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, transformations are specified using [label]: must [verb] [variable in] [preposition] [variable out].

Design requirements

To express requirements on the values of variables we use design-requirements. 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:

define component centrifugal-pump
  variables
    min-water-flow is a liquid-material-flow

  design-requirement
    water-flow-min: water-flow must be at least min-water-flow

(In)equalities can be expressed using the design rule syntax [label]: [subject variable] must be [comparison] [bound variable] or [label]: [subject variable] must be [comparison] [value] [optional unit]. Where the comparison may be one of:

  • equal to

  • not equal to

  • at least

  • at most

  • greater than

  • smaller than

The logic may be extended using or.

Constraints

We define requirements as that what is desired for the system. However, some parts may be already present. That what is given can be expressed using constraints. goal-, transformation-, and design-constraints exist, and are identical to their ...-requirements counterparts, apart from the change from must to does when going from requirements to constraints.

For instance, our battery power source will always convert the chemical power-potential to power regardless of our requirements:

define component battery
  parameters
    power-out is an electrical-energy-flow

  variables
    power-potential is a chemical-energy-flow

  transformation-constraints
    convert-potential: does convert power-potential into power-out

Needs

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 using needs, which should be used with caution. Needs serve a documentation purpose, but are mostly ignored by the compiler.

Let’s say our drive-mechanism needs to be waterproof up to IP68 compliance:

world
  component
    drive-mechanism is an electrical-drive-mechanism

 need
   compliance: 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!

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. This way, multiple components can refer to the same torque, instead of each having their own unique variables.

To indicate the owner of a certain parameter, you can end the property keyword to the parameter declaration. Note that by definition flows cannot be properties of components as they flow through the system. As such, no single component owns a flow.

For instance, we can define the length of the drive mechanism like so:

define type
  spatial-measure

world
  variables
    drive-length is a spatial-measure

  component
    drive-mechanism is an electrical-drive-mechanism with arguments
      drive-length

define component electrical-drive-mechanism
  parameters
    length is a spatial-measure property

Note

Note that we do have to specify the spatial-measure type at every component definition. The typechecker will alert you if any type mismatches are found (or in case you forgot to add them).

Relations

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, but contain no further (mathematical) detail in their specification. This is intentional, as the language is not designed to replace all kinds of complex computation environments and languages. Lets say we want to describe the battery’s efficiency as a relation between power potential (chemical) and the output power (electrical):

define relation
  battery-efficiency-model

define component battery
  parameters
    power-out is an electrical-energy-flow

  variables
    power-potential is a chemical-energy-flow

  relations
    battery-efficiency: battery-efficiency-model with arguments
      power-potential, power-out

Note

Note that the relation’s definition is merely a name, without any further (argument) specifications as of now. This is rather loose and may change in the future.

Subclauses

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.

You can add them like so:

goal-requirement
  provide-power: power-source must provide power to electric-motor with subclauses
    c0: power must be at least 300 Watt
  end

Thus by simply adding with subclauses at the end of a requirement line, we can enumerate design rules until we end it using the end keyword. Design rules follow the design-requirement syntax.

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 options:

  • shall

  • must

  • should

  • could

  • won't

Comments

There are two types of comments available in ESL specifications. Regular comments and attached comments. As a comment sign we use the pound sign (#). The attached comments are directly tied to their component and are included and available as additional information in any output document we generate. Attached comments can be added using the #< combination or in a special comment section, like so:

define component centrifugal-pump  # I am a regular (ignored) comment.
  parameter
    torque is a mechanical-energy-flow  #< Centrifugal pump requires
                                        #< a lot of torque.

  comments
    torque #< So much info! I'm attached to the torque, too, by the way.

Multi-comments are made by repeating the (attached) comment symbols on every line. The comment section works by naming the instance you want to attach a comment to and using the attached comment sign. This can help separating the comment documentation from the requirements. Valid targets are components, goal- and transformation-requirements, needs, and relations.

Final specification

Finally, we can combine all the outlined concepts into a single specification:

define type
  mechanical-energy-flow is a real
  electrical-energy-flow is a real
  chemical-energy-flow is a real
  liquid-material-flow is a real
  performance-measure is a real
  spatial is a real

define verb
  provide to
  convert into

define relation
  pump-efficiency-model
  battery-efficiency-model

world
  variables
    torque, steady-state-torque is a mechanical-energy-flow
    reliability is a performance-measure
    drive-length, pump-length is a spatial

  components
    drive-mechanism is an electrical-drive-mechanism with arguments
      torque, drive-length

    pump is a centrifugal-pump with arguments
      torque, pump-length

  goal-requirements
    provide-torque: drive-mechanism must provide torque to pump with subclauses
      c0: steady-state-torque must be equal to 40 Nm
      c1: reliability must be at least 95 %
    end

  design-requirements
    drive-length-eq: drive-length must be equal to pump-length

define component centrifugal-pump
  parameters
    torque is a mechanical-energy-flow
    length is a spatial property

  variables
    water-flow, min-water-flow is a liquid-material-flow
    efficiency is a performance-measure

  transformation-requirements
    convert-torque: must convert torque into water-flow with subclauses
      c0: efficiency must be at least 75 %
    end

  design-requirements
    water-flow-min: water-flow must be at least min-water-flow

  relations
    pump-efficiency: pump-efficiency-model with arguments
      torque, water-flow, efficiency

define component electrical-drive-mechanism
  parameters
    torque is a mechanical-energy-flow
    length is a spatial property

  variables
    power is an electrical-energy-flow
    protection is a performance-measure

  components
    motor is a brushless-motor with arguments
      power, torque
    power-source is a battery with arguments
      power

  goal-requirements
    provide-power: power-source must provide power to motor with subclauses
      c0: power must be at least 300 Watt
    end

  needs
    compliance: protection must be IP68 compliant

define component brushless-motor
  parameters
    power is an electrical-energy-flow
    torque is a mechanical-energy-flow

  transformation-requirements
    convert-power: must convert power into torque

define component battery
  parameters
    power-out is an electrical-energy-flow  #< Unit is in Watt.

  variables
    power-potential is a chemical-energy-flow

  transformation-constraints
    convert-potential: does convert power-potential into power-out with subclauses
      c0: power-out is at most 300 W
    end

  relations
    battery-efficiency: battery-efficiency-model with arguments
      power-potential, power-out

  comments
    power-out #< Is an alternating current.