Browse DevX
Sign up for e-mail newsletters from DevX


Domain-specific Modeling: Making Code Generation Complete : Page 3

Domain-specific modeling is most successful when the models let you generate complete working code, without the need for post-generation code modifications or additions. The examples and guidelines in this article show you how.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Example 2: Generating Assembler for 8-bit Microcontrollers
You can apply the same model-navigation approach in other cases, too. Here's a slightly more demanding case—generating 8-bit code for an embedded device. This particular device has a voice-menu system that enables remote control of many home-automation features, such as turning a light on or off, setting the room temperature, air conditioning control, etc. The system is programmable via an 8-bit microcontroller using an assembler-like programming language. In this case, code generation must take into account issues such as code size and memory usage that were not relevant when producing the XML in the previous example.

Besides such basic operations as accessing memory addresses, calculation, comparison and jump, the developer must also handle a few operations specific to voice menus, such as reading menu items aloud. The domain-specific language includes these concepts directly in the modeling language. The design model in Figure 2 illustrates an example of such a language.

Figure 2. Setting Parameters: The figure shows a design for setting one home automation parameter in a voice menu system.
Here's a sample of the code generated from the model in Figure 2.

01 Speak 0x01 (Pause for 0.5 sec) 02 Speak 0x02 (the...) 03 Speak 0x03 (...current...) 04 Speak 0x04 (...lifestyle...) 05 Speak 0x05 (...is...) 06 GetLifeStyle 07 Speaks Lifestyle 08 Speak 0x06 (Pause 0.3 sec) 09 Speak 0x07 (select...) 10 Speak 0x08 (...another...) 11 Speak 0x04 (...lifestyle...) 12 FillMemB 00 13 :3_844 14 Add to MemB 01 15 Speak 0x09 (for...) 16 Speaks Lifestyle 17 Speak 0x10 (...press...) 18 Speak number MemB 19 Is MemB >= 0F 20 IFNot 21 Goto 3_844

The fundamental code-generating solution relies on a flow-like execution of actions specified in the model. The metamodel for the language is relatively simple. Each elementary operation type (speaking, memory access, and comparison) has been implemented as an individual modeling concept, while the flow of execution and conditional jumps appear as relationships between these concepts. Each modeling concept also carries information about related design attributes such as the command tag, possible parameters, or conditions. As the assembly language here is domain-specific, with one assembly mnemonic reflecting one basic voice menu operation, the mapping from modeling concepts to mnemonics is solid and simple.

The generator follows the flow of operation via relationships, transforming the information contained in each design element into output code. For example, the generator uses the first bubble on the top left corner of diagram to generate the set of speech commands in lines 1—5..

Because the spoken audio samples consume a lot of memory, each word is stored only once and reused when constructing complete sentences. Thus, the spoken messages in menu elements consist of a sequence of individual words or short phrases, along with the memory addresses for the corresponding audio samples. When the code generator meets such a construct, it simply iterates over the collection and outputs the speak command for each word followed by the address of the sample. When the same audio appears multiple times the generator outputs the same memory address—for example, lines 4 and 11 use the same memory address.

Variations of the speak command can read out variable values (see lines 7 and 16) or numeric arguments (see line 18). In addition to speech commands, there are also operations for getting (line 6) and setting (line 12) values of variables.

Author's Note: This model and example code uses names to denote the variables, but in production, an organization would substitute real memory addresses.

You can see a slightly more complex part of the generation process in lines 12—21, which reads out the selection numbers for all predefined lifestyle settings.

12 FillMemB 00 13 :3_844 14 Add to MemB 01 15 Speak 0x09 (for...) 16 Speaks Lifestyle 17 Speak 0x10 (...press...) 18 Speak number MemB 19 Is MemB >= 0F 20 IFNot 21 Goto 3_844

First, it initializes the selection variable memB (lines 12 and 14). Then it retrieves and speaks the information about a predefined lifestyle (lines 15—17, simplified here to save space) and the selection option (line 18). Lines 19—21 represent the conditional jump. If the selection variable memB is less than 15 (0F hex), the code jumps back to line 13 and continues with the next predefined lifestyle, repeating the loop until memB equals 15.

In this case the key to the successful code generation is the modeling language. While there are a few domain-specific commands included in the target language itself, there is no real framework on the platform side to make the generation easier—and as you can see, the generation process itself does not include any "magic." The model level covers the structural and behavioral essence of the system, leaving no need for the generator to tackle complex variation or implementation issues related to the low-level language used.

Thanks for your registration, follow us on our social networks to keep up-to-date