Code generation is organised as a common base class CodeGenerator with a hierarchy of derived classes that specialise for specific targets.
The base class CodeGenerator reads (and writes) the configuration file. The latter includes source automata as well as execution attributes associated with individual events. E.g., the configuration file specifies a mapping from input events to respective input line addresses and polarities of edges that trigger the event. This is fine for configuration purposes, but it does not match the needs for code generation. Here, we need to set up edge detection code per line with associated events — just the other way around. Other aspects addressed by precompiling configuration data include: allocating consecutive state indices and event indices for the target code; have the event indices ordered by execution priority; compile the transition relations to vectors of integers; prepare look-up tables for bit-masks.
CodePrimitives is derived from CodeGenerator to formulate how the generated code should behave. For this purpose, it introduces abstract data types like Integer and Word and operations on them, i.e., integer division, bit-wise conjunction of words, conditional execution like switch/case or if/then/else. Abstract here reads "without a specific implementation". The outcome on this stage is a cyclic function stated in terms of data types and operations thereon to perform edge detection, event selection, event execution and output operation. The respective templates of code snippets are meant to be independent of an actual implementation.
To obtain actual code, the classes EmbeddedcCodeGenerator and Iec61131stCodeGenerator are derived from CodePrimitives, respectively. The derived classes implement the individual primitives, e.g., they specify how an integer data is allocated and how and abstract if/then/else construct in implemented C or IEC 61131-3 ST. This is a straight forward exercise. At this stage, the generated code can also be organised according to the target language: do we generate a function, or a program, shall we distinguish local from global data etc, and what are the generic options to read line-levels or to otherwise interact with a host program. The latter stage is then further refined by the derived classes ATmegaCodeGenerator, KinetisCodeGenerator and GebtoolsCodeGenerator. The former two take special care of GPIO pin access and other hardware architecture featurs. The latter provides tailored typedef constructs to please the GEB toolchain.