READER_INTERFACE
################


GENERAL
=======

In encoding version 1 all topic types marked with extensibility of FINAL or APPENDABLE are using the
PLAIN_CDR encoding. On the other hand types marked with extensibility MUTABLE are encoded in PL_CDR.[1]

The members of the topic type are handled in declaration order, each in it's own 'decode_stage'.
The 'GET_PAYLOAD_HEADER' stage jumps to the stage handling the first declared member in the topic type.
Each stage jumps to the decode_stage of the next declared member.
If there is no next declared member, stage 'SKIP_PAYLOAD' is selected.

The signal 'align_offset' keeps track of the current alignement offset (Basically byte_count mod 8).

The general procedure is that the input is latched ('data_in_latch') allowing to work Byte-oriented, since 
the input is word-sized. Each time the 'align_offset' reaches b"X11" a new input word is latched.

The CDR Encodings of all types are Byte aligned.

PRIMITIVES TYPES
================

Primitive Types are directly latched into registers of equal size (name <NAME>_lach), that are 
accesible directly via a port of the same name (i.e. <NAME>).
The name of the generated decode_stage is GET_<NAME>.
The generated decode_stage first checks the alignement and aligns the stream using the 'ALIGN_STREAM' stage.
* Primitive size 1
    The input is directly latched using the get_sub_vector function together with the current 'align_offset',
    1 is added to the 'align_offset', the decode_stage of the next declared member is taken, and the 'FETCH' 
    stage is called if the current 'align_offset' is b"X11".
* Primitive size 2
    The input is directly latched using the get_sub_vector function together with the current 'align_offset',
    2 is added to the 'align_offset', the decode_stage of the next declared member is taken, and the 'FETCH' 
    stage is called if the current 'align_offset' is b"X1X".
* Primitive size 4
    The input is directly latched, 4 is added to the 'align_offset', the decode_stage of the next declared 
    member is taken, and the 'FETCH' stage is called.
* Primitive size 8
    The decode_stage is divided with the help of 'cnt' in 3 sub-stages. A helper double-word latch 'dw_latch'
    is used. The first 2 sub-stages latch the word into the helper latch, and the last sub-stage is for 
    latching the final signal in it's final place. The "FETCH" stage is called in the first and last 
    sub-stages. In the last sub-stage 8 is added to the 'align_offset' and the decode_stage of the next 
    declared member is taken.
    NOTE: The extra sub-stage is used to push the signal to a memory in a single operation
* Primitive size 16
    The decode_stage is divided with the help of 'cnt' in 5 sub-stages. A helper quad-word latch 'qw_latch'
    is used. The first 4 sub-stages latch the word into the helper latch, and the last sub-stage is for 
    latching the final signal in it's final place. The "FETCH" stage is called in all except the 
    second-to-last sub-stage. In the last sub-stage 16 is added to the 'align_offset' and the decode_stage 
    of the next declared member is taken.
    NOTE: The extra sub-stage is used to push the signal to a memory in a single operation
    
NOTE:   If there is no next declared member, the last sub-stage should not call the "FETCH" stage. 
        (Should be overriden by "SKIP_PAYLOAD")
    
The alignements and sizes for IDL primitive types are following:

IDL TYPE                        SIZE    ALIGNMENT [2]
int8/uint8                      1       1
octet                           1       1
boolean                         1       1
char                            1       1
short/unsigned short            2       2
wchar                           2       2
long/unsigned long              4       4
float                           4       4
long long/unsigned long long    8       8
double                          8       8
long double                     16      8

ENUMERATED TYPES
================

Enumerations and Bitmasks are encoded into primitives according to their bit_bound.
The width of the latch and port is the same as the specified bit_bound, but the CDR encoding is always
Byte-aligned, so care as to be taken (i.e. resizing).
Other than that the same rules as for primitives apply.

BIT_BOUND   PRIMITIVE [3]
1-8         octet
9-16        short
17-32       long (DEFAULT if no bit_bound specified)
33-64       long long

