Code Refactoring

This commit is contained in:
Greek 2022-01-24 15:10:48 +01:00
parent 59bff52832
commit a99b8f13c8
4 changed files with 82 additions and 80 deletions

View File

@ -16,25 +16,25 @@ 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 "x11" a new input word is latched.
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 <TYPENAME>_lach), that are
accesible directly via a port of the same name (i.e. <TYPENAME>).
The name of the generated decode_stage is GET_<TYPENAME>.
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 "x11".
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 "x1x".
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.
@ -44,12 +44,14 @@ The generated decode_stage first checks the alignement and aligns the stream usi
and the last sub-stage is for latching the final signal in it's final place. 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
NOTE: If there is no next declared member, the second-to-last stage should NOT call the "FETCH" stage
* 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 (calling 'FETCH' stage each time),
and the last sub-stage is for latching the final signal in it's final place. 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 second-to-last stage should NOT call the "FETCH" stage
The alignements and sizes for IDL primitive types are following:
@ -89,51 +91,51 @@ the contents.
SEQUENCE
--------
The name of the generated memory is <TYPENAME>_mem, and the memory signals are connected via signals of
name <TYPENAME>_mem_<SIGNALNAME>. The generated memory uses a MAX_BURST_LENGTH of 1.
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
<TYPENAME>_len out <TYPENAME>_len_latch
<TYPENAME>_addr in <TYPENAME>_mem_addr in 'IDLE' stage
<TYPENAME>_ready out <TYPENAME>_mem_ready_in in 'IDLE' stage, else '0' [NOTE: ANDing for aggregated elment types (see Structures below)]
<TYPENAME>_ren in <TYPENAME>_mem_read and <TYPENAME>_mem_valid_in in 'IDLE' stage
<TYPENAME>_valid out <TYPENAME>_mem_valid_out [NOTE: ANDing for aggregated elment types (see Structures below)]
<TYPENAME>_ack in <TYPENAME>_mem_ready_out in 'IDLE' stage
<TYPENAME> out <TYPENAME>_mem_data_out
<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_<TYPENAME>_LENGTH
* 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 <TYPENAME>_len_latch. If the length is equal zero, the decode_stage of the next
declared member is taken, instead of the GET_<TYPENAME>. A special <TYPENAME>_cnt counter (used to
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>. A special <NAME>_cnt counter (used to
index the type specific memory) is initialized to 0.
* GET_<TYPENAME>
* GET_<NAME>
This stage is similar to the respective primitive decode_stage with following valiations:
The <TYPENAME>_cnt is used to set the current <TYPENAME>_mem_addr. On sucessful latch
(<TYPENAME>_mem_valid_in and <TYPENAME>_ready_in = '1') the align_offset is incremented by the
respective size, the <TYPENAME>_cnt is incremented, and if the current <TYPENAME>_cnt is equal to
<TYPENAME>_len-1, the decode_stage of the next declared member is taken.
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.
ARRAY
-----
Array is similar to the sequence, but has no length encoding (since it always has the smae size).
That means that there is no <TYPENAME>_len port signal, <TYPENAME>_len_latch latch, and also no
GET_<TYPENAME>_LENGTH stage.
The initialization of the <TYPENAME>_cnt has to be done in the previous decode_stage.
The <TYPENAME>_cnt is compared against the fixed array length consatnt form the type package.
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 consatnt form the type package.
MAP
---
Maps are basically sequences of aggregated element type [4]:
struct <TYPENAME>_Entry {
struct <NAME>_Entry {
<key_type> key;
<value_type> value;
};
sequence<<TYPENAME>_Entry> <TYPENAME>;
sequence<<NAME>_Entry> <NAME>;
For simplicity the name of the structure is ignored.
(I.e. the generated names are <TYPENAME>_key, <TYPENAME>_value instead of
<TYPENAME>_<TYPENAME>_Entry_key and <TYPENAME>_<TYPENAME>_Entry_value)
(I.e. the generated names are <NAME>_key, <NAME>_value instead of
<NAME>_<NAME>_Entry_key and <NAME>_<NAME>_Entry_value)
AGGREGATED TYPES
================
@ -141,21 +143,21 @@ AGGREGATED TYPES
STRUCTURE
---------
If a type member is in itself another structure, the generated <TYPENAME> ports,signals,memories.stages,etc
are split into <TYPENAME>_<SUB-TYPENAME> signals,ports,memories,stages,etc.
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, a new decode_stage called
<TYPENAME>_MEMBER_END is generated, which handles the <TYPENAME>_cnt increment and check which
normally be handled in the GET_<TYPENAME> decode_stage. The <TYPENAME>_ready and <TYPENAME>_valid
<NAME>_MEMBER_END is generated, which handles 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 <TYPENAME> objects are split into <TYPENAME>_<SUB-TYPENAME> objects,
including the special <TYPENAME>_d objects, which handle the value of the discriminator itself.
In contrast to structures, the first decode_stage (GET_<TYPENAME>_D) selects the next decode_stage
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.
@ -166,16 +168,16 @@ 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_TYPENAME>_cnt of the outer collection is used to index the multidimensional signals
The <OUTER_COLLECTION_NAME>_cnt of the outer collection is used to index the multidimensional signals
of the inner collection.
The <OUTER_COLLECTION_TYPENAME>_ready and <OUTER_COLLECTION_TYPENAME>_valid ports of the outer 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_TYPENAME>_addr_latch helper latch is defined, that latches the
<OUTER_COLLECTION_TYPENAME>_addr port when the <OUTER_COLLECTION_TYPENAME>_<INNER_COLLECTION_TYPENAME>_ren
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_TYPENAME>_<INNER_COLLECTION_TYPENAME> and
<OUTER_COLLECTION_TYPENAME>_<INNER_COLLECTION_TYPENAME>_valid port signals.
<OUTER_COLLECTION_NAME>_<INNER_COLLECTION_NAME> and
<OUTER_COLLECTION_NAME>_<INNER_COLLECTION_NAME>_valid port signals.
OPTIONALS
@ -184,13 +186,13 @@ 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 <TYPENAME>_opt port signal is defined, that is connected to a <TYPENAME>_opt_latch latch.
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 <TYPENAME> (i.e. the stage that was in return_stage) checks
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 <TYPENAME>_opt_latch to '0' and selects the decode_stage of the next declared member. Otherwise
the <TYPENAME>_opt_latch is set to '1'.
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'.
@ -205,7 +207,7 @@ In General the writer_interface is a similar layout to the reader_interface with
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 <TYPENAME> port signals are inverted (i.e. in).
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.
@ -214,35 +216,35 @@ COLLECTION TYPE
The port signals of all collection types are modified as follows:
MOD NAME DIRECTION CONNECTED
remove <TYPENAME> out -
add <TYPENAME>_r out <TYPENAME>_mem_data_out
add <TYPENAME>_w in <TYPENAME>_mem_data_in
add <TYPENAME>_wen in <TYPENAME>_mem_valid_in in 'IDLE' stage [NOTE: ORed together with <TYPENAME>_ren]
change <TYPENAME>_len in Used in <TYPENAME>_cnt checks, and to see if collection is empty
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 <TYPENAME>_len_latch is removed (Since the Length is now an input).
The 'WRITE_<TYPENAME>' encode_stage is divided with the help of 'cnt' into 2 sub-stages.
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 (<TYPENAME>_mem_valid_out) and does the usual write
procedure. On sucessfull write the <TYPENAME>_mem_ready_out has to be pulsed high to finalize the memory
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 <TYPENAME>_mem_ready_out is pulled high
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 <TYPENAME>_opt port signal is inverted (in) and the <TYPENAME>_opt_latch is removed.
The memory width is extended by 1 bit, and the <TYPENAME>_opt is prepended
(i.e. <TYPENAME>_mem_data_in <= <TYPENAME>_opt & <TYPENAME>;)
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 <TYPENAME>_opt signals are also split into
<TYPENAME>_opt_r and <TYPENAME>_opt_w port signals.
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
@ -261,20 +263,20 @@ The 'ALIGN_STREAM' stage is split into 'ALIGN_IN_STREAM' (for decode_stage) and
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(<TYPENAME>)[6] Type (i.e. the last decalred
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(<TYPENAME>) members, the rest is ignored)
(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(<TYPENAME>) directly.
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(<TYPENAME>) Type.
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 <TYPENAME>KeyHolder[7] Type. Note that this encoding is in PLAIN_CDR2
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
@ -286,7 +288,7 @@ 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 <TYPENAME>KeyHolder[7] members is in ascending member ID and may not be the same as KeyHolder(<TYPENAME>)[6]
* 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

View File

@ -110,7 +110,7 @@ architecture arch of TYPENAME_reader_interface is
signal optional, optional_next : std_logic;
signal abort_mem : std_logic;
signal ready_in_dds_sig : std_logic;
signal valid_latch, valid_latch_next : std_logic;
signal valid_sig, valid_sig_next : std_logic;
signal decode_stage, decode_stage_next : DECODE_STAGE_TYPE;
signal return_stage, return_stage_next : DECODE_STAGE_TYPE;
-- ###GENERATED START###
@ -159,7 +159,7 @@ begin
eoc_user <= eoc_dds;
status_user <= status_dds;
valid <= valid_latch;
valid <= valid_sig;
decode_error <= decode_error_latch;
ready_in_dds <= ready_in_dds_sig;
@ -181,7 +181,7 @@ begin
align_offset_next <= align_offset;
target_align_next <= target_align;
optional_next <= optional;
valid_latch_next <= valid_latch;
valid_sig_next <= valid_sig;
data_in_latch_next <= data_in_latch;
align_op_next <= align_op;
abort_mem <= '0';
@ -202,7 +202,7 @@ begin
stage_next <= GET_PAYLOAD_HEADER;
-- RESET
decode_error_latch_next <= '0';
valid_latch_next <= '0';
valid_sig_next <= '0';
abort_mem <= '1';
else
-- ###GENERATED START###
@ -275,7 +275,7 @@ begin
-- If no Decode Error, mark output as valid
if (decode_error_latch = '0') then
valid_latch_next <= '1';
valid_sig_next <= '1';
end if;
-- Reset
@ -365,7 +365,7 @@ begin
last_word_in_latch <= '0';
decode_error_latch <= '0';
optional <= '0';
valid_latch <= '0';
valid_sig <= '0';
align_op <= '0';
align_offset <= (others => '0');
data_in_latch <= (others => '0');
@ -382,7 +382,7 @@ begin
last_word_in_latch <= last_word_in_latch_next;
decode_error_latch <= decode_error_latch_next;
optional <= optional_next;
valid_latch <= valid_latch_next;
valid_sig <= valid_sig_next;
align_op <= align_op_next;
align_offset <= align_offset_next;
data_in_latch <= data_in_latch_next;

View File

@ -24,7 +24,7 @@ package user_config is
-- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.128]
constant DEFAULT_IPv4_ADDRESS : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := x"C0A80080";
-- Number of RTPS Writer Endpoints
constant NUM_WRITERS : natural := 0;
constant NUM_WRITERS : natural := 1;
-- Number of RTPS Reader Endpoints
constant NUM_READERS : natural := 1;
-- Number of RTPS Endpoints (Do not modify)
@ -66,7 +66,7 @@ package user_config is
-- *ENDPOINT CONFIG*
constant ENDPOINT_CONFIG : CONFIG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
0 to NUM_READERS-1 => DEFAULT_READER_CONFIG,
NUM_READERS to NUM_WRITERS-1 => DEFAULT_WRITER_CONFIG
NUM_READERS to NUM_ENDPOINTS-1 => DEFAULT_WRITER_CONFIG
);
-- Set to TRUE for Simulation Testing (Extra Code generated)

View File

@ -101,7 +101,7 @@ package rtps_config_package is
end record;
constant READER_ENDPOINT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body
constant WRITER_ENDPOINT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body
constant LOCAL_PARTICIPANT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body
constant LOCAL_PARTICIPANT_DATA : OUTPUT_DATA_TYPE; --Deferred to package body
type STRING_WORD_ARRAY_TYPE is array (0 to (256/(WORD_WIDTH/8))-1) of std_logic_vector(WORD_WIDTH-1 downto 0);
type ENDPOINT_STRING_TYPE is array (0 to NUM_ENDPOINTS-1) of STRING_WORD_ARRAY_TYPE;