diff --git a/sim/L0_rtps_reader_test2.do b/sim/L0_rtps_reader_test2.do new file mode 100644 index 0000000..3011fc9 --- /dev/null +++ b/sim/L0_rtps_reader_test2.do @@ -0,0 +1,82 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -divider SYSTEM +add wave -noupdate /l0_rtps_reader_test2/uut/clk +add wave -noupdate /l0_rtps_reader_test2/uut/reset +add wave -noupdate -divider INPUT +add wave -noupdate -group META /l0_rtps_reader_test2/uut/empty_meta +add wave -noupdate -group META /l0_rtps_reader_test2/uut/rd_meta +add wave -noupdate -group META /l0_rtps_reader_test2/uut/last_word_in_meta +add wave -noupdate -group META -radix hexadecimal /l0_rtps_reader_test2/uut/data_in_meta +add wave -noupdate -expand -group USER /l0_rtps_reader_test2/uut/empty_user +add wave -noupdate -expand -group USER /l0_rtps_reader_test2/uut/rd_user +add wave -noupdate -expand -group USER -radix hexadecimal /l0_rtps_reader_test2/uut/data_in_user +add wave -noupdate -expand -group USER /l0_rtps_reader_test2/uut/last_word_in_user +add wave -noupdate -divider HC +add wave -noupdate /l0_rtps_reader_test2/uut/start_hc +add wave -noupdate /l0_rtps_reader_test2/uut/opcode_hc +add wave -noupdate /l0_rtps_reader_test2/uut/ack_hc +add wave -noupdate /l0_rtps_reader_test2/uut/valid_out_hc +add wave -noupdate /l0_rtps_reader_test2/uut/ready_out_hc +add wave -noupdate -radix hexadecimal /l0_rtps_reader_test2/uut/data_out_hc +add wave -noupdate /l0_rtps_reader_test2/uut/last_word_out_hc +add wave -noupdate /l0_rtps_reader_test2/uut/done_hc +add wave -noupdate /l0_rtps_reader_test2/uut/ret_hc +add wave -noupdate -divider {MAIN FSM} +add wave -noupdate /l0_rtps_reader_test2/uut/stage +add wave -noupdate /l0_rtps_reader_test2/uut/stage_next +add wave -noupdate /l0_rtps_reader_test2/uut/cnt +add wave -noupdate -divider {MEMORY FSM} +add wave -noupdate /l0_rtps_reader_test2/uut/mem_op_done +add wave -noupdate /l0_rtps_reader_test2/uut/mem_op_start +add wave -noupdate /l0_rtps_reader_test2/uut/mem_opcode +add wave -noupdate /l0_rtps_reader_test2/uut/mem_stage +add wave -noupdate /l0_rtps_reader_test2/uut/mem_stage_next +add wave -noupdate /l0_rtps_reader_test2/uut/mem_cnt +add wave -noupdate /l0_rtps_reader_test2/uut/mem_pos +add wave -noupdate -radix unsigned /l0_rtps_reader_test2/uut/mem_addr_base +add wave -noupdate -childformat {{/l0_rtps_reader_test2/uut/mem_endpoint_data.guid -radix hexadecimal} {/l0_rtps_reader_test2/uut/mem_endpoint_data.addr -radix hexadecimal} {/l0_rtps_reader_test2/uut/mem_endpoint_data.portn -radix hexadecimal} {/l0_rtps_reader_test2/uut/mem_endpoint_data.next_seq_nr -radix unsigned -childformat {{/l0_rtps_reader_test2/uut/mem_endpoint_data.next_seq_nr(0) -radix unsigned} {/l0_rtps_reader_test2/uut/mem_endpoint_data.next_seq_nr(1) -radix unsigned}}} {/l0_rtps_reader_test2/uut/mem_endpoint_data.lease_deadline -radix hexadecimal} {/l0_rtps_reader_test2/uut/mem_endpoint_data.res_time -radix hexadecimal}} -subitemconfig {/l0_rtps_reader_test2/uut/mem_endpoint_data.guid {-height 15 -radix hexadecimal} /l0_rtps_reader_test2/uut/mem_endpoint_data.addr {-height 15 -radix hexadecimal} /l0_rtps_reader_test2/uut/mem_endpoint_data.portn {-height 15 -radix hexadecimal} /l0_rtps_reader_test2/uut/mem_endpoint_data.next_seq_nr {-height 15 -radix unsigned -childformat {{/l0_rtps_reader_test2/uut/mem_endpoint_data.next_seq_nr(0) -radix unsigned} {/l0_rtps_reader_test2/uut/mem_endpoint_data.next_seq_nr(1) -radix unsigned}}} /l0_rtps_reader_test2/uut/mem_endpoint_data.next_seq_nr(0) {-height 15 -radix unsigned} /l0_rtps_reader_test2/uut/mem_endpoint_data.next_seq_nr(1) {-height 15 -radix unsigned} /l0_rtps_reader_test2/uut/mem_endpoint_data.lease_deadline {-height 15 -radix hexadecimal} /l0_rtps_reader_test2/uut/mem_endpoint_data.res_time {-height 15 -radix hexadecimal}} /l0_rtps_reader_test2/uut/mem_endpoint_data +add wave -noupdate -group MEM_CTRL -radix unsigned /l0_rtps_reader_test2/uut/mem_addr +add wave -noupdate -group MEM_CTRL /l0_rtps_reader_test2/uut/mem_valid_in +add wave -noupdate -group MEM_CTRL /l0_rtps_reader_test2/uut/mem_ready_in +add wave -noupdate -group MEM_CTRL /l0_rtps_reader_test2/uut/mem_read +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l0_rtps_reader_test2/uut/mem_write_data +add wave -noupdate -group MEM_CTRL /l0_rtps_reader_test2/uut/abort_read +add wave -noupdate -group MEM_CTRL /l0_rtps_reader_test2/uut/mem_valid_out +add wave -noupdate -group MEM_CTRL /l0_rtps_reader_test2/uut/mem_ready_out +add wave -noupdate -group MEM_CTRL -radix hexadecimal /l0_rtps_reader_test2/uut/mem_read_data +add wave -noupdate -divider TESTBENCH +add wave -noupdate -group TESTBENCH /l0_rtps_reader_test2/start_meta +add wave -noupdate -group TESTBENCH /l0_rtps_reader_test2/packet_sent_meta +add wave -noupdate -group TESTBENCH /l0_rtps_reader_test2/start_user +add wave -noupdate -group TESTBENCH /l0_rtps_reader_test2/packet_sent_user +add wave -noupdate -group TESTBENCH /l0_rtps_reader_test2/check_stage +add wave -noupdate -group TESTBENCH /l0_rtps_reader_test2/out_check_done +add wave -noupdate -group TESTBENCH /l0_rtps_reader_test2/stim_done +add wave -noupdate -group TESTBENCH /l0_rtps_reader_test2/test_done +add wave -noupdate -divider GAP +add wave -noupdate -radix unsigned /l0_rtps_reader_test2/uut/gap_start +add wave -noupdate -radix unsigned /l0_rtps_reader_test2/uut/gap_list_base +add wave -noupdate -radix unsigned /l0_rtps_reader_test2/uut/gap_list_end +add wave -noupdate /l0_rtps_reader_test2/uut/bitmap_latch +add wave -noupdate /l0_rtps_reader_test2/uut/bitmap_pos +add wave -noupdate -radix unsigned /l0_rtps_reader_test2/uut/next_seq_nr +add wave -noupdate -radix unsigned /l0_rtps_reader_test2/uut/bitmap_cnt +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {Begin {49575000 ps} 1} {Error {53225000 ps} 1} {Cursor {50275000 ps} 0} +quietly wave cursor active 3 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 100 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ns +update +WaveRestoreZoom {49779800 ps} {50803800 ps} diff --git a/src/PID_Ref.txt b/src/PID_Ref.txt index b40cc9a..5ad42db 100644 --- a/src/PID_Ref.txt +++ b/src/PID_Ref.txt @@ -132,15 +132,26 @@ PID_TYPE_MAX_SIZE_SERIALIZED long PID_ENTITY_NAME EntityName_t string -PID_CONTENT_FILTER_INFO DDSI-RTPS 9.6.3.1 -PID_COHERENT_SET DDSI-RTPS 9.6.3.2 -PID_GROUP_COHERENT_SET DDSI-RTPS 9.6.3.3 -PID_GROUP_SEQ_NUM DDSI-RTPS 9.6.3.4 -PID_WRITER_GROUP_INFO DDSI-RTPS 9.6.3.5 -PID_SECURE_WRITER_GROUP_INFO DDSI-RTPS 9.6.3.6 -PID_ORIGINAL_WRITER_INFO DDSI-RTPS 9.6.3.7 -PID_KEY_HASH DDSI-RTPS 9.6.3.8 -PID_STATUS_INFO DDSI-RTPS 9.6.3.9 +PID_CONTENT_FILTER_INFO ContentFilterInfo_t + sequence FilterResult_t + sequence FilterSignatureSequence +PID_COHERENT_SET SequenceNumber_t + SequenceNumber (2xlong) +PID_GROUP_COHERENT_SET SequenceNumber_t + SequenceNumber (2xlong) +PID_GROUP_SEQ_NUM SequenceNumber_t + SequenceNumber (2xlong) +PID_WRITER_GROUP_INFO GroupDigest_t + octet[4] +PID_SECURE_WRITER_GROUP_INFO GroupDigest_t + octet[4] +PID_ORIGINAL_WRITER_INFO OriginalWriterInfo_t + GUID octet[16] originalWriterGUID + SequenceNumber (2xlong) originalWriterSN +PID_KEY_HASH KeyHash_t + octet[16] +PID_STATUS_INFO StatusInfo_t + octet[4] diff --git a/src/REF.txt b/src/REF.txt index ba7e9d9..55350cb 100644 --- a/src/REF.txt +++ b/src/REF.txt @@ -517,7 +517,7 @@ READER 02| | +-------------------------------------------------------------+ 03| | - + LIFESPAN_DEADLINE + + + LIFESPAN_DEADLINE + 04| | +-------------------------------------------------------------+ 05| | @@ -535,6 +535,20 @@ READER **| | +-------------------------------------------------------------+ +STATUS INFO +----------- +31............24..............16..............8...............0 ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++-+-+-+-+-----------------------------------------------+-+-+-+ +| |P| |K| UNUSED |F|U|D| ++-+-+-+-+-----------------------------------------------+-+-+-+ + +P...Sample has associated Payload +K...Key Hash available +F...FilteredFlag (1:1 PID_STATUS_INFO Mapping) +U...UnregisteredFlag (1:1 PID_STATUS_INFO Mapping) +D...DisposedFlag (1:1 PID_STATUS_INFO Mapping) + INSTANCE MEMORY =============== diff --git a/src/Tests/Level_0/L0_rtps_reader_test2.vhd b/src/Tests/Level_0/L0_rtps_reader_test2.vhd new file mode 100644 index 0000000..f8778c0 --- /dev/null +++ b/src/Tests/Level_0/L0_rtps_reader_test2.vhd @@ -0,0 +1,1240 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library osvvm; -- Utility Library +context osvvm.OsvvmContext; + +use work.rtps_package.all; +use work.user_config.all; +use work.rtps_config_package.all; +use work.rtps_test_package.all; + +-- This testbench tests the User traffic handling of the RTPS Reader (Volatile, Reliable, With Key). +-- The testbench checks which packets are accepted and propagated as Cache Changes to the History Cache. +-- This testbench covers following: +-- * Traffic from matched/unmatched remote Endpoint +-- * Traffic with/without prior HEARTBEAT +-- * HEARTBEAT Handling +-- * GAP Handling +-- * Inline-QoS Handling +-- * Traffic without Payload (Unregister/Dispose DDS Operations) + +entity L0_rtps_reader_test2 is +end entity; + +architecture testbench of L0_rtps_reader_test2 is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_ENDPOINTS : natural := 4; + constant ACCEPT_RES : std_logic_vector(WORD_WIDTH downto 0) := (others => '0'); + constant REJECT_RES : std_logic_vector(WORD_WIDTH downto 0) := (others => '1'); + + -- *TYPE DECLARATION* + type SEND_STAGE_TYPE is (IDLE, BUSY); + type CHECK_STAGE_TYPE is (IDLE, CHECK, RESPONSE); + type TEST_RAM_TYPE is array (0 to (MAX_REMOTE_ENDPOINTS*WRITER_ENDPOINT_FRAME_SIZE_A)-1) of std_logic_vector(WORD_WIDTH-1 downto 0); + + -- *SIGNAL DECLARATION* + signal clk, empty_user, empty_meta, rd_user, rd_meta, last_word_in_user, last_word_in_meta : std_logic := '0'; + signal reset : std_logic := '1'; + signal data_in_user, data_in_meta, data_out_hc : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal start_hc, ack_hc, done_hc, done_hc_delay, ready_out_hc, valid_out_hc, last_word_out_hc : std_logic := '0'; + signal opcode_hc : HISTORY_CACHE_OPCODE_TYPE := NOP; + signal ret_hc : HISTORY_CACHE_RESPONSE_TYPE := OK; + signal stim_stage_user, stim_stage_meta : SEND_STAGE_TYPE := IDLE; + signal check_stage : CHECK_STAGE_TYPE := IDLE; + shared variable stimulus_user, stimulus_meta, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent_user, packet_sent_meta : std_logic := '0'; + signal cnt_stim_meta, cnt_stim_user : natural := 0; + signal start_meta, start_user : std_logic := '0'; + shared variable SB_out : osvvm.ScoreBoardPkg_slv.ScoreBoardPType; + signal stim_done, mem_check_done, out_check_done, test_done : std_logic := '0'; + + -- *FUNCTION DECLARATION* + function gen_sn(input : natural) return SEQUENCENUMBER_TYPE is + variable ret : SEQUENCENUMBER_TYPE; + begin + ret(0) := (others => '0'); + ret(1) := unsigned(int(input, WORD_WIDTH)); + return ret; + end function; +begin + + -- Unit Under Test + uut : entity work.rtps_reader(arch) + generic map ( + ENTITYID => DEFAULT_READER_ENTITYID, + RELIABILTY_QOS => RELIABLE_RELIABILITY_QOS, + LIVELINESS_QOS => AUTOMATIC_LIVELINESS_QOS, + DURABILITY_QOS => VOLATILE_DURABILITY_QOS, + HEARTBEAT_RESPONSE_DELAY => DURATION_ZERO, + HEARTBEAT_SUPPRESSION_DELAY => DURATION_ZERO, + LEASE_DURATION => DURATION_INFINITE, + WITH_KEY => TRUE, + MAX_REMOTE_ENDPOINTS => MAX_REMOTE_ENDPOINTS + ) + port map ( + -- SYSTEM + clk => clk, + reset => reset, + time => TIME_ZERO, + empty_user => empty_meta or packet_sent_user, + rd_user => rd_user, + data_in_user => data_in_user, + last_word_in_user => last_word_in_user, + empty_meta => empty_meta or packet_sent_meta, + rd_meta => rd_meta, + data_in_meta => data_in_meta, + last_word_in_meta => last_word_in_meta, + wr_rtps => open, + full_rtps => '0', + last_word_out_rtps => open, + data_out_rtps => open, + start_hc => start_hc, + opcode_hc => opcode_hc, + ack_hc => ack_hc, + done_hc => done_hc, + ret_hc => ret_hc, + data_out_hc => data_out_hc, + valid_out_hc => valid_out_hc, + ready_out_hc => ready_out_hc, + last_word_out_hc => last_word_out_hc + ); + + stimulus_prc : process + variable RV : RandomPType; + variable e0, e1, e2, endpoint : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA; + variable payload : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + variable sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable cc : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + variable src_ts, life_ts : TIME_TYPE := TIME_INVALID; + + -- Wrapper to use procedure as function + impure function gen_rand_loc_2 return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; + begin + gen_rand_loc(RV, ret); + return ret; + end function; + + impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is + variable ret : GUIDPREFIX_TYPE; + begin + ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH)); + return ret; + end function; + + procedure start_meta_test is + begin + start_meta <= '1'; + wait until rising_edge(clk); + start_meta <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure start_user_test is + begin + start_user <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + wait until rising_edge(clk); + end procedure; + + procedure push_reference(accept : in BOOLEAN) is + begin + -- NOTE: First Word represents the Response that we will return. + if (accept) then + SB_out.Push(ACCEPT_RES); + else + SB_out.Push(REJECT_RES); + end if; + for i in 0 to reference.length-1 loop + SB_out.Push(reference.last(i) & reference.data(i)); + end loop; + end procedure; + + impure function gen_payload return TEST_PACKET_TYPE is + variable ret : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + begin + for i in 0 to RV.RandInt(1,10) loop + ret.data(ret.length) := RV.RandSlv(WORD_WIDTH); + ret.length := ret.length + 1; + end loop; + return ret; + end function; + + impure function gen_key_hash return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := (others => (others => '0')); + begin + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := RV.RandSlv(WORD_WIDTH); + end loop; + return ret; + end function; + + procedure wait_on_meta_sent is + begin + wait until rising_edge(packet_sent_meta); + end procedure; + + procedure wait_on_user_sent is + begin + wait until rising_edge(packet_sent_user); + end procedure; + + procedure wait_on_out_check is + begin + if (out_check_done /= '1') then + wait until out_check_done = '1'; + end if; + end procedure; + + procedure wait_on_completion is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + begin + + SetAlertLogName("rtps_reader - Level 0 - User Traffic Handling"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- Endpoint 1 + e0 := DEFAULT_ENDPOINT_DATA; + e0.nr := 0; + e0.match := MATCH; + e0.entityid := RV.RandSlv(ENTITYID_WIDTH); + e0.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 2 + e1 := DEFAULT_ENDPOINT_DATA; + e1.nr := 1; + e1.match := MATCH; + e1.entityid := RV.RandSlv(ENTITYID_WIDTH); + e1.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + -- Endpoint 3 + e2 := DEFAULT_ENDPOINT_DATA; + e2.nr := 2; + e2.match := MATCH; + e2.entityid := RV.RandSlv(ENTITYID_WIDTH); + e2.unicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + + Log("Initiating Test", INFO); + stim_done <= '0'; + start_meta <= '0'; + start_user <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + + src_ts := TIME_INVALID; + life_ts := TIME_INVALID; + + -- *GENERAL SEQUENCE NUMBER HANDLING* + Log("Test General SequenceNumber Handling", INFO); + + Log("Ignore Endpoint 0 sent DATA [SN 1]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(1); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + -- NOTE: We do not wait here for the sent, to allow meta traffic being available during user traffic handling. + + Log("Insert Endpoint 0,1,2", INFO); + gen_endpoint_match_frame(e0, stimulus_meta); + gen_endpoint_match_frame(e1, stimulus_meta); + gen_endpoint_match_frame(e2, stimulus_meta); + start_meta_test; + wait_on_meta_sent; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 0 sent DATA [SN 1]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(1); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 0 sent DATA [SN 1]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(1); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 0 sent DATA [SN 3]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(3); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 0 sent DATA [SN 2]", INFO); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(2); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, TIME_INVALID, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + -- *HEARTBEAT HANDLING* + Log("Test HEARTBEAT Handling", INFO); + + Log("Endpoint 2 Heartbeat [First 2, Last 11]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_HEARTBEAT; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.firstSN := gen_sn(2); + sub.lastSN := gen_sn(11); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 2]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(2); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 2 sent DATA [SN 11]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(11); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Endpoint 2 Heartbeat [First 5, Last 15]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_HEARTBEAT; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.firstSN := gen_sn(5); + sub.lastSN := gen_sn(15); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 5]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(5); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 15]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(15); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 2 sent DATA [SN 12]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(12); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Endpoint 2 Heartbeat [First 15, Last 18]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_HEARTBEAT; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.firstSN := gen_sn(15); + sub.lastSN := gen_sn(18); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 16]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(16); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 16]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(18); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 2 sent DATA [SN 15]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(15); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Endpoint 2 Heartbeat [First 19, Last 18]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_HEARTBEAT; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.firstSN := gen_sn(19); + sub.lastSN := gen_sn(18); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 2 sent DATA [SN 19]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(19); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + -- *GAP HANDLING* + Log("Test GAP Handling", INFO); + + Log("Endpoint 2 Heartbeat [GAP 1-10]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.gapStart := gen_sn(1); + sub.gapList := (base => gen_sn(11), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 11]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(11); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Endpoint 2 Heartbeat [GAP 2-10,12]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.gapStart := gen_sn(2); + sub.gapList := (base => gen_sn(10), numBits => int(3, CDR_LONG_WIDTH), bitmap => (0 => '1', 2 => '1', others => '0')); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 13]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(13); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Endpoint 2 Heartbeat [GAP 21-22]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.gapStart := gen_sn(21); + sub.gapList := (base => gen_sn(23), numBits => int(0, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 2 sent DATA [SN 20]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(20); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Endpoint 2 Heartbeat [GAP 21-22, 24]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.gapStart := gen_sn(21); + sub.gapList := (base => gen_sn(22), numBits => int(3, CDR_LONG_WIDTH), bitmap => (0 => '1', 2 => '1', others => '0')); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 21]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(21); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 2 sent DATA [SN 23]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(23); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Endpoint 2 Heartbeat [GAP 21-22, 24]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.gapStart := gen_sn(21); + sub.gapList := (base => gen_sn(23), numBits => int(3, CDR_LONG_WIDTH), bitmap => (0 => '1', 2 => '1', others => '0')); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 24]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(24); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 2 sent DATA [SN 25]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(25); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Endpoint 2 Heartbeat [GAP 20-30]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_GAP; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.gapStart := gen_sn(20); + sub.gapList := (base => gen_sn(31), numBits => int(1, CDR_LONG_WIDTH), bitmap => (others => '0')); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 2 sent DATA [SN 26]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(26); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 2 sent DATA [SN 31]", INFO); + endpoint := e2; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(31); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + -- *DURABILITY AND INLINE-QOS HANDLING* + Log("Test Durability and Inline-QoS Handling", INFO); + + Log("Accept Endpoint 1 sent DATA [SN 10]", INFO); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(10); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + cc := gen_cache_change(sub); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 1 sent DATA [SN 11, Inline-QoS (Lifespan, Status Info, Key Hash)]", INFO); + src_ts := gen_duration(1,0); + life_ts := gen_duration(2,0); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(11); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + sub.data := gen_payload; + cc := gen_cache_change(sub); + cc.kind := ALIVE_FILTERED; + cc.src_timestamp := src_ts; + cc.instance := gen_key_hash; + gen_inline_qos(cc, life_ts, sub.inlineQos); + gen_sentinel(sub.inlineQos); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 1 sent DATA [SN 12, Inline-QoS (Invalid PID_LIFESPAN)]", INFO); + src_ts := gen_duration(1,100); + life_ts := gen_duration(2,100); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(12); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + sub.data := gen_payload; + cc := gen_cache_change(sub); + cc.kind := ALIVE_FILTERED; + cc.src_timestamp := src_ts; + cc.instance := gen_key_hash; + gen_inline_qos(cc, life_ts, sub.inlineQos, PID_LIFESPAN, -1); + gen_sentinel(sub.inlineQos); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 1 sent DATA [SN 12, Inline-QoS (Extra Bytes in PID_LIFESPAN)]", INFO); + src_ts := gen_duration(1,200); + life_ts := gen_duration(2,200); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(12); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + sub.data := gen_payload; + cc := gen_cache_change(sub); + cc.kind := ALIVE_FILTERED; + cc.src_timestamp := src_ts; + cc.instance := gen_key_hash; + gen_inline_qos(cc, life_ts, sub.inlineQos, PID_LIFESPAN, +1); + gen_sentinel(sub.inlineQos); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 1 sent DATA [SN 13, Inline-QoS (Invalid PID_STATUS_INFO)]", INFO); + src_ts := gen_duration(1,300); + life_ts := gen_duration(2,300); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(13); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + sub.data := gen_payload; + cc := gen_cache_change(sub); + cc.kind := ALIVE_FILTERED; + cc.src_timestamp := src_ts; + cc.instance := gen_key_hash; + gen_inline_qos(cc, life_ts, sub.inlineQos, PID_STATUS_INFO, -1); + gen_sentinel(sub.inlineQos); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 1 sent DATA [SN 13, Inline-QoS (Extra Bytes in PID_STATUS_INFO)]", INFO); + src_ts := gen_duration(1,400); + life_ts := gen_duration(2,400); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(13); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + sub.data := gen_payload; + cc := gen_cache_change(sub); + cc.kind := ALIVE_FILTERED; + cc.src_timestamp := src_ts; + cc.instance := gen_key_hash; + gen_inline_qos(cc, life_ts, sub.inlineQos, PID_STATUS_INFO, +1); + gen_sentinel(sub.inlineQos); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Ignore Endpoint 1 sent DATA [SN 14, Inline-QoS (Invalid PID_KEY_HASH)]", INFO); + src_ts := gen_duration(1,500); + life_ts := gen_duration(2,500); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(14); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + sub.data := gen_payload; + cc := gen_cache_change(sub); + cc.kind := ALIVE_FILTERED; + cc.src_timestamp := src_ts; + cc.instance := gen_key_hash; + gen_inline_qos(cc, life_ts, sub.inlineQos, PID_KEY_HASH, -1); + gen_sentinel(sub.inlineQos); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user_test; + wait_on_user_sent; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 1 sent DATA [SN 14, Inline-QoS (Extra Bytes in PID_KEY_HASH)]", INFO); + src_ts := gen_duration(1,600); + life_ts := gen_duration(2,600); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(14); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + sub.data := gen_payload; + cc := gen_cache_change(sub); + cc.kind := ALIVE_FILTERED; + cc.src_timestamp := src_ts; + cc.instance := gen_key_hash; + gen_inline_qos(cc, life_ts, sub.inlineQos, PID_KEY_HASH, +1); + gen_sentinel(sub.inlineQos); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + -- *NON_PAYLOAD TRAFFIC HANDLING* + Log("Test Non-Payload Traffic Handling", INFO); + + Log("Accept Endpoint 1 sent DATA [SN 15, No Payload, Inline-QoS (Lifespan, Status Info, Key Hash)]", INFO); + src_ts := gen_duration(2,0); + life_ts := gen_duration(3,0); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(15); + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + cc := gen_cache_change(sub); + cc.kind := NOT_ALIVE_DISPOSED; + cc.src_timestamp := src_ts; + cc.instance := gen_key_hash; + gen_inline_qos(cc, life_ts, sub.inlineQos); + gen_sentinel(sub.inlineQos); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + Log("Accept Endpoint 1 sent DATA [SN 16, Serialized Key, Inline-QoS (Lifespan, Status Info)]", INFO); + src_ts := gen_duration(2,500); + life_ts := gen_duration(3,500); + endpoint := e1; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(16); + sub.flags(SUBMESSAGE_KEY_FLAG_POS) := '1'; + sub.flags(SUBMESSAGE_INLINE_QOS_FLAG_POS) := '1'; + sub.data := gen_payload; + cc := gen_cache_change(sub); + cc.kind := NOT_ALIVE_DISPOSED; + cc.src_timestamp := src_ts; + gen_inline_qos(cc, life_ts, sub.inlineQos); + gen_sentinel(sub.inlineQos); + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + gen_add_cache_change_dds(cc, life_ts, endpoint.nr, reference); + push_reference(TRUE); + start_user_test; + wait_on_user_sent; + wait_on_out_check; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + -- *CONCURRENT TRAFFIC HANDLING* + Log("Test Concurrent User and Metatraffic Handling", INFO); + + Log("Unmatch Endpoint 0 and Ignore Endpoint 0 sent DATA [SN 3]", INFO); + e0.match := UNMATCH; + gen_endpoint_match_frame(e0, stimulus_meta); + endpoint := e0; + sub := DEFAULT_RTPS_SUBMESSAGE; + sub.submessageID := SID_DATA; + sub.writerId := endpoint.entityid; + sub.readerId := DEFAULT_READER_ENTITYID; + sub.writerSN := gen_sn(1); + sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + sub.data := gen_payload; + gen_rtps_handler_out(sub, get_loc(endpoint), FALSE, src_ts, endpoint.participant.guidPrefix, stimulus_user); + start_user <= '1'; + start_meta <= '1'; + wait until rising_edge(clk); + start_user <= '0'; + start_meta <= '0'; + stimulus_meta := EMPTY_TEST_PACKET; + stimulus_user := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + + stim_done <= '1'; + wait_on_completion; + TranscriptOpen(RESULTS_FILE, APPEND_MODE); + SetTranscriptMirror; + ReportAlerts; + TranscriptClose; + std.env.stop; + wait; + end process; + + clock_prc : process + begin + clk <= '0'; + wait for 25 ns; + clk <= '1'; + wait for 25 ns; + end process; + + empty_meta_prc : process + begin + empty_meta <= '0'; + wait; -- TODO: Remove + wait until rd_meta = '1'; + wait until rising_edge(clk); + empty_meta <= '1'; + wait until rising_edge(clk); + end process; + + empty_user_prc : process + begin + empty_user <= '0'; + wait; -- TODO: Remove + wait until rd_user = '1'; + wait until rising_edge(clk); + empty_user <= '1'; + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(empty_meta = '1' and rd_meta = '1', "Input FIFO read signal high while empty signal high (meta)", ERROR); + alertif(empty_user = '1' and rd_user = '1', "Input FIFO read signal high while empty signal high (user)", ERROR); + end if; + end process; + + input_meta_prc : process(all) + begin + data_in_meta <= stimulus_meta.data(cnt_stim_meta); + last_word_in_meta <= stimulus_meta.last(cnt_stim_meta); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_meta <= 0; + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + else + case (stim_stage_meta) is + when IDLE => + if (start_meta = '1' and stimulus_meta.length /= 0) then + stim_stage_meta <= BUSY; + packet_sent_meta <= '0'; + end if; + when BUSY => + if (rd_meta = '1') then + if (cnt_stim_meta = stimulus_meta.length-1) then + stim_stage_meta <= IDLE; + packet_sent_meta <= '1'; + cnt_stim_meta <= 0; + else + cnt_stim_meta <= cnt_stim_meta + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + input_user_prc : process(all) + begin + data_in_user <= stimulus_user.data(cnt_stim_user); + last_word_in_user <= stimulus_user.last(cnt_stim_user); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim_user <= 0; + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + else + case (stim_stage_user) is + when IDLE => + if (start_user = '1' and stimulus_user.length /= 0) then + stim_stage_user <= BUSY; + packet_sent_user <= '0'; + end if; + when BUSY => + if (rd_user = '1') then + if (cnt_stim_user = stimulus_user.length-1) then + stim_stage_user <= IDLE; + packet_sent_user <= '1'; + cnt_stim_user <= 0; + else + cnt_stim_user <= cnt_stim_user + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_out.empty) then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + out_check_prc : process(all) + variable accept : std_logic_vector(WORD_WIDTH downto 0); + begin + if rising_edge(clk) then + case (check_stage) is + when IDLE => + ack_hc <= '0'; + done_hc <= '0'; + ready_out_hc <= '0'; + ret_hc <= ERROR; + out_check_done <= '0'; + if (start_hc = '1') then + ack_hc <= '1'; + check_stage <= CHECK; + case (opcode_hc) is + when ADD_CACHE_CHANGE => + -- Pop Response Value + SB_out.pop(accept); + when others => + Alert("Unexpected HC Opcode", ERROR); + end case; + end if; + when CHECK => + ack_hc <= '0'; + ready_out_hc <= '1'; + out_check_done <= '0'; + if (valid_out_hc = '1') then + SB_out.Check(last_word_out_hc & data_out_hc); + + if (last_word_out_hc = '1') then + ready_out_hc <= '0'; + check_stage <= RESPONSE; + end if; + end if; + when RESPONSE => + ack_hc <= '0'; + ready_out_hc <= '0'; + done_hc <= '1'; + if (accept = ACCEPT_RES) then + ret_hc <= OK; + else + ret_hc <= REJECTED; + end if; + check_stage <= IDLE; + out_check_done <= '1'; + end case; + end if; + end process; + + watchdog : process + begin + wait for 1 ms; + Alert("Test timeout", FAILURE); + std.env.stop; + end process; + +end architecture; \ No newline at end of file diff --git a/src/Tests/testbench.pro b/src/Tests/testbench.pro index 91b8a76..e24f15b 100644 --- a/src/Tests/testbench.pro +++ b/src/Tests/testbench.pro @@ -30,17 +30,19 @@ analyze Level_0/L0_rtps_out_test1.vhd analyze Level_1/L1_rtps_builtin_endpoint_test1.vhd analyze Level_0/L0_mem_ctrl_test1.vhd analyze Level_0/L0_rtps_reader_test1.vhd +analyze Level_0/L0_rtps_reader_test2.vhd -simulate L0_rtps_handler_test1 -simulate L0_rtps_handler_test2 -simulate L0_rtps_builtin_endpoint_test1 -simulate L0_rtps_builtin_endpoint_test2 -simulate L0_rtps_builtin_endpoint_test3 -simulate L0_rtps_builtin_endpoint_test4 -simulate L0_rtps_builtin_endpoint_test5 -simulate L0_rtps_builtin_endpoint_test6 -simulate L0_rtps_builtin_endpoint_test7 -simulate L0_rtps_out_test1 -simulate L1_rtps_builtin_endpoint_test1 -simulate L0_mem_ctrl_test1 -simulate L0_rtps_reader_test1 \ No newline at end of file +#simulate L0_rtps_handler_test1 +#simulate L0_rtps_handler_test2 +#simulate L0_rtps_builtin_endpoint_test1 +#simulate L0_rtps_builtin_endpoint_test2 +#simulate L0_rtps_builtin_endpoint_test3 +#simulate L0_rtps_builtin_endpoint_test4 +#simulate L0_rtps_builtin_endpoint_test5 +#simulate L0_rtps_builtin_endpoint_test6 +#simulate L0_rtps_builtin_endpoint_test7 +#simulate L0_rtps_out_test1 +#simulate L1_rtps_builtin_endpoint_test1 +#simulate L0_mem_ctrl_test1 +#simulate L0_rtps_reader_test1 +simulate L0_rtps_reader_test2 diff --git a/src/rtps_package.vhd b/src/rtps_package.vhd index d6309d4..2a8ea2c 100644 --- a/src/rtps_package.vhd +++ b/src/rtps_package.vhd @@ -456,6 +456,8 @@ package rtps_package is constant DEFAULT_USER_DOMAIN_TAG : USER_STRING_TYPE := (others => NUL); + function to_guid(A : GUIDPREFIX_TYPE; B : std_logic_vector(ENTITYID_WIDTH-1 downto 0)) return GUID_TYPE; + -- *OVERLOAD FUNCTIONS* function convert_from_double_word (input: DOUBLE_WORD_ARRAY) return unsigned; function convert_to_double_word (input: unsigned(63 downto 0)) return DOUBLE_WORD_ARRAY; @@ -679,4 +681,14 @@ package body rtps_package is return to_integer(dw(0)); end function; + function to_guid(A : GUIDPREFIX_TYPE; B : std_logic_vector(ENTITYID_WIDTH-1 downto 0)) return GUID_TYPE is + variable ret : GUID_TYPE := GUID_UNKNOWN; + begin + for i in 0 to GUIDPREFIX_TYPE'length-1 loop + ret(i) := A(i); + end loop; + ret(3) := B; + return ret; + end function; + end package body; diff --git a/src/rtps_reader.vhd b/src/rtps_reader.vhd index e76174b..593b2bb 100644 --- a/src/rtps_reader.vhd +++ b/src/rtps_reader.vhd @@ -402,6 +402,8 @@ begin sn_latch_1_next <= sn_latch_1; sn_latch_2_next <= sn_latch_2; sn_latch_3_next <= sn_latch_3; + bitmap_latch <= bitmap_latch_next; + bitmap_cnt <= bitmap_cnt_next; bitmap_pos_next <= bitmap_pos; key_hash_rcvd_next <= key_hash_rcvd; key_hash_next <= key_hash; @@ -412,13 +414,15 @@ begin return_stage_next <= return_stage; check_time_next <= check_time; lifespan_next <= lifespan; + parameter_end_next <= parameter_end; + next_seq_nr_next <= next_seq_nr; -- DEFAULT Unregistered mem_opcode <= NOP; opcode_hc <= NOP; lease_deadline <= TIME_INVALID; res_time <= TIME_INVALID; + reset_read_cnt <= '0'; rd_meta <= '0'; - rd_user <= '0'; mem_op_start <= '0'; start_hc <= '0'; valid_out_hc <= '0'; @@ -506,7 +510,7 @@ begin stage_next <= LATCH_SRC_ADDR; -- SANITY CHECK: Skip Packet if non-standard Payload - if(header_opcode = SID_DATA and payload_flag = '1') then + if(header_opcode = SID_DATA and header_flags(SUBMESSAGE_NON_STANDARD_PAYLOAD_FLAG_POS) = '1') then stage_next <= SKIP_PACKET; end if; end if; @@ -900,7 +904,7 @@ begin res_time <= TIME_INVALID; end if; -- If current Sequence Number obsolete (removed from source history cache) - elsif (first_seq_nr > mem_endpoint_data.next_seq_nr and first_seq_nr <= last_seq_nr) then + elsif (first_seq_nr > mem_endpoint_data.next_seq_nr) then -- Store new expected Sequence Number and set Response Dealy next_seq_nr_next <= first_seq_nr; mem_op_start <= '1'; @@ -932,7 +936,7 @@ begin -- Currently in Heartbeat Response Delay elsif (mem_endpoint_data.res_time(1)(0) = '0') then -- If current Sequence Number obsolete (removed from source history cache) - if (first_seq_nr > mem_endpoint_data.next_seq_nr and first_seq_nr <= last_seq_nr) then + if (first_seq_nr > mem_endpoint_data.next_seq_nr) then -- Store new expected Sequence Number next_seq_nr_next <= first_seq_nr; mem_op_start <= '1'; @@ -1121,6 +1125,8 @@ begin -- Ignore null; when PID_SENTINEL => + -- Reset + parameter_end_next <= (others => '1'); -- QOS DONE stage_next <= INITIATE_ADD_CACHE_CHANGE_REQUEST; when others => @@ -1197,25 +1203,31 @@ begin when INITIATE_ADD_CACHE_CHANGE_REQUEST => -- Wait for Endpoint Data if (mem_op_done = '1') then - -- Data is Next expected Sequence Number - if ((RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and seq_nr = mem_endpoint_data.next_seq_nr) or (RELIABILTY_QOS = BEST_EFFORT_RELIABILITY_QOS and seq_nr >= mem_endpoint_data.next_seq_nr) or (DURABILITY_QOS = VOLATILE_DURABILITY_QOS and mem_endpoint_data.next_seq_nr = SEQUENCENUMBER_UNKNOWN)) then - -- SANITY CHECK: Skip if no Hash Key and no Payload - if (WITH_KEY and key_hash_rcvd = '0' and data_flag = '0' and key_flag = '0') then - -- Ignore - stage_next <= SKIP_PACKET; - else - start_hc <= '1'; - opcode_hc <= ADD_CACHE_CHANGE; - -- Wait until History Cache acknowledges request - if (ack_hc = '1') then - start_hc <= '0'; - stage_next <= ADD_CACHE_CHANGE; - cnt_next <= 0; - end if; - end if; - else + -- Unknown Endpoint + if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then -- Ignore stage_next <= SKIP_PACKET; + else + -- Data is Next expected Sequence Number + if ((RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and seq_nr = mem_endpoint_data.next_seq_nr) or (RELIABILTY_QOS = BEST_EFFORT_RELIABILITY_QOS and seq_nr >= mem_endpoint_data.next_seq_nr) or (DURABILITY_QOS = VOLATILE_DURABILITY_QOS and mem_endpoint_data.next_seq_nr = SEQUENCENUMBER_UNKNOWN)) then + -- SANITY CHECK: Skip if no Hash Key and no Payload + if (WITH_KEY and key_hash_rcvd = '0' and data_flag = '0' and key_flag = '0') then + -- Ignore + stage_next <= SKIP_PACKET; + else + start_hc <= '1'; + opcode_hc <= ADD_CACHE_CHANGE; + -- Wait until History Cache acknowledges request + if (ack_hc = '1') then + start_hc <= '0'; + stage_next <= ADD_CACHE_CHANGE; + cnt_next <= 0; + end if; + end if; + else + -- Ignore + stage_next <= SKIP_PACKET; + end if; end if; end if; when ADD_CACHE_CHANGE => @@ -1226,7 +1238,6 @@ begin data_out_hc <= status_info; data_out_hc(SSI_KEY_HASH_FLAG) <= key_hash_rcvd; data_out_hc(SSI_PAYLOAD_FLAG) <= data_flag; - data_out_hc(SSI_ALIGNED_FLAG) <= data_flag; -- Output Guard if (ready_out_hc = '1') then cnt_next <= cnt + 1; @@ -1317,7 +1328,7 @@ begin stage_next <= PUSH_PAYLOAD; else -- DONE - last_word_out_hc <= '1'; + last_word_out_hc <= '1'; stage_next <= FINALIZE_ADD_CACHE_CHANGE_REQUEST; end if; end if; @@ -2437,7 +2448,7 @@ begin if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET; - mem_write_data <= (others => '0'); + mem_write_data <= std_logic_vector(TIME_INVALID(0)); if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; @@ -2447,7 +2458,7 @@ begin if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1; - mem_write_data <= (others => '0'); + mem_write_data <= std_logic_vector(TIME_INVALID(1)); if (mem_ready_in = '1') then -- DONE mem_stage_next <= IDLE; @@ -2465,7 +2476,7 @@ begin mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_IPV4_ADDR_OFFSET; mem_write_data <= mem_endpoint_latch_data.addr; - mem_endpoint_data.addr <= mem_endpoint_latch_data.addr; + mem_endpoint_data_next.addr <= mem_endpoint_latch_data.addr; -- Memory Flow Control Guard if (mem_ready_in = '1') then if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then @@ -2489,7 +2500,7 @@ begin mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET; mem_write_data <= mem_endpoint_latch_data.portn & ((mem_write_data'length-mem_endpoint_latch_data.portn'length-1) downto 0 => '0'); - mem_endpoint_data.portn <= mem_endpoint_latch_data.portn; + mem_endpoint_data_next.portn <= mem_endpoint_latch_data.portn; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then @@ -2518,7 +2529,7 @@ begin mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1; mem_write_data <= std_logic_vector(mem_endpoint_latch_data.next_seq_nr(1)); - mem_endpoint_data.next_seq_nr <= mem_endpoint_latch_data.next_seq_nr; + mem_endpoint_data_next.next_seq_nr <= mem_endpoint_latch_data.next_seq_nr; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then @@ -2544,7 +2555,7 @@ begin mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1; mem_write_data <= std_logic_vector(mem_endpoint_latch_data.lease_deadline(1)); - mem_endpoint_data.lease_deadline <= mem_endpoint_latch_data.lease_deadline; + mem_endpoint_data_next.lease_deadline <= mem_endpoint_latch_data.lease_deadline; -- Memory Flow Control Guard if (mem_ready_in = '1') then if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then @@ -2573,7 +2584,7 @@ begin mem_valid_in <= '1'; mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1; mem_write_data <= std_logic_vector(mem_endpoint_latch_data.res_time(1)); - mem_endpoint_data.res_time <= mem_endpoint_latch_data.res_time; + mem_endpoint_data_next.res_time <= mem_endpoint_latch_data.res_time; -- Memory Flow Control Guard if (mem_ready_in = '1') then -- DONE @@ -2807,7 +2818,7 @@ begin -- Reset Read counter if (reset = '1' or reset_read_cnt = '1') then read_cnt <= (others => '0'); - -- Increment read counter each time rd_user is high + -- Increment read counter each time rd_sig is high elsif (rd_sig = '1') then read_cnt <= read_cnt + 1; end if; @@ -2822,6 +2833,7 @@ begin return_stage <= IDLE; mem_stage <= RESET_MEMORY; seq_nr <= SEQUENCENUMBER_UNKNOWN; + next_seq_nr <= SEQUENCENUMBER_UNKNOWN; sn_latch_1 <= SEQUENCENUMBER_UNKNOWN; sn_latch_2 <= SEQUENCENUMBER_UNKNOWN; sn_latch_3 <= SEQUENCENUMBER_UNKNOWN; @@ -2838,10 +2850,13 @@ begin bitmap_pos <= 0; mem_cnt <= 0; mem_pos <= 0; + is_meta <= '0'; key_hash_rcvd <= '0'; last_word_in_latch <= '0'; stale_check <= '0'; + parameter_end <= (others => '1'); + bitmap_cnt <= (others => '0'); meta_opcode <= (others => '0'); status_info <= (others => '0'); mem_addr_base <= (others => '0'); @@ -2852,11 +2867,13 @@ begin opcode <= (others => '0'); count <= (others => '0'); key_hash <= (others => (others => '0')); + bitmap_latch <= (others => (others => '0')); else stage <= stage_next; return_stage <= return_stage_next; mem_stage <= mem_stage_next; seq_nr <= seq_nr_next; + next_seq_nr <= next_seq_nr_next; sn_latch_1 <= sn_latch_1_next; sn_latch_2 <= sn_latch_2_next; sn_latch_3 <= sn_latch_3_next; @@ -2876,6 +2893,8 @@ begin is_meta <= is_meta_next; key_hash_rcvd <= key_hash_rcvd_next; last_word_in_latch <= last_word_in_latch_next; + parameter_end <= parameter_end_next; + bitmap_cnt <= bitmap_cnt_next; stale_check <= stale_check_next; meta_opcode <= meta_opcode_next; status_info <= status_info_next; @@ -2887,6 +2906,7 @@ begin opcode <= opcode_next; count <= count_next; key_hash <= key_hash_next; + bitmap_latch <= bitmap_latch_next; end if; end if; end process; diff --git a/src/rtps_test_package.vhd b/src/rtps_test_package.vhd index e41b6ff..2b89b28 100644 --- a/src/rtps_test_package.vhd +++ b/src/rtps_test_package.vhd @@ -120,6 +120,7 @@ package rtps_test_package is count : std_logic_vector(COUNT_WIDTH-1 downto 0); writerSN : SEQUENCENUMBER_TYPE; fragmentNumberState : FRAGMENTNUMBER_SET_TYPE; + inlineQos : TEST_PACKET_TYPE; data : TEST_PACKET_TYPE; fragmentStartingNumber : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); fragmentsInSubmessage : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0); @@ -211,6 +212,19 @@ package rtps_test_package is constant DEFAULT_ENDPOINT_DATA : ENDPOINT_DATA_TYPE; -- Deferred to Package Body type ENDPOINT_DATA_ARRAY_TYPE is array (natural range <>) of ENDPOINT_DATA_TYPE; + type CACHE_CHANGE_TYPE is record + littleEndian : std_logic; + serialized_key : boolean; + kind : CACHE_CHANGE_KIND_TYPE; + writer_guid : GUID_TYPE; + instance : INSTANCE_HANDLE_TYPE; + seq_nr : SEQUENCENUMBER_TYPE; + src_timestamp : TIME_TYPE; + payload : TEST_PACKET_TYPE; + end record; + + constant DEFAULT_CACHE_CHANGE : CACHE_CHANGE_TYPE; -- Defeered to Package Body + function test_memory_match (A,B : TEST_MEMORY_TYPE) return boolean; function to_string (input : TEST_MEMORY_TYPE) return string; @@ -224,6 +238,9 @@ package rtps_test_package is procedure gen_rtps_handler_out(ref : in RTPS_SUBMESSAGE_TYPE; participant : PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE); procedure gen_rtps_handler_out(ref : in RTPS_SUBMESSAGE_TYPE; endpoint : ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE); + function gen_cache_change(ref : RTPS_SUBMESSAGE_TYPE) return CACHE_CHANGE_TYPE; + procedure gen_add_cache_change_dds(ref : in CACHE_CHANGE_TYPE; lifespan_deadline : in TIME_TYPE; pos : in natural; output : inout TEST_PACKET_TYPE); + procedure gen_participant_data( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE); procedure gen_participant_data( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer); function gen_participant_mem_frame (ref : PARTICIPANT_DATA_TYPE) return TEST_PARTICIPANT_MEMORY_FRAME_TYPE; @@ -243,6 +260,12 @@ package rtps_test_package is procedure gen_sentinel(output : inout TEST_PACKET_TYPE); procedure gen_parameter(pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); data : in TEST_PACKET_TYPE; output : inout TEST_PACKET_TYPE); + procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; lifespan : DURATION_TYPE; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer); + procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer); + procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; lifespan : DURATION_TYPE; output : inout TEST_PACKET_TYPE); + procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; output : inout TEST_PACKET_TYPE); + + procedure gen_rand_loc(RV : inout RandomPType; ret : out LOCATOR_TYPE); procedure gen_rand_entityid(RV : inout RandomPType; reader : boolean; ret : out std_logic_vector(ENTITYID_WIDTH-1 downto 0)); function int(n : integer; width : natural) return std_logic_vector; @@ -382,6 +405,7 @@ package body rtps_test_package is octetsToInlineQos => int(16, SUBMESSAGE_LENGTH_WIDTH), writerSN => FIRST_SEQUENCENUMBER, fragmentNumberState => DEFAULT_FRAGMENTNUMBER_SET, + inlineQos => EMPTY_TEST_PACKET, data => EMPTY_TEST_PACKET, fragmentStartingNumber => int(1,CDR_LONG_WIDTH), fragmentsInSubmessage => int(1,CDR_SHORT_WIDTH), @@ -485,6 +509,17 @@ package body rtps_test_package is nr => 0 ); + constant DEFAULT_CACHE_CHANGE : CACHE_CHANGE_TYPE := ( + littleEndian => '0', + serialized_key => FALSE, + kind => ALIVE, + writer_guid => GUID_UNKNOWN, + instance => HANDLE_NIL, + seq_nr => SEQUENCENUMBER_UNKNOWN, + src_timestamp => TIME_INVALID, + payload => EMPTY_TEST_PACKET + ); + -- *PACKAGE INTERNAL HELPER FUNCTIONS* procedure store_byte(in_off : in natural range 0 to 3; input : in std_logic_vector(WORD_WIDTH-1 downto 0); out_off : in natural range 0 to 3; output : inout TEST_PACKET_TYPE) is @@ -761,6 +796,16 @@ package body rtps_test_package is end if; end loop; end if; + -- INLINE QOS + if (ref.inlineQos.length > 0) then + for i in 0 to (ref.inlineQos.length*4)-1 loop + store_byte((i+tmp) mod 4, ref.inlineQos.data(i/4), i mod 4, output); + if ((i+tmp) mod 4 = 3) then + output.length := output.length + 1; + output.data(output.length) := (others => '0'); + end if; + end loop; + end if; -- DATA if (ref.data.length > 0) then for i in 0 to (ref.data.length*4)-1 loop @@ -898,6 +943,13 @@ package body rtps_test_package is output.data(output.length) := std_logic_vector(ts(1)); output.length := output.length + 1; end if; + -- INLINE QOS + if (ref.inlineQos.length > 0) then + for i in 0 to ref.inlineQos.length-1 loop + output.data(output.length) := ref.inlineQos.data(i); + output.length := output.length + 1; + end loop; + end if; -- DATA PAYLOAD if (ref.data.length > 0) then for i in 0 to ref.data.length-1 loop @@ -959,6 +1011,74 @@ package body rtps_test_package is gen_rtps_handler_out(ref, get_loc(endpoint.participant, TRUE), TRUE, TIME_INVALID, endpoint.participant.guidPrefix, output); end procedure; + function gen_cache_change(ref : RTPS_SUBMESSAGE_TYPE) return CACHE_CHANGE_TYPE is + variable ret : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + begin + assert(ref.submessageID = SID_DATA) report "Cache Change can only be derived from DATA Submessages." severity FAILURE; + + ret.seq_nr := ref.writerSN; + ret.payload := ref.data; + ret.serialized_key := TRUE when (ref.flags(SUBMESSAGE_KEY_FLAG_POS) = '1') else FALSE; + return ret; + end function; + + procedure gen_add_cache_change_dds(ref : in CACHE_CHANGE_TYPE; lifespan_deadline : in TIME_TYPE; pos : in natural; output : inout TEST_PACKET_TYPE) is + begin + -- Status Info + output.data(output.length) := (others => '0'); + case (ref.kind) is + when ALIVE_FILTERED => + output.data(output.length)(SSI_FILTERED_FLAG) := '1'; + when NOT_ALIVE_DISPOSED => + output.data(output.length)(SSI_DISPOSED_FLAG) := '1'; + when NOT_ALIVE_UNREGISTERED => + output.data(output.length)(SSI_UNREGISTERED_FLAG) := '1'; + when others => + null; + end case; + if (ref.payload.length > 0 and (not ref.serialized_key)) then + output.data(output.length)(SSI_PAYLOAD_FLAG) := '1'; + end if; + if (ref.instance /= HANDLE_NIL) then + output.data(output.length)(SSI_KEY_HASH_FLAG) := '1'; + end if; + output.length := output.length + 1; + -- Source Timestamp + output.data(output.length) := std_logic_vector(ref.src_timestamp(0)); + output.length := output.length + 1; + output.data(output.length) := std_logic_vector(ref.src_timestamp(1)); + output.length := output.length + 1; + -- Lifespan Deadline + output.data(output.length) := std_logic_vector(lifespan_deadline(0)); + output.length := output.length + 1; + output.data(output.length) := std_logic_vector(lifespan_deadline(1)); + output.length := output.length + 1; + -- Key Hash + if (ref.instance /= HANDLE_NIL) then + output.data(output.length) := ref.instance(0); + output.length := output.length + 1; + output.data(output.length) := ref.instance(1); + output.length := output.length + 1; + output.data(output.length) := ref.instance(2); + output.length := output.length + 1; + output.data(output.length) := ref.instance(3); + output.length := output.length + 1; + end if; + -- Remote Writer Endpoint Position + output.data(output.length) := std_logic_vector(to_unsigned(pos, WORD_WIDTH)); + output.length := output.length + 1; + -- Payload + -- NOTE: Do not send Serialized Key if Key Hash is available + if (ref.payload.length > 0 and (not (ref.serialized_key and ref.instance /= HANDLE_NIL))) then + for i in 0 to ref.payload.length-1 loop + output.data(output.length) := ref.payload.data(i); + output.length := output.length + 1; + end loop; + end if; + -- Mark Last Word + output.last(output.length-1) := '1'; + end procedure; + procedure gen_liveliness_assertion(participant : in PARTICIPANT_DATA_TYPE; manual : in boolean; extra_data : in TEST_PACKET_TYPE; output : inout TEST_PACKET_TYPE) is begin -- Representation Identifier & Representation Options @@ -2016,6 +2136,88 @@ package body rtps_test_package is end loop; end procedure; + procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; lifespan : in DURATION_TYPE; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer) is + begin + -- Lifespan + if (lifespan /= DEFAULT_LIFESPAN_QOS or pid = PID_LIFESPAN) then + if (pid = PID_LIFESPAN) then + assert (8+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE; + output.data(output.length) := PID_LIFESPAN & endian_swap(ref.littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH)); + else + output.data(output.length) := PID_LIFESPAN & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH)); + end if; + output.length := output.length + 1; + output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(lifespan(0))); + output.length := output.length + 1; + output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(lifespan(1))); + output.length := output.length + 1; + if (pid = PID_LIFESPAN) then + output.length := output.length + offset; + end if; + end if; + -- Status Info + if (ref.kind /= ALIVE or pid = PID_STATUS_INFO) then + if (pid = PID_STATUS_INFO) then + assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE; + output.data(output.length) := PID_STATUS_INFO & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH)); + else + output.data(output.length) := PID_STATUS_INFO & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH)); + end if; + output.length := output.length + 1; + output.data(output.length) := (others => '0'); + case (ref.kind) is + when ALIVE_FILTERED => + output.data(output.length)(SSI_FILTERED_FLAG) := '1'; + when NOT_ALIVE_DISPOSED => + output.data(output.length)(SSI_DISPOSED_FLAG) := '1'; + when NOT_ALIVE_UNREGISTERED => + output.data(output.length)(SSI_UNREGISTERED_FLAG) := '1'; + when others => + null; + end case; + output.length := output.length + 1; + if (pid = PID_STATUS_INFO) then + output.length := output.length + offset; + end if; + end if; + -- Key Hash + if (ref.instance /= HANDLE_NIL or pid = PID_KEY_HASH) then + if (pid = PID_KEY_HASH) then + assert (16+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE; + output.data(output.length) := PID_KEY_HASH & endian_swap(ref.littleEndian, int(16+(offset*4),PARAMETER_LENGTH_WIDTH)); + else + output.data(output.length) := PID_KEY_HASH & endian_swap(ref.littleEndian, int(16,PARAMETER_LENGTH_WIDTH)); + end if; + output.length := output.length + 1; + output.data(output.length) := ref.instance(0); + output.length := output.length + 1; + output.data(output.length) := ref.instance(1); + output.length := output.length + 1; + output.data(output.length) := ref.instance(2); + output.length := output.length + 1; + output.data(output.length) := ref.instance(3); + output.length := output.length + 1; + if (pid = PID_KEY_HASH) then + output.length := output.length + offset; + end if; + end if; + end procedure; + + procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer) is + begin + gen_inline_qos(ref,DEFAULT_LIFESPAN_QOS,output,pid,offset); + end procedure; + + procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; lifespan : DURATION_TYPE; output : inout TEST_PACKET_TYPE) is + begin + gen_inline_qos(ref,lifespan,output,PID_PAD,0); + end procedure; + + procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; output : inout TEST_PACKET_TYPE) is + begin + gen_inline_qos(ref,output,PID_PAD,0); + end procedure; + function test_memory_match (A,B : TEST_MEMORY_TYPE) return boolean is begin if (A'length /= B'length) then