COLLECTION TYPES
================

In contrast to primitive types, collection types are latched into memories of equal width and depth
equal to the maximum length. Memory access port signals are made available to the user to allow to access
the contents. 

SEQUENCE
--------
The name of the generated memory is <NAME>_mem, and the memory signals are connected via signals of 
name <NAME>_mem_<SIGNALNAME>. The generated memory uses a MAX_BURST_LENGTH of 1.
Following Port signals are defined:
NAME                DIRECTION   CONNECTED
<NAME>_len          out         <NAME>_len_latch
<NAME>_addr         in          <NAME>_mem_addr in 'IDLE' stage
<NAME>_ready        out         <NAME>_mem_ready_in in 'IDLE' stage, else '0' [NOTE: ANDing for aggregated elment types (see Structures below)]
<NAME>_ren          in          <NAME>_mem_read and <NAME>_mem_valid_in in 'IDLE' stage
<NAME>_valid        out         <NAME>_mem_valid_out [NOTE: ANDing for aggregated elment types (see Structures below)]
<NAME>_ack          in          <NAME>_mem_ready_out in 'IDLE' stage
<NAME>              out         <NAME>_mem_data_out

2 decode_stages are defined:
* GET_<NAME>_LENGTH
    The first decode_stage is similar to a 4-byte primitive decode stage and latches the length of the 
    sequence into the <NAME>_len_latch. If the length is equal zero, the decode_stage of the next 
    declared member is taken, instead of the GET_<NAME>. If on the other hand, the length is greater 
    than the MAX sequence length specified in the type package, the length is set to the value of the 
    type package. A special <NAME>_cnt counter (used to index the type specific memory) is initialized to 0.
    NOTE: It could be configured, that instead of truncating larger sequences, a decode error is triggered.
* GET_<NAME>
    This stage is similar to the respective primitive decode_stage with following valiations:
    The <NAME>_cnt is used to set the current <NAME>_mem_addr. On sucessful latch 
    (<NAME>_mem_valid_in and <NAME>_ready_in = '1') the align_offset is incremented by the 
    respective size, the <NAME>_cnt is incremented, and if the current <NAME>_cnt is equal to
    <NAME>_len-1, the decode_stage of the next declared member is taken.
    
A 'abort_mem' signal is defined and connected (ORed) to the reset port of all memories. The 'abort_mem'
signal is pulled high when leaving from the IDLE stage to clear all memory output latches.
    
ARRAY
-----
Array is similar to the sequence, but has no length encoding (since it always has the same size).
That means that there is no <NAME>_len port signal, <NAME>_len_latch latch, and also no 
GET_<NAME>_LENGTH stage.
The initialization of the <NAME>_cnt has to be done in the previous decode_stage.
The <NAME>_cnt is compared against the fixed array length constant form the type package.

MAP
---
Maps are basically sequences of aggregated element type [4]:
struct <NAME>_Entry {
    <key_type> key;
    <value_type> value;
};
sequence<<NAME>_Entry> <NAME>;

For simplicity the name of the <NAME>_Entry struct is ignored.
(I.e. the generated names are <NAME>_key, <NAME>_value instead of 
<NAME>_<NAME>_Entry_key and <NAME>_<NAME>_Entry_value)

AGGREGATED TYPES
================

STRUCTURE
---------

If a type member is in itself another structure, the generated <NAME> ports,signals,memories,stages,etc 
are split into <NAME>_<SUB-NAME> signals,ports,memories,stages,etc.

In case the element type of a collection type is an aggregated type, the stage of the last memebr is 
responsible for handling the <NAME>_cnt increment and check which normally be handled in the GET_<NAME> 
decode_stage. The <NAME>_ready and <NAME>_valid
port signals are generated by ANDing the respective memory signals of all sub-elements.

UNION
-----

