Domain-Specific Languages have become a common tool in the toolbox of software developers. There is a natural reason for this: they are more expressive and therefore tackle complexity better, making software development easier and more convenient. They can also raise the level of abstraction from raw implementation code to the actual problem domain. Designs and specifications expressed with the higher-level problem domain concepts make specifications easier to create, check and communicate with. Most importantly, together with domain-specific generators, they can automate the creation of production code.
When companies start using domain-specific languages, they often want to utilize existing languages and specifications along with related components and legacy code. Through a concrete example from a medical domain, we describe how existing languages for Programmable Logic Controllers (PLCs), like IEC 61131-3 structured text or function block diagrams, can be extended with domain-specific constructs.
We also demonstrate native code building for the run-time system (RTS), targeting both Intel and ARM processors, and managing HMI components for monitoring measurement and control processes. The high-level languages are not only used for design and code generation, but also when debugging and profiling, or even incremental specification and execution “on the fly”. We conclude by describing our experiences of creating the domain-specific language and of using it in production.
Example domain: blood separation machines
PLCs are widely used in different industries and machines for automation. We focus here on a medical domain and describe how control logic for blood separation machines can be specified with models in domain-specific languages. These models are then used to generate the functional code – integrated with the libraries and target operating systems.
A blood separator is a medical device separating various kinds of fluids from blood. The main task of this device is to separate erythrocytes (RC), lymphocytes (BC) and plasma (PL) after centrifugation. In practice, the separation process is performed by mechanical presses and devices called “blood separation machines” operating with high speed and precision. Such a device is expected to:
- prevent the mixing of fluids using a precise control logic with a prompt response;
- enable measurements of fluid weight; and
- recognize different blood variants and adapt the separation process to blood specifics.
In addition to these medical operations there are also technical and organizational requirements on machine operation, e.g. that a device can concurrently execute several processes of separation, make labels for marking bags, or update a database of blood types and blood supplies using a web service.
Traditionally applications for these devices are developed using general-purpose languages (GPL), such as C++, Java or IEC 61131, describing both the structure and logic of the application. Figure 1 shows an example of one of the languages: an IEC 61131 function block diagram. This language specifies the individual functions of the system, and their connections along with input and output variables. In our example, the model specifies the three variable links between functions for motor speed adjustment and a step motor. Other IEC languages then allow the specification of control and logic within the functions and the whole system.
Since IEC languages are general-purpose, there is nothing in the above language, or in other GPLs, that relates them to blood separation or even to the medical domain. These languages thus don’t enable reasoning, checking, optimization for code generation, or integration with the dedicated libraries or hardware/platform in use. Nor do they allow checking any of the rules or constraints of blood separation, but leave these to be manually checked at the code level. To improve the quality and productivity of the development, we defined a domain-specific language and a code generator targeting blood separation.
Extending the language with domain concepts
To raise the level of abstraction, the language concepts were taken directly from the problem domain, in our case blood separation. This does not mean that we completely abandon all currently used languages: parts that are considered to work well can be incorporated. This also allows us to use existing specifications along with domain-specific languages.
A natural source for language constructs is the blood separation machine itself. The various elements of the hardware are easy to detect: a press, motor, switch, balance, clamp, fluid sensor and position detector. Each of these have also specific characteristics, e.g. a press must describe its limits, a detector measures the position and limits of movements, a motor has speed and direction, and an activity has state. Among all the potential characteristics those relevant for machine specification can be used directly as constructs in the language. To formalize these language constructs they are specified as a metamodel.
A metamodel typically also captures relationships among the language constructs and related constraints. Figure 2 shows a partial metamodel describing some of the key language concepts, their relationships and constraints. This metamodel was defined in the MetaEdit+ tool , enabling immediate language testing as well as production use with already available modeling editors. ()
Reading the metamodel from top left, a TwoStateController is an object of the language with two properties: a string identifier and a Boolean property to indicate if the controller is on or off. It can be connected via a SwitchSensor relationship to a Press object. The Press has more complex properties than just an entry field: several IEC_Inputs each having its own characteristics. A Press object can be connected to a PositionDetector to provide its position as a value. The PositionDetector again has its own properties, including the current position of a press. Other domain concepts are defined similarly.
If already available specifications need to be applied along with the domain concepts, their modeling constructs can be added to the metamodel too. For example, the concept of Function comes directly from IEC 61131, and the ways how it is connected have been added to the metamodel too: A function has a set of properties and it can be connected via Signal distribution to other functions and also to some other domain concepts. This enables evolutionary refinement of models which use general constructs, like Functions, into models which use domain-specific language constructs.
By directly using the concepts of the blood separation domain as language constructs, the modeling language helps prevent errors early in the development phase, minimizes specification work, and at the same time makes the language more suitable for code generation. Describing things in problem domain terms instead of implementation concepts is also good future-proofing. We can for example use the same models for other target languages or libraries.
While the metamodel defines what is possible to specify with the language, perhaps more important is what it left out: all those concepts that are not relevant for specifying blood separation machines are not part of the metamodel. This not only helps in using the language, but makes it easier to build the generators as they access the same metamodel knowing the meaning of each model element.
In addition to the metamodel, the language definition has a concrete syntax: the notation. For each language construct we created a symbol that is used to visualize it in a model. The notation was again taken from the problem domain. A sample of the notation is shown in Figure 3 .
Incremental refinement of the language while using it
A good practice is to test the language early on with concrete application examples: in our case, specifying the structure and functionality of various blood separation machines. Figure 3 illustrates a sample model describing fluid squeezing. This model uses the concepts defined in the metamodel shown in Figure 2 . Elements M1T to M6T on the left are TwoStateControllers (optical sensors), TopBloodBag is a Press and TopStepMotor is a StepMotor. In addition to the names of the elements shown in the screenshot, the tool also allows to specify the related properties and their default values, like direction and speed for step motors.
Industrial automation, and the medical domain in particular, demands high quality from the software and related systems. The domain-specific language follows the constraints and rules of the domain, guiding engineers to create correct, consistent and complete specifications. For example, the language does not allow connecting a motor to other objects other than through its ports (Figure 3 , ports Enabled, Direction and Speed of the TopStepMotor).
The same language is also used to specify control logic, like calibration of the balance (Figure 4 ). As before, this model directly applies the domain concepts, like Switch and Balance. Here the whole model is specified with plain domain concepts, without using functions or other general-purpose constructs.
Independently of the hardware employed to realize the device, the operating system, and any libraries used in implementation, a typical balance calibration procedure consists of the following steps:
- Pressing a switch to start and stop calibration (TopBalCalib)
- Reading previous reference values, for possible comparison with new ones (TopBalRefVal)
- Selection of the switch that shows if a calibration weight is placed on the scale (TopBalMax)
- Reading of numerical values, with and without the presence of the weight, using an A/D converter (TopBal and TopBalCtrl)
- Updating appropriate values of TopBalRefVal, depending on whether TopBalMax is on or off
- Repeating the calibration routine while the switch (TopBalCalib) is on
The specification of balance calibration in Figure 4 is used for generating control logic code for different programming languages and for different target platforms. For embedded systems, a particularly useful platform is a Run-Time System (RTS) which interprets or executes IEC 61131 and IEC 61499 specifications. Such a RTS provides execution of code generated based on function block diagrams. Also, it enables synchronization of distributed components, and reporting on the state of the system using events. From the code generation point of view, such a target system significantly simplifies the definition of the code generator, which needs to synchronize control logic with drivers and task scheduler.
Generators for code and configuration
Building a generator is about defining how model concepts are mapped to program code or other output like library calls. The access of the model elements is dictated by the language definition (metamodel). Consider the generator script in Figure 5 as an example: it accesses AnalogControllers (like TopBalCtrl on Figure 4), and then connections to two state switches and controllers. The green text refers directly to concepts of the language. The generator is defined in the same MetaEdit+ tool ( )we used for language definition. In this way changes in the metamodel can be immediately seen and tested while making the generators, significantly speeding up language and generator development.
This generator is then executed during code generation to produce the code needed for calibration of the machine. Other generators produce other parts like code for press, position detector, etc. Listing 1 shows the piece of code generated from the model shown in Figure 4 . The generator script described above produces the code for the if-then-else structure, and another generator script produces the variables and initializations given in the first half of Listing 1 .
This generator module and others were defined using various models ofblood separation functionality as a source. Essentially, if the currentoutput of the generator was not considered adequate, e.g. in terms offunctionality covered or style of code being generated, the generatorwas extended and possibly the language too. Moreover, since thegenerator is fully configurable, it can be modified to target otherkinds of coding practices, libraries and target languages.
Themodels specifying the various features of the blood separation machinewere grouped for the purpose of execution in special functions,programs, tasks, services, etc. Due to the fact that RTS interprets orexecutes IEC 61131 specifications, individual models were grouped in aconfiguration (Figure 6 ) from which IEC 61131 structured text for tasks and hardware signals is generated as part of the code generation (Listing 2 ).
Simulating and monitoring the generated application code
Basedon our experience, a good approach for verification of control logicand use cases is to simulate them as generated applications. This isalso a typical approach when the real device and hardware are not yetavailable. For the purpose of simulation we created as many forms asthere are simulated domain concepts related to the machine and itsoperation .
Several types of user controls, such as two-statebuttons, sliders, labels, and multi-state switches, are used in theinterface of the simulator. Controls are needed for visualization ofdifferent data types: Boolean, enumerator, integer, real and text. Herewe used only designs from Visual Studio and did not program any.
Thecontrols and forms created in .NET are visual representations of thedomain concepts, used for monitoring and debugging. Figure 7 shows anexample of a form for the balance calibration, where the slider at thebottom left is a visual representation of an A/D converter, buttons areswitches, and the labels on the right are reference values forcalibration.
Thishelped achieve an important goal: the specifications created for theblood separation closely resemble the concepts used for debugging andmonitoring the operation of the machine. The next step was then tosubmit the descriptions based on the modeling language to a .NETapplication. This called for implementing generators similar to thecontrol logic that had already been created.
In addition to thelogical description, our metamodel covers specification ofimplementation concepts used for a synchronization of the modeling tool,RTS and application for testing and monitoring. These specificationscontain a mapping between objects constructed in the modeling tool and.NET controls, including mapping between their properties. Listing 3 is a part of the extended metamodel and contains descriptions of the implementation concepts for the model from Figure 4 and monitoring application from Figure 7 . For example, user control DVMexBalance uses as an identifier the property “name”.
ForType and MetaType properties with the same name are used, and ID andOUT are predefined by using the implementation properties Name and Valuerespectively. A similar approach is used for the control of the typeLabel, which is a part of the standard .NET library. The “connProp”attribute defines a relation between controls. This relation isimportant in cases where the .NET application is used for codegeneration, but not in cases when it is used only for monitoring. Thedescription of a metamodel which is used by the .NET application is alsogenerated from the modeling tool.
Thelast component necessary for model execution is an interpreter ofAction Reports (AR) . Action reports are also produced automaticallyfrom the model using a generator: an example is shown in Listing 4 . The Action reports interpreter is driven by the metamodel (Listing 3 )and sets or gets values of control properties on given events orconditions, in given time intervals or cyclically whenever the processoris idle. In the example below, the action report CalibrateBalance isinvoked every 100 milliseconds. During the execution, current propertyvalues (:OUT;) of controls whose identifiers are given after WHEREid=’*’ are received. In a similar way, values from the run-time system(RTS) are collected, and properties for monitoring in controls of theapplication are set up.
Listing 4 : An example of an action report which synchronizes control program for calibration with a client application
Action reports SetVarValue and GetVarValue use the command language of RTS as an interface and TCP/IPcommunication protocol for accessing variables. The interpreter ofaction reports resolves all commands at runtime, so there is no need forstatic linking. In most cases action reports get and set variables ofboth the control logic of RTS and the user interface in given timeintervals, without any additional transformation of their values.
Debugging and profiling
Domain-specificconcepts may also be used in debugging and profiling. While we canalways debug the system in a programming tool, it usually does not makesense to debug the generated code itself, but rather to debug at themodel level. The developer is more familiar with the model he createdthan the generated code. Also if a problem is found we want to correctit in the model, not the code.
There are at least two useful optionsregarding model-level debugging. The first option is model animation,i.e. highlighting elements in models that are active when the code isbeing executed. This may be very useful when a model specifies behavior(e.g. Figure 4 ). The second option, which is more advanced, isbased on generation of code aimed at creating and modifying debuggingapplications. Such code defines a set of events that are relevant fordebugging processes running over the target RTS.
For example,relevant events may include changing values of variables, activation andsuspension of a task, data segment initialization, etc. The state spaceof the debugging environment is determined by the program logic, aswell as features of the RTS, and it must be mapped into a set of actionsperformed over a debugging application or a modeling tool.
Thereare two approaches for generating applications with HMI components(Figure 8). In the first alternative, labeled as Traditional Flow,models are transformed into an executable program. The secondalternative is based on the existence of a dynamic linker that isincluded in the RTS, and code generation is performed in two steps.
Firstthe model is transformed into an optimized XML tree structure, and thenthe XML tree structure is transformed into binary code. Thisalternative offers a powerful mechanism for code generation since itdoes not have limitations specific to GPLs. On the other hand,implementation of such code generators is more complex, compared to codegenerators for GPLs. Regardless of the code generation approach,synchronization between RTS, modeling tool and HMI components in thesimulator is achieved by action reports, i.e. by message passing and byevent handling.
Investment in language and generator development
Sincethe blood separation applications were defined in parallel withlanguage development, it is not straightforward to calculate the effortneeded to define the language, generators and related tool integration.Our estimation for this effort is 1 man-week, which is comparable withother reported industrial experiences, such as 1.5 man-weeks by Polarfor their heart-rate monitors and 3 man-weeks by Panasonic for theirhome automation control unit.
To indicate some measure of theeffort needed to build the generator, 928 lines of generator codeproduce the target IEC61131 program code and configuration code. Weestimate that the number of lines in the generator definition can besmaller if only domain-specific concepts would be used as input for thegenerator. The same generator can then be used to produce a wide varietyof new features to the current device, but also to produce otherdevices within the blood separation domain.
In our case,development of the HMI components required 1 man-month. During theirdevelopment features of controls were tested by running the system withpartially implemented control logic. The modeling tool was used fordesigning the control logic and generating the code. Parallel testing oflogical and visual properties of .NET controls reduced development timeby approximately one week. Since this was the same time spent onconstructing the DSL and writing generators, the investment pays backwhen the next version or new device for blood separation is developed.
Improvements in device development
Domain-specificlanguages are claimed to enable raising the level of abstraction fromcoding concepts closer to the actual problem domain. Our experiencesdemonstrate this within a medical domain. Blood separation devices canbe developed with a language that mostly uses the already familiarconcepts of blood separation. From these models code can then beautomatically generated for control logic, configuration and simulationapplications for testing and monitoring. This is seen to improve thedevelopment speed and quality significantly. From the point of view ofthe development process:
- Complete code for the control logic varies based on the features and functionality of the device, but usually contains hundreds of lines of generated IEC 61131 structured text;
- The code for the client application, which is used for the debugging, contains around 50 lines of action reports per .NET form;
- Generation of code and configuration is transformed into binary and immediately executed by the RTS (Figure 8 );
- Debugging with domain-specific models is enabled by the incremental specification and RTS that dynamically links code increments without stopping the control process.
The quality of the generated code, along with the RTS, shows good performance meeting the criteria for production systems:
- All control tasks that are executed by the RTS are using at most 1% of one core on 2GHz dual-core processors; and
- An embedded device with a single-core ARM or Intel processor at 500 MHz uses less than 4% of processor time for the most critical control tasks.
The use of DSLs and automation not only makes sense from adevelopment point of view, but also offers business opportunities.Automation in development allows the company to react quickly tocustomer needs and create new variants of blood separation functions, oreven product lines of these devices.
Since the language andgenerator are defined in parallel with development, they can be modifiedfor future needs. It is worth noticing that while the languages andgenerators were implemented by one person they are used by many: A smallinvestment to start with, but a potential for high reward when severaldevelopers are using the DSL to create production software.
1. Model Execution: An Approach based on extending Domain-Specific Modeling with Action Reports, ComSIS, 2013
Verislav Djukić ()is a software architect employed in Djukic Software GmbH, Germany. Heis involved in the development of PLC based Run-Time Systems, modelingtools, Domain-Specific Languages and control logic for medical devices.Verislav holds a Ph.D. in software engineering from the University ofNovi Sad, Serbia. His current research interests are related to theextending of M2T transformations for the purpose of model execution.
Aleksandar Popović ()is an assistant professor at the Computer Science Department of theFaculty of Science and Mathematics, University of Montenegro. Hiscurrent research interest includes domainspecific languages anddomain-specific modeling. Also, he works for Djukic Software GmbH andhas been actively involved in the development of DSLs for embedded andReal-Time systems. Aleksandar holds a Ph.D. in computer science from theUniversity of Montenegro.
Juha-Pekka Tolvanen ()has been involved in domain-specific languages, code generators andrelated tools since 1991. He works for MetaCase and has acted as aconsultant world-wide for modeling language and code generatordevelopment. Juha-Pekka has co-authored a book (Domain-SpecificModeling, Wiley) and holds a Ph.D. in computer science from theUniversity of Jyväskylä, Finland.