When however, they reach the point that their modeling tool performs code
generation, a different kind of problem appears: the generated code
representing the exchanged messages' data structures is completely different,
even though the structures themselves carry the same semantic content
(asn2dataModel
guarantees that).
Someone must translate the data between these different codes, and this is the
job performed by aadl2glueC
: it creates the necessary C3.2 ``glue'' code for mapping the data between the data structures generated
by asn1c
and the data structures generated by the modeling tool.
Notice that the work performed by this code is done at runtime, so it
must be performed with accuracy and precision - and as fast as possible. In the case of SCADE for example, the code generated by aadl2glueC
is using
advanced MACROs provided by ESTEREL to read/write the fields from within
the messages to the appropriate SCADE destinations (variables, object
instances, etc):
AVALON:~/ASSERT$ ls -l total 16 -rw-r--r-- 1 root root 235 2007-02-21 13:27 Data.aadl -rw-r--r-- 1 root root 446 2007-02-21 13:32 Lustre5.PosData.asn1.lus -rw-r--r-- 1 root root 716 2007-02-21 13:29 PosData.asn1 -rw-r--r-- 1 root root 213 2007-02-21 13:29 System.aadl AVALON:~/ASSERT$ aadl2glueC Data.aadl System.aadl AVALON:~/ASSERT$ ls -l total 36 -rw-r--r-- 1 root root 235 2007-02-21 13:27 Data.aadl -rw-r--r-- 1 root root 446 2007-02-21 13:32 Lustre5.PosData.asn1.lus -rw-r--r-- 1 root root 716 2007-02-21 13:29 PosData.asn1 -rw-r--r-- 1 root root 12693 2007-02-21 13:41 PosData.asn1.TC_Parser.from. asn1c.to.Lustre5.c -rw-r--r-- 1 root root 291 2007-02-21 13:41 PosData.asn1.TC_Parser.from. asn1c.to.Lustre5.h -rw-r--r-- 1 root root 213 2007-02-21 13:29 System.aadl AVALON:~/ASSERT$ cat PosData.asn1.TC_Parser.from.asn1c.to.Lustre5.h #ifndef __LUSTREPOSDATAASN1_H__ #define __LUSTREPOSDATAASN1_H__ #include <stdlib.h> /* for size_t */ int Convert_From_ASN1C_To_TCLink_In__TC_Parser__Id( void *pBuffer, size_t iBufferSize); int Convert_From_TCLink_To_ASN1C_In__TC_Parser__Param( void *pBuffer, size_t iMaxBufferSize); ...As seen above, this code generator creates ``glue'' functions that are responsible for mapping the data between the interfaces.
The first, Convert_From_ASN1C_To_TCLink_In_TC_Parser__Id
decodes an input ASN.1 stream (as provided by the pBuffer and iBufferSize
parameters) of ASN.1 type TC_Link
and stores its values inside the
SCADE variables that have been generated for parameter Id
of
subprogram TC_Parser
. The second one, Convert_From_TCLink_To_ASN1C_In__TC_Parser__Param
,
does the reverse: it reads the data used by SCADE to represent
parameter Param
of subprogram TC_Parser
and encodes
them in an ASN.1 stream of type TC_Link
. The stream is
stored inside the provided buffer arguments.
The implementation details on how the mapping between data stuctures takes place are stored inside PosData.asn1.TC_Parser.from.asn1c.to.Lustre5.c.
The generated functions don't stop at providing message translators; in the end, the outside world only needs access to two functions: an Initialize_PIname function that calls whatever initialization code is necessary (and must be called exactly once at the beginning of the system runtime) and an Execute_PIname which calls the appropriate message translation primitives for the input parameters, executes the functional code for the Provided Interface, and translates the outputs back into ASN.1 streams.
To put it simply, the code mapper creates a complete interface for usage of the APLC's code from ASSERT's VM, utilizing ASN.1 to encode and decode the messages it sends and receives.