Due to the dynamic nature of unions, all defined sub-types have to be handled equally.
Similar to structures the generated <NAME> objects are split into <NAME>_<SUB-NAME> objects,
including the special <NAME>_d objects, which handle the value of the discriminator itself.
In contrast to structures, the first decode_stage (GET_<NAME>_D) selects the next decode_stage 
according to the discriminator value itself. The rest of the generated decode_stages select the 
decode_stage of the next declared member.


NESTED COLLECTIONS
==================

If a collection type has in itself another collection type, an array of memories is generated, and the 
respective memory connection signals are also multidimensional (Meaning that custom types have to be 
created).
The <OUTER_COLLECTION_NAME>_cnt of the outer collection is used to index the multidimensional signals 
of the inner collection.
The <OUTER_COLLECTION_NAME>_ready and <OUTER_COLLECTION_NAME>_valid ports of the outer collection 
are no longer dependant on the inner collection (If the outer array has no other elements type except the 
inner collection the ports have to be hardwired).
A new <OUTER_COLLECTION_NAME>_addr_latch helper latch is defined, that latches the 
<OUTER_COLLECTION_NAME>_addr port when the <OUTER_COLLECTION_NAME>_<INNER_COLLECTION_NAME>_ren 
port signal is '1'. This address latch is used to connect the correct memory to the 
<OUTER_COLLECTION_NAME>_<INNER_COLLECTION_NAME> and 
<OUTER_COLLECTION_NAME>_<INNER_COLLECTION_NAME>_valid port signals.


OPTIONALS
=========

If a type member is specified as optional, a special header is preceding the CDR encoding.[5]
Generally the same procedure as the type of the optional member is followed with following 
modifications.
A new <NAME>_opt port signal is defined, that is connected to a <NAME>_opt_latch latch.
The previous decode_stage selects the 'GET_OPTIONAL_HEADER' decode_stage, and sets the 'return_stage'
to the actual next decode_stage (The decode_stage of the optional member).
The first generated decode_stage of the <NAME> (i.e. the stage that was in return_stage) checks
the 'optional' signal before anything else (even before the alignement). If 'optional' is '0', it sets
the <NAME>_opt_latch to '0' and selects the decode_stage of the next declared member. Otherwise 
the <NAME>_opt_latch is set to '1'.



WRITER_INTERFACE
################

GENERAL
=======

In General the writer_interface is a similar layout to the reader_interface with following modifications.

All "GET_*" stages are renamed to "WRITE_*". 
The "FETCH" stage is renamed to "PUSH".
'write_sub_vector' is used to write into 'data_out_latch' (instead of 'get_sub_vector' and 'data_in_latch').
The direction  of the <NAME> port signals are inverted (i.e. in).
Instead of calling 'SKIP_PAYLOAD' stage on the last declared member, the 'PUSH' stage is explicitly called
and the 'encode_done' and 'finalize_payload' signals are set.

COLLECTION TYPE
===============
The port signals of all collection types are modified as follows:

MOD     NAME            DIRECTION   CONNECTED
remove  <NAME>          out         -
add     <NAME>_r        out         <NAME>_mem_data_out
add     <NAME>_w        in          <NAME>_mem_data_in
add     <NAME>_wen      in          <NAME>_mem_valid_in in 'IDLE' stage [NOTE: ORed together with <NAME>_ren]
change  <NAME>_len      in          Used in <NAME>_cnt checks, and to see if collection is empty

The <NAME>_len_latch is removed (Since the Length is now an input).
The 'WRITE_<NAME>' encode_stage is divided with the help of 'cnt' into 2 sub-stages.
The first sub-stage is responsible for requesting the value from the memory (Memory READ request).
The second sub-stage waits until the value is valid (<NAME>_mem_valid_out) and does the usual write 
procedure. On sucessfull write the <NAME>_mem_ready_out has to be pulsed high to finalize the memory 
operation.
NOTE: If the encode_stage already is divided into sub-stages (due to the primitive type), a single 
sub-stage is added that does the Memory fetch operation, and the <NAME>_mem_ready_out is pulled high
in the last sub-stage.

