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 casegenerating 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 15..
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 addressfor 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 1221, 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 1517, simplified here to save space) and the selection option (line 18). Lines 1921 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 easierand 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.