Hardware/software co-design can be challenging. In this blog article, I am going to explain how model-driven development using domain-specific languages (DSLs) can reduce time to market and improve product quality in heterogeneous hardware/software environments.
Today it is quite common that embedded systems consist of different component types and technologies (microcontrollers, FPGAs, DSPs, ASICs, SOCs, etc.). These heterogeneous environments are often necessary to fulfill different demands regarding costs, performance, power consumption, timing constraints, temperature, reliability, and so on.
A hardware/software co-design approach is often used to meet these demands through a strongly-coupled, simultaneous development of these hardware and software components.
The resources of an embedded system are often limited due to reasons of cost and power consumption. As a consequence, optimizing the system regarding memory consumption, logic cells, etc. is important. However, this requirement contradicts the requirement of flexibility.
Embedded systems have a strong demand for flexibility. (Hardware) components must be replaceable due to, e.g., a discontinuation of products or for the sake of vendor independence. Adding new features should be possible in a quick and cost-effective way.
Furthermore, an embedded system often serves as a common platform for several products to meet different customer requirements. This adds a considerable effort to the overall system design.
Figure 1: Hardware/software co-design example (traditional approach)
The figure above shows an example of a typical system which consists of three different component types or “domains”.
The embedded system has an FPGA for connecting external periphery and to meet performance constraints. A microcontroller is used to configure the FPGA and to run basic non-time-critical data processing. The end user interacts with the embedded system via a GUI, which configures the FPGA and the microcontroller. The current system status is also reflected by the GUI.
The functionality of each domain is modularized into several function blocks, where the meaning of a function block depends on the technology and the underlying (programming) language. A function block represents a C function on the microprocessor, a Java class in the GUI domain, and a VHDL entity on the FPGA.
Components can interact with each other. The microcontroller can write data into an FPGA register and can be triggered via interrupt when the FPGA provides new data. A click on a GUI button changes the microcontroller’s state and the current value of an FPGA register is displayed in the GUI.
Connecting components of different technology domains is generally not trivial and adds complexity to the overall system design.
In the example above, different clock domains in FPGA and microcontroller imply the need of an asynchronous data exchange interface, like FIFOs or dual-port memory. Developers must exercise care to keep both domains synchronized, e.g., regarding addresses.
In a model-based approach, part of the overall system is described by one or more DSLs. Generators produce code for different domains.
For the scenario above, we can use a DSL to model function blocks and the communication between them. Function blocks usually represent handwritten, conventional code like C, VHDL, etc. and are abstracted to interfaces with additional information in the DSL.
component A controller { in a int out b OtherType } component B fpga { in a OtherType out b int } A.a = B.b B.a = A.b
The pseudo DSL code above exemplarily shows how an FPGA component is connected to a microcontroller component.
This high-level abstraction of the system has the advantage that the developer can focus on the overall system structure without being distracted by implementation details. Recurring and error-prone tasks, like writing the boilerplate code to glue different domains (here: how the two assignments are actually implemented), are automated by the modeling platform.
Validation rules give the developer immediate feedback about design flaws and thus increase developer productivity.
As you can see in figure 1, developing products or features involving different domains becomes unnecessarily challenging if using the traditional hardware/software co-design approach. Functionality is distributed over several domains, which makes describing products or features unnecessarily complicated.
Figure 2 depicts the same system as figure 1. However, function blocks are now clustered by product, and each product can be easily described by a DSL file.
Figure 2: Example hardware/software co-design (DSL approach)
In the traditional approach, each domain requires a separate optimization. In contrast, the modeling platform can perform global optimizations by taking the complete model of the embedded system into account. Such global optimizations could pertain to, e.g., communication between different components, detection of unused function blocks.
Code generators produce arbitrary code from the model, which makes the overall system more independent of individual component manufacturers. In addition to modeling the system structure on the basis of function blocks, the DSL allows component-independent behavior modeling. The transition between handwritten code and DSL code is fluent, so that existing handwritten code can later be expressed by DSL code – as far as it makes sense.
In the past, Xtext has successfully been used for embedded systems modeling.
Xtext is an open-source framework for the development of DSLs and a solid foundation for building customized modeling platforms. It provides out-of-the-box support for a number of editors (Eclipse, Visual Studio Code, etc.) that can be integrated into almost any development ecosystem.
A strong demand for flexibility and sensible resource utilization as well as possible uses in heterogeneous environments make embedded system design complex. This negatively affects time to market and product quality.
A model-based hardware/software co-design approach can tackle these problems. A DSL gives the developer a global system view without sacrificing flexibility or performance. A model-based approach improves developer productivity and reduces time to market.
How do you target such issues in your projects?
Feel free to leave a comment below.