OPTIONALS
=========
The direction of the <NAME>_opt port signal is inverted (in) and the <NAME>_opt_latch is removed.
The memory width is extended by 1 bit, and the <NAME>_opt is prepended 
(i.e. <NAME>_mem_data_in <= <NAME>_opt & <NAME>;)
No 'optional' check is done in the respective encode_stage. 
An extra sub-stage is added after the memory fetch operation, that writes the optional header depending
on the highest bit of the returned memory value (i.e. the optional bit). If the highest bit is '0' the
optional header gets a length of zero and the encode_stage of the next declared member is selected, else
the actual size of the optional member type is written. The parameter ID of the optional header is 
hardcoded to the actual member ID of the optional member.
NOTE: If the optional is part of a collection type, the <NAME>_opt signals are also split into
<NAME>_opt_r and <NAME>_opt_w port signals.


KEY_HOLDER
##########

GENERAL
=======

Generally the key_holder is a combination of both the reader_interface and writer_interface.

The port signals are predefined and fixed (no port signal generation).

Both encode_stage and decode_stage signals exist.
The 'ALIGN_STREAM' stage is split into 'ALIGN_IN_STREAM' (for decode_stage) and 'ALIGN_OUT_STREAM' 
(for encode_stage).

The decode procedure (decode_stage stages) follows 2 different decoding procedures.
The first - taken on a 'PUSH_DATA' opcode - follows the reader_interface procedure of the <TOPIC> type until 
the last declared member that is also member of the KeyHolder(<NAME>)[6] Type (i.e. the last decalred 
key of the type), after which the 'SKIP_PAYLOAD' stage is taken. 
(Since the serialized key only uses the KeyHolder(<NAME>) members, the rest is ignored)
The second - taken on a 'PUSH_SERIALIZED_KEY' opcode - follows the reader_interface procedure of the 
KeyHolder(<NAME>) directly.
Since the decode_stages for the second decoding procedure are a subset of the first decoding procedure,
the same decode stages are used, and only the 'decode_stage_next' signal is set depending on the 
'opcode_latch' signal. The 'GET_PAYLAOD_HEADER' stage selects the correct first decode stage.

Similarly the encode procedure also follows 2 different encoding procedures.
The first - taken on a 'READ_SERIALIZED_KEY' opcode - follows the write_interface procedure of the 
KeyHolder(<NAME>) Type.
The second - taken on a 'READ_KEY_HASH' opcode (if the key is not already calculated) - follows the
write_interface procedure of the <NAME>KeyHolder[7] Type. Note that this encoding is in PLAIN_CDR2 
Big Endian, meaning that types wich have an ALIGN_8 in PLAIN_CDR have a ALIGN_4 in PLAIN_CDR2.
Both encoding procedures share the same encode_stages, and the 'encode_stage_next' signal is
set depending on the 'opcode_latch' signal. On a 'READ_SERIALIZED_KEY' opcode the 
'WRITE_PAYLOAD_HEADER' stage selects the first encode_stage, while on a 'READ_KEY_HASH' opcode the 
'START_KEY_HASH_GENERATION' stage selects the first encode_stage.


PITFALLS
########
* Make sure to initialize the 'cnt' signal to zero before calling a decode_stage/encode_stage with sub-stages
* Keep in mind the ALIGN difference between PLAIN_CDR and PLAIN_CDR2
* Note that the order of the <NAME>KeyHolder[7] members is in ascending member ID and may not be the same as KeyHolder(<NAME>)[6]

[1] DDS_XTYPES v1.3, 7.4.3.1
[2] DDS_XTYPES v1.3, 7.4.1.1.1
[3] DDS_XTYPES v1.3, 7.4.1.1.3
[4] DDS_XTYPES v1.3, 7.4.1.1.4
[5] DDS_XTYPES v1.3, 7.4.1.1.5.2
[6] DDS_XTYPES v1.3, 7.2.2.4.7
[7] DDS_XTYPES v1.3, 7.6.8