diff --git a/sim/L0_rtps_builtin_endpoint_test1.do b/sim/L0_rtps_builtin_endpoint_test1.do index 4ff88a2..c87213e 100644 --- a/sim/L0_rtps_builtin_endpoint_test1.do +++ b/sim/L0_rtps_builtin_endpoint_test1.do @@ -1,56 +1,56 @@ onerror {resume} quietly WaveActivateNextPane {} 0 add wave -noupdate -divider SYSTEM -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/clk -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/reset +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/clk +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/reset add wave -noupdate -divider INPUT -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/empty -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/rd -add wave -noupdate -radix hexadecimal /l0_rtps_builtin_endpoint_test2/uut/data_in -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/last_word_in -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/last_word_in_latch +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/empty +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/rd +add wave -noupdate -radix hexadecimal /l0_rtps_builtin_endpoint_test1/uut/data_in +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/last_word_in +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/last_word_in_latch add wave -noupdate -divider OUTPUT -add wave -noupdate -group ENDPOINTS /l0_rtps_builtin_endpoint_test2/uut/full_ue -add wave -noupdate -group ENDPOINTS /l0_rtps_builtin_endpoint_test2/uut/wr_ue -add wave -noupdate -group ENDPOINTS -radix hexadecimal /l0_rtps_builtin_endpoint_test2/uut/data_out_ue -add wave -noupdate -group ENDPOINTS /l0_rtps_builtin_endpoint_test2/uut/last_word_out_ue -add wave -noupdate -group {RTPS OUT} /l0_rtps_builtin_endpoint_test2/uut/full_ro -add wave -noupdate -group {RTPS OUT} /l0_rtps_builtin_endpoint_test2/uut/wr_ro -add wave -noupdate -group {RTPS OUT} -radix hexadecimal /l0_rtps_builtin_endpoint_test2/uut/data_out_ro -add wave -noupdate -group {RTPS OUT} /l0_rtps_builtin_endpoint_test2/uut/last_word_out_ro +add wave -noupdate -group ENDPOINTS /l0_rtps_builtin_endpoint_test1/uut/full_ue +add wave -noupdate -group ENDPOINTS /l0_rtps_builtin_endpoint_test1/uut/wr_ue +add wave -noupdate -group ENDPOINTS -radix hexadecimal /l0_rtps_builtin_endpoint_test1/uut/data_out_ue +add wave -noupdate -group ENDPOINTS /l0_rtps_builtin_endpoint_test1/uut/last_word_out_ue +add wave -noupdate -group {RTPS OUT} /l0_rtps_builtin_endpoint_test1/uut/full_ro +add wave -noupdate -group {RTPS OUT} /l0_rtps_builtin_endpoint_test1/uut/wr_ro +add wave -noupdate -group {RTPS OUT} -radix hexadecimal /l0_rtps_builtin_endpoint_test1/uut/data_out_ro +add wave -noupdate -group {RTPS OUT} /l0_rtps_builtin_endpoint_test1/uut/last_word_out_ro add wave -noupdate -divider TESTBENCH -add wave -noupdate /l0_rtps_builtin_endpoint_test2/start -add wave -noupdate /l0_rtps_builtin_endpoint_test2/stim_stage -add wave -noupdate /l0_rtps_builtin_endpoint_test2/stimulus.length -add wave -noupdate /l0_rtps_builtin_endpoint_test2/cnt_stim -add wave -noupdate /l0_rtps_builtin_endpoint_test2/packet_sent -add wave -noupdate /l0_rtps_builtin_endpoint_test2/SB.ItemNumberVar +add wave -noupdate /l0_rtps_builtin_endpoint_test1/start +add wave -noupdate /l0_rtps_builtin_endpoint_test1/stim_stage +add wave -noupdate /l0_rtps_builtin_endpoint_test1/stimulus.length +add wave -noupdate /l0_rtps_builtin_endpoint_test1/cnt_stim +add wave -noupdate /l0_rtps_builtin_endpoint_test1/packet_sent +add wave -noupdate /l0_rtps_builtin_endpoint_test1/SB.ItemNumberVar add wave -noupdate -divider {MAIN FSM} -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/stage -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/stage_next -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/cnt -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/endpoint_mask -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/participant_match +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/stage +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/stage_next +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/cnt +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/endpoint_mask +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/participant_match add wave -noupdate -divider {MEM FSM} -add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test2/uut/mem_opcode -add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test2/uut/mem_op_start -add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test2/uut/mem_op_done -add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test2/uut/mem_stage -add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test2/uut/mem_stage_next -add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test2/uut/mem_cnt -add wave -noupdate -group MEM_FSM -radix unsigned /l0_rtps_builtin_endpoint_test2/uut/mem_addr_base +add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test1/uut/mem_opcode +add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test1/uut/mem_op_start +add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test1/uut/mem_op_done +add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test1/uut/mem_stage +add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test1/uut/mem_stage_next +add wave -noupdate -group MEM_FSM /l0_rtps_builtin_endpoint_test1/uut/mem_cnt +add wave -noupdate -group MEM_FSM -radix unsigned /l0_rtps_builtin_endpoint_test1/uut/mem_addr_base add wave -noupdate -divider GUARD -add wave -noupdate -radix unsigned /l0_rtps_builtin_endpoint_test2/uut/read_cnt -add wave -noupdate -radix unsigned /l0_rtps_builtin_endpoint_test2/uut/parameter_end -add wave -noupdate /l0_rtps_builtin_endpoint_test2/uut/parse_prc/rd_guard +add wave -noupdate -radix unsigned /l0_rtps_builtin_endpoint_test1/uut/read_cnt +add wave -noupdate -radix unsigned /l0_rtps_builtin_endpoint_test1/uut/parameter_end +add wave -noupdate /l0_rtps_builtin_endpoint_test1/uut/parse_prc/rd_guard add wave -noupdate -divider MEMORY -add wave -noupdate -group MEMORY -radix unsigned /l0_rtps_builtin_endpoint_test2/uut/mem_ctrl_inst/ram_inst/addr -add wave -noupdate -group MEMORY /l0_rtps_builtin_endpoint_test2/uut/mem_ctrl_inst/ram_inst/wen -add wave -noupdate -group MEMORY /l0_rtps_builtin_endpoint_test2/uut/mem_ctrl_inst/ram_inst/ren -add wave -noupdate -group MEMORY -radix hexadecimal /l0_rtps_builtin_endpoint_test2/uut/mem_ctrl_inst/ram_inst/wr_data -add wave -noupdate -group MEMORY -radix hexadecimal /l0_rtps_builtin_endpoint_test2/uut/mem_ctrl_inst/ram_inst/rd_data +add wave -noupdate -group MEMORY -radix unsigned /l0_rtps_builtin_endpoint_test1/uut/mem_ctrl_inst/ram_inst/addr +add wave -noupdate -group MEMORY /l0_rtps_builtin_endpoint_test1/uut/mem_ctrl_inst/ram_inst/wen +add wave -noupdate -group MEMORY /l0_rtps_builtin_endpoint_test1/uut/mem_ctrl_inst/ram_inst/ren +add wave -noupdate -group MEMORY -radix hexadecimal /l0_rtps_builtin_endpoint_test1/uut/mem_ctrl_inst/ram_inst/wr_data +add wave -noupdate -group MEMORY -radix hexadecimal /l0_rtps_builtin_endpoint_test1/uut/mem_ctrl_inst/ram_inst/rd_data add wave -noupdate -divider MISC -add wave -noupdate -radix unsigned /l0_rtps_builtin_endpoint_test2/uut/seq_nr +add wave -noupdate -radix unsigned /l0_rtps_builtin_endpoint_test1/uut/seq_nr TreeUpdate [SetDefaultTree] WaveRestoreCursors {Begin {63775000 ps} 1} {Error {66975000 ps} 1} {Cursor {33675000 ps} 0} quietly wave cursor active 1 diff --git a/src/TEMPLATE_user_config.vhd b/src/TEMPLATE_user_config.vhd index 43c9254..46b1aed 100644 --- a/src/TEMPLATE_user_config.vhd +++ b/src/TEMPLATE_user_config.vhd @@ -18,6 +18,8 @@ package user_config is constant MAX_REMOTE_PARTICIPANTS : natural := 50; -- Maximum number of supported remote Endpoints (Affects generated Memory Size) constant MAX_REMOTE_ENDPOINTS : natural := 50; + -- If Multicast Locators should be used instead of Unicast Locators + constant PREFER_MULTICAST_LOCATORS : boolean := FALSE; -- 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"; diff --git a/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1_mc.vhd b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1_mc.vhd new file mode 100644 index 0000000..9c83d13 --- /dev/null +++ b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1_mc.vhd @@ -0,0 +1,737 @@ +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 matching of remote participants. Due to the fact, that participant matching does not have an immediate effect visible to the outside, +-- this testbench is using external names to access the memory of the rtps_builtin_endpoint directly and check the contents at the supposed participant locations. +-- This testbench covers following: +-- * Mathing compatible Participants +-- * Ignoring incompatible Participants +-- * Unmatching previously matched Participants (Due to incompatibility) +-- * Unmatching previously matched Participants (Due to Unregister/Dispose Status Updates) +-- * Update data of previously matched Participant +-- * Big/Little Endian Participant Data +-- * Memory Full Behaviour +-- * PREFER_MULTICAST = TRUE + + +entity L0_rtps_builtin_endpoint_test1_mc is +end entity; + +architecture testbench of L0_rtps_builtin_endpoint_test1_mc is + + -- *CONSTANT DECLARATION* + constant MAX_REMOTE_PARTICIPANTS : natural := 3; + + -- *TYPE DECLARATION* + type TEST_STAGE_TYPE is (IDLE, BUSY); + type TEST_RAM_TYPE is array (0 to (MAX_REMOTE_PARTICIPANTS*PARTICIPANT_FRAME_SIZE)-1) of std_logic_vector(WORD_WIDTH-1 downto 0); + + -- *SIGNAL DECLARATION* + signal clk, in_empty, rd_sig, last_word_in, last_word_out_ue: std_logic := '0'; + signal reset : std_logic := '1'; --TODO: Do that in all testbenches + signal wr_ue, full_ue : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0'); + signal data_in, data_out_ue : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal stim_stage : TEST_STAGE_TYPE := IDLE; + shared variable stimulus, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET; + signal packet_sent : std_logic := '0'; + signal cnt_stim : natural := 0; + signal start : std_logic := '0'; + shared variable SB_out : work.ScoreBoardPkg_builtin_endpoint.ScoreBoardPType; + shared variable SB_mem : work.ScoreBoardPkg_MemoryTest.ScoreBoardPType; + signal stim_done, mem_check_done, check_done, test_done : std_logic := '0'; + + -- *FUNCTION DECLARATION* + procedure wait_on_complete is + begin + if (test_done /= '1') then + wait until test_done = '1'; + end if; + end procedure; + + procedure wait_on_mem_check is + begin + if (mem_check_done /= '1') then + wait until mem_check_done = '1'; + end if; + end procedure; + + procedure wait_on_sent is + begin + wait until rising_edge(packet_sent); + end procedure; + +begin + + -- Unit Under Test + uut : entity work.rtps_builtin_endpoint(arch) + generic map ( + MAX_REMOTE_PARTICIPANTS => MAX_REMOTE_PARTICIPANTS, + PREFER_MULTICAST => TRUE + ) + port map ( + -- SYSTEM + clk => clk, + reset => reset, + time => TIME_ZERO, + -- FROM RTPS HANDLER + empty => in_empty or packet_sent, + rd => rd_sig, + data_in => data_in, + last_word_in => last_word_in, + -- FROM USER ENDPOINT + alive => (others => '0'), + -- TO USER ENDPOINT + full_ue => full_ue, + wr_ue => wr_ue, + data_out_ue => data_out_ue, + last_word_out_ue => last_word_out_ue, + -- RTPS OUTPUT + full_ro => '0', + wr_ro => open, + data_out_ro => open, + last_word_out_ro => open + ); + + stimulus_prc : process + variable rtps_sub : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE; + variable RV : RandomPType; + variable participant : PARTICIPANT_DATA_TYPE := DEFAULT_PARTICIPANT_DATA; + variable m0, m1, m2 : PARTICIPANT_DATA_TYPE := DEFAULT_PARTICIPANT_DATA; + variable p0, p1, p2, p3 : GUIDPREFIX_TYPE; + + -- 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; + + procedure push_reference is + variable wr_sig : std_logic_vector(NUM_ENDPOINTS-1 downto 0) := (others => '1'); + begin + gen_participant_match_frame(participant, reference); + for i in 0 to reference.length-1 loop + SB_out.Push(wr_sig & reference.last(i) & reference.data(i)); + end loop; + reference := EMPTY_TEST_PACKET; + end procedure; + + 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_test is + begin + start <= '1'; + wait until rising_edge(clk); + start <= '0'; + wait until rising_edge(clk); + end procedure; + begin + + SetAlertLogName("rtps_builtin_endpoint - Level 0 - (Prefer Multicast) - Participant Matching"); + SetAlertEnable(FAILURE, TRUE); + SetAlertEnable(ERROR, TRUE); + SetAlertEnable(WARNING, TRUE); + SetLogEnable(DEBUG, FALSE); + SetLogEnable(PASSED, FALSE); + SetLogEnable(INFO, TRUE); + RV.InitSeed(RV'instance_name); + + -- NOTE: A single incremented Sequence Number is used for all the Participants. This should not be a problem for + -- the best effort participant data, as long as it is monotonically increasing. + rtps_sub := DEFAULT_RTPS_SUBMESSAGE; + rtps_sub.submessageID := SID_DATA; + rtps_sub.writerId := ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER; + rtps_sub.readerId := ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR; + rtps_sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1'; + + p0 := gen_rand_guid_prefix; + p1 := gen_rand_guid_prefix; + p2 := gen_rand_guid_prefix; + p3 := gen_rand_guid_prefix; + + + Log("Initiating Test", INFO); + start <= '0'; + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + -- MEMORY STATE: -/0,1,2 + + Log("Match Participant 0 [Compatible]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p0; + participant.nr := 0; + participant.match := MATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + m0 := participant; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + SB_mem.Push(gen_participant_mem_frame(participant)); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 0(p0)/1,2 + + Log("Match Participant 1 [Compatible, Little Endian]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p1; + participant.nr := 1; + participant.littleEndian := '1'; + participant.match := MATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + m1 := participant; + report "DOMAIN_ID: " & to_hstring(DOMAIN_ID); + report "PARTICIPANT DOMAIN_ID: " & to_hstring(participant.domainId); + gen_participant_data(participant, rtps_sub.data); + gen_sentinel('1', rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + SB_mem.Push(gen_participant_mem_frame(participant)); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 1(p1),0(p0)/2 + + Log("Ignore Participant 2 [Incompatible Domain ID]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p2; + participant.nr := 2; + participant.domainId := int(2, DOMAIN_ID_WIDTH); + participant.match := UNMATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 1(p1),0(p0)/2 + + Log("Unmatch Participant 0 [Incompatible Domain ID]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p0; + participant.nr := 0; + participant.domainId := int(2, DOMAIN_ID_WIDTH); + participant.match := UNMATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + m0 := DEFAULT_PARTICIPANT_DATA; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + push_reference; + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 1(p1)/0,2 + + + Log("Ignore Participant 2 [Incompatible Domain TAG]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p2; + participant.nr := 2; + participant.domainTag := DEFAULT_DOMAIN_TAG; + participant.match := UNMATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 1(p1)/0,2 + + Log("Unmatch Participant 1 [Incompatible Domain TAG]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p1; + participant.nr := 1; + participant.domainTag := DEFAULT_DOMAIN_TAG; + participant.match := UNMATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + push_reference; + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: -/1,0,2 + + Log("Match Participant 0 [+Unicast Metatraffic Locator]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p0; + participant.nr := 1; + participant.match := MATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.metatrafficUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + m1 := participant; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + SB_mem.Push(gen_participant_mem_frame(participant)); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 1(p0)/0,2 + + Log("Match Participant 1 [ALL Values Set non default]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p1; + participant.nr := 0; + participant.vendorId := RV.RandSlv(VENDORID_WIDTH); + participant.expectsInlineQoS(0) := '1'; + participant.leaseDuration := gen_duration(5,500); + participant.manualLivelinessCount := int(6, CDR_LONG_WIDTH); + participant.builtinEndpointQoS(0) := '1'; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.defaultMulticastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.metatrafficUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.metatrafficMulticastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.match := MATCH; + participant.PREFER_MULTICAST := TRUE; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + m0 := participant; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + SB_mem.Push(gen_participant_mem_frame(participant)); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 0(p1),1(p0)/2 + + Log("Ignore Participant 2 [Incompatible Protocol Version]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p2; + participant.nr := 2; + participant.protocolVersion := PROTOCOLVERSION_1_0; + participant.match := UNMATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 0(p1),1(p0)/2 + + Log("Unmatch Participant 0 [Incompatible Protocol Version]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p0; + participant.nr := 0; + participant.protocolVersion := PROTOCOLVERSION_1_0; + participant.match := UNMATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + m1 := DEFAULT_PARTICIPANT_DATA; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + push_reference; + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 0(p1)/1,2 + + Log("Match Participant 0 [Compatible, Only Subscribers]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p0; + participant.nr := 1; + participant.match := MATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + m1 := participant; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + SB_mem.Push(gen_participant_mem_frame(participant)); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 1(p0),0(p1)/2 + + Log("Match Participant 2 [Compatible, Only Publishers]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p2; + participant.nr := 2; + participant.match := MATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + m2 := participant; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + SB_mem.Push(gen_participant_mem_frame(participant)); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 2(p2),1(p0),0(p1)/- + + Log("Update Participant 1 [Valid/Invalid Default/Metatraffic Locators]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p1; + participant.nr := 0; + participant.match := MATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(4,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, 1 => gen_rand_loc_2, 2 => gen_rand_loc_2, 3 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.defaultUnicastLocatorList.locator(1).kind := LOCATOR_KIND_UDPv6; + participant.defaultUnicastLocatorList.locator(2).addr := (others => '0'); + participant.defaultUnicastLocatorList.locator(3).portn := (others => '0'); + participant.defaultMulticastLocatorList := (numLocators => int(4,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, 1 => gen_rand_loc_2, 2 => gen_rand_loc_2, 3 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.defaultMulticastLocatorList.locator(1).kind := LOCATOR_KIND_UDPv6; + participant.defaultMulticastLocatorList.locator(2).portn := (others => '0'); + participant.defaultMulticastLocatorList.locator(3).addr := (others => '0'); + participant.metatrafficUnicastLocatorList := (numLocators => int(4,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, 1 => gen_rand_loc_2, 2 => gen_rand_loc_2, 3 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.metatrafficUnicastLocatorList.locator(1).kind := LOCATOR_KIND_UDPv6; + participant.metatrafficUnicastLocatorList.locator(2).addr := (others => '0'); + participant.metatrafficUnicastLocatorList.locator(3).portn := (others => '0'); + participant.metatrafficMulticastLocatorList := (numLocators => int(4,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, 1 => gen_rand_loc_2, 2 => gen_rand_loc_2, 3 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.metatrafficMulticastLocatorList.locator(1).kind := LOCATOR_KIND_UDPv6; + participant.metatrafficMulticastLocatorList.locator(2).portn := (others => '0'); + participant.metatrafficMulticastLocatorList.locator(3).addr := (others => '0'); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + m0 := participant; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + SB_mem.Push(gen_participant_mem_frame(participant)); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 2(p2),1(p0),0(p1)/- + + Log("Ignore Participant 3 [Memory Full]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p3; + participant.nr := 0; + participant.match := MATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1'; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + -- Re-Check Memory + SB_mem.Push(gen_participant_mem_frame(m0)); + SB_mem.Push(gen_participant_mem_frame(m1)); + SB_mem.Push(gen_participant_mem_frame(m2)); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + + Log("Unmatch Participant 2 [No Endpoints]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p2; + participant.nr := 2; + participant.match := UNMATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + m2 := DEFAULT_PARTICIPANT_DATA; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + push_reference; + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 1(p0),0(p1)/2 + + Log("Unmatch Participant 0 [Incompatible Built-in Endpoints]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p0; + participant.nr := 0; + participant.match := UNMATCH; + participant.PREFER_MULTICAST := TRUE; + participant.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR)); + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1'; + participant.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1'; + m1 := DEFAULT_PARTICIPANT_DATA; + gen_participant_data(participant, rtps_sub.data); + gen_sentinel(rtps_sub.data); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + push_reference; + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.data := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + -- MEMORY STATE: 0(p1)/1,2 + + Log("Unmatch Participant 1 [Unregister/Dispose]", INFO); + participant := DEFAULT_PARTICIPANT_DATA; + participant.guidPrefix := p1; + participant.nr := 0; + participant.match := UNMATCH; + participant.PREFER_MULTICAST := TRUE; + m0 := DEFAULT_PARTICIPANT_DATA; + rtps_sub.flags := (SUBMESSAGE_INLINE_QOS_FLAG_POS => '1', others => '0'); + gen_inline_qos(NOT_ALIVE_DISPOSED, to_key_hash(to_guid(participant.guidPrefix,ENTITYID_PARTICIPANT)), rtps_sub.inlineQos); + gen_sentinel(rtps_sub.inlineQos); + gen_rtps_handler_out(rtps_sub, participant, stimulus); + push_reference; + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + rtps_sub.inlineQos := EMPTY_TEST_PACKET; + rtps_sub.writerSN := rtps_sub.writerSN + 1; + rtps_sub.flags := (SUBMESSAGE_DATA_FLAG_POS => '1', others => '0'); + -- MEMORY STATE: -/0,1,2 + + stim_done <= '1'; + wait_on_complete; + 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; + + in_empty_prc : process + begin + in_empty <= '0'; + wait until rd_sig = '1'; + wait until rising_edge(clk); + in_empty <= '1'; + wait until rising_edge(clk); + end process; + + endpoint_full_prc : process + begin + full_ue <= (others => '0'); + wait until (or wr_ue) = '1'; + wait until rising_edge(clk); + full_ue <= (others => '1'); + wait until rising_edge(clk); + end process; + + alert_prc : process(all) + begin + if rising_edge(clk) then + alertif(in_empty = '1' and rd_sig = '1', "Input FIFO read signal high while empty signal high", ERROR); + alertif(full_ue /= (0 to NUM_ENDPOINTS-1 => '0') and (wr_ue /= (0 to NUM_ENDPOINTS-1 => '0')), "Endpoint FIFO write signal high while full signal high", ERROR); + end if; + end process; + + input_prc : process(all) + begin + data_in <= stimulus.data(cnt_stim); + last_word_in <= stimulus.last(cnt_stim); + + if rising_edge(clk) then + if (reset = '1') then + cnt_stim <= 0; + stim_stage <= IDLE; + packet_sent <= '1'; + else + case (stim_stage) is + when IDLE => + if (start = '1' and stimulus.length /= 0) then + stim_stage <= BUSY; + packet_sent <= '0'; + end if; + when BUSY => + if (rd_sig = '1') then + if (cnt_stim = stimulus.length-1) then + stim_stage <= IDLE; + packet_sent <= '1'; + cnt_stim <= 0; + else + cnt_stim <= cnt_stim + 1; + end if; + end if; + end case; + end if; + end if; + end process; + + output_check_prc : process(all) + begin + if rising_edge(clk) then + if (wr_ue /= (0 to NUM_ENDPOINTS-1 => '0')) then + SB_out.Check(wr_ue & last_word_out_ue & data_out_ue); + end if; + if (stim_done = '1' and SB_out.empty) then + check_done <= '1'; + else + check_done <= '0'; + end if; + end if; + end process; + + done_proc : process(clk) + begin + if rising_edge(clk) then + if (stim_done = '1' and SB_mem.empty and check_done = '1') then + test_done <= '1'; + else + test_done <= '0'; + end if; + end if; + end process; + + mem_check_prc : process + alias mem is <>; + alias mem_op_done is <>; + alias idle_sig is <>; + variable reference : TEST_PARTICIPANT_MEMORY_FRAME_TYPE; + begin + mem_check_done <= '0'; + -- SAFEGUARD: (Prevent Fall-through Behavior) + if (reset /= '0') then + wait until reset = '0'; + end if; + -- Wait for Packet to be sent + wait until rising_edge(packet_sent); + -- Wait for UUT IDLE state + if (idle_sig /= '1') then + wait until idle_sig = '1'; + end if; + -- Wait for ongoing memory operation + if (mem_op_done /= '1') then + wait until mem_op_done = '1'; + end if; + while (not SB_mem.empty) loop + SB_mem.Pop(reference); + for i in 0 to reference'length-1 loop + AffirmIf(?? (mem(reference(i).addr) ?= reference(i).data), "Address: " & integer'image(reference(i).addr) & " Received: " & to_hstring(mem(reference(i).addr)) & " Expected: " & to_hstring(reference(i).data)); + end loop; + end loop; + -- Toggle High for one clock cycle + mem_check_done <= '1'; + wait until rising_edge(clk); + 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/Level_0/L0_rtps_builtin_endpoint_test1.vhd b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1_uc.vhd similarity index 99% rename from src/Tests/Level_0/L0_rtps_builtin_endpoint_test1.vhd rename to src/Tests/Level_0/L0_rtps_builtin_endpoint_test1_uc.vhd index d3be673..a5e8bc4 100644 --- a/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1.vhd +++ b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1_uc.vhd @@ -20,12 +20,13 @@ use work.rtps_test_package.all; -- * Update data of previously matched Participant -- * Big/Little Endian Participant Data -- * Memory Full Behaviour +-- * PREFER_MULTICAST = FALSE -entity L0_rtps_builtin_endpoint_test1 is +entity L0_rtps_builtin_endpoint_test1_uc is end entity; -architecture testbench of L0_rtps_builtin_endpoint_test1 is +architecture testbench of L0_rtps_builtin_endpoint_test1_uc is -- *CONSTANT DECLARATION* constant MAX_REMOTE_PARTICIPANTS : natural := 3; @@ -140,7 +141,7 @@ begin end procedure; begin - SetAlertLogName("rtps_builtin_endpoint - Level 0 - Participant Matching"); + SetAlertLogName("rtps_builtin_endpoint - Level 0 - (Prefer Unicast) - Participant Matching"); SetAlertEnable(FAILURE, TRUE); SetAlertEnable(ERROR, TRUE); SetAlertEnable(WARNING, TRUE); diff --git a/src/Tests/Level_2/L2_Testbench_Lib2.vhd b/src/Tests/Level_2/L2_Testbench_Lib2.vhd index 6d0c17d..e49478c 100644 --- a/src/Tests/Level_2/L2_Testbench_Lib2.vhd +++ b/src/Tests/Level_2/L2_Testbench_Lib2.vhd @@ -247,7 +247,8 @@ begin rtps_builtin_endpoint_w_inst : entity Testbench_Lib2.rtps_builtin_endpoint(arch) generic map ( - MAX_REMOTE_PARTICIPANTS => 5 + MAX_REMOTE_PARTICIPANTS => 5, + PREFER_MULTICAST => PREFER_MULTICAST_LOCATORS ) port map ( clk => clk, diff --git a/src/Tests/Level_2/L2_Testbench_Lib2_config.vhd b/src/Tests/Level_2/L2_Testbench_Lib2_config.vhd index 3f40c6a..4d6c3ab 100644 --- a/src/Tests/Level_2/L2_Testbench_Lib2_config.vhd +++ b/src/Tests/Level_2/L2_Testbench_Lib2_config.vhd @@ -15,6 +15,8 @@ package user_config is constant MAX_REMOTE_PARTICIPANTS : natural := 50; -- Maximum number of supported remote Endpoints (Affects generated Memory Size) constant MAX_REMOTE_ENDPOINTS : natural := 50; + -- If Multicast Locators should be used instead of Unicast Locators + constant PREFER_MULTICAST_LOCATORS : boolean := FALSE; -- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.129] constant DEFAULT_IPv4_ADDRESS : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := x"C0A80081"; diff --git a/src/Tests/Level_2/L2_Testbench_Lib3.vhd b/src/Tests/Level_2/L2_Testbench_Lib3.vhd index d72aed6..58981fe 100644 --- a/src/Tests/Level_2/L2_Testbench_Lib3.vhd +++ b/src/Tests/Level_2/L2_Testbench_Lib3.vhd @@ -304,7 +304,8 @@ begin rtps_builtin_endpoint_r_inst : entity Testbench_Lib3.rtps_builtin_endpoint(arch) generic map ( - MAX_REMOTE_PARTICIPANTS => 5 + MAX_REMOTE_PARTICIPANTS => 5, + PREFER_MULTICAST => PREFER_MULTICAST_LOCATORS ) port map ( clk => clk, diff --git a/src/Tests/Level_2/L2_Testbench_Lib3_config.vhd b/src/Tests/Level_2/L2_Testbench_Lib3_config.vhd index 061a0af..a8e8eed 100644 --- a/src/Tests/Level_2/L2_Testbench_Lib3_config.vhd +++ b/src/Tests/Level_2/L2_Testbench_Lib3_config.vhd @@ -15,6 +15,8 @@ package user_config is constant MAX_REMOTE_PARTICIPANTS : natural := 50; -- Maximum number of supported remote Endpoints (Affects generated Memory Size) constant MAX_REMOTE_ENDPOINTS : natural := 50; + -- If Multicast Locators should be used instead of Unicast Locators + constant PREFER_MULTICAST_LOCATORS : boolean := FALSE; -- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.130] constant DEFAULT_IPv4_ADDRESS : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := x"C0A80082"; diff --git a/src/Tests/Level_2/L2_testbench_Lib4.vhd b/src/Tests/Level_2/L2_testbench_Lib4.vhd index 6a2ebcb..268280d 100644 --- a/src/Tests/Level_2/L2_testbench_Lib4.vhd +++ b/src/Tests/Level_2/L2_testbench_Lib4.vhd @@ -211,7 +211,8 @@ begin rtps_builtin_endpoint_inst : entity work.rtps_builtin_endpoint(arch) generic map ( - MAX_REMOTE_PARTICIPANTS => MAX_REMOTE_PARTICIPANTS + MAX_REMOTE_PARTICIPANTS => MAX_REMOTE_PARTICIPANTS, + PREFER_MULTICAST => PREFER_MULTICAST_LOCATORS ) port map ( clk => clk, diff --git a/src/Tests/Level_2/L2_testbench_Lib4_config.vhd b/src/Tests/Level_2/L2_testbench_Lib4_config.vhd index 4cb84b4..0d200ba 100644 --- a/src/Tests/Level_2/L2_testbench_Lib4_config.vhd +++ b/src/Tests/Level_2/L2_testbench_Lib4_config.vhd @@ -15,6 +15,8 @@ package user_config is constant MAX_REMOTE_PARTICIPANTS : natural := 50; -- Maximum number of supported remote Endpoints (Affects generated Memory Size) constant MAX_REMOTE_ENDPOINTS : natural := 50; + -- If Multicast Locators should be used instead of Unicast Locators + constant PREFER_MULTICAST_LOCATORS : boolean := FALSE; -- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.90] constant DEFAULT_IPv4_ADDRESS : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := x"C0A8005A"; diff --git a/src/Tests/Level_2/L2_testbench_Lib5.vhd b/src/Tests/Level_2/L2_testbench_Lib5.vhd index 9a8a1d4..2236c39 100644 --- a/src/Tests/Level_2/L2_testbench_Lib5.vhd +++ b/src/Tests/Level_2/L2_testbench_Lib5.vhd @@ -233,7 +233,8 @@ begin rtps_builtin_endpoint_inst : entity work.rtps_builtin_endpoint(arch) generic map ( - MAX_REMOTE_PARTICIPANTS => MAX_REMOTE_PARTICIPANTS + MAX_REMOTE_PARTICIPANTS => MAX_REMOTE_PARTICIPANTS, + PREFER_MULTICAST => PREFER_MULTICAST_LOCATORS ) port map ( clk => clk, diff --git a/src/Tests/Level_2/L2_testbench_Lib5_config.vhd b/src/Tests/Level_2/L2_testbench_Lib5_config.vhd index 496e571..7ffe612 100644 --- a/src/Tests/Level_2/L2_testbench_Lib5_config.vhd +++ b/src/Tests/Level_2/L2_testbench_Lib5_config.vhd @@ -15,6 +15,8 @@ package user_config is constant MAX_REMOTE_PARTICIPANTS : natural := 50; -- Maximum number of supported remote Endpoints (Affects generated Memory Size) constant MAX_REMOTE_ENDPOINTS : natural := 50; + -- If Multicast Locators should be used instead of Unicast Locators + constant PREFER_MULTICAST_LOCATORS : boolean := FALSE; -- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.91] constant DEFAULT_IPv4_ADDRESS : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := x"C0A8005B"; diff --git a/src/Tests/Testbench_Lib1_config.vhd b/src/Tests/Testbench_Lib1_config.vhd index 93aaddb..64e2a78 100644 --- a/src/Tests/Testbench_Lib1_config.vhd +++ b/src/Tests/Testbench_Lib1_config.vhd @@ -15,6 +15,8 @@ package user_config is constant MAX_REMOTE_PARTICIPANTS : natural := 50; -- Maximum number of supported remote Endpoints (Affects generated Memory Size) constant MAX_REMOTE_ENDPOINTS : natural := 50; + -- If Multicast Locators should be used instead of Unicast Locators + constant PREFER_MULTICAST_LOCATORS : boolean := FALSE; -- 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"; diff --git a/src/Tests/testbench.pro b/src/Tests/testbench.pro index 0303958..ebd5d2a 100644 --- a/src/Tests/testbench.pro +++ b/src/Tests/testbench.pro @@ -180,7 +180,8 @@ analyze ScoreBoard_test_memory.vhd analyze ScoreBoard_builtin_endpoint.vhd analyze Level_0/L0_rtps_handler_test1.vhd analyze Level_0/L0_rtps_handler_test2.vhd -analyze Level_0/L0_rtps_builtin_endpoint_test1.vhd +analyze Level_0/L0_rtps_builtin_endpoint_test1_uc.vhd +analyze Level_0/L0_rtps_builtin_endpoint_test1_mc.vhd analyze Level_0/L0_rtps_builtin_endpoint_test2.vhd analyze Level_0/L0_rtps_builtin_endpoint_test3.vhd analyze Level_0/L0_rtps_builtin_endpoint_test4.vhd @@ -256,7 +257,8 @@ simulate L0_rtps_handler_test1 simulate L0_rtps_handler_test2 simulate L0_rtps_out_test1 simulate L0_mem_ctrl_test1 -simulate L0_rtps_builtin_endpoint_test1 +simulate L0_rtps_builtin_endpoint_test1_uc +simulate L0_rtps_builtin_endpoint_test1_mc simulate L0_rtps_builtin_endpoint_test2 simulate L0_rtps_builtin_endpoint_test3 simulate L0_rtps_builtin_endpoint_test4 diff --git a/src/rtps_builtin_endpoint.vhd b/src/rtps_builtin_endpoint.vhd index 9e6e2c7..54b793b 100644 --- a/src/rtps_builtin_endpoint.vhd +++ b/src/rtps_builtin_endpoint.vhd @@ -12,6 +12,7 @@ use work.rtps_config_package.all; entity rtps_builtin_endpoint is generic ( + PREFER_MULTICAST : boolean := FALSE; MAX_REMOTE_PARTICIPANTS : natural := 50 ); port ( @@ -135,7 +136,7 @@ architecture arch of rtps_builtin_endpoint is -- FSM states. Explained below in detail type STAGE_TYPE is (IDLE, PACKET_HEADER, PACKET_SRC_ADDR, PACKET_SRC_ENTITYID, PACKET_SRC_GUIDPREFIX, PACKET_DEST_ENTITYID, CHECK_SRC_ENTITYID, LATCH_SEQ_NR, PROCESS_DATA, PROCESS_MESSAGE_SEQUENCE_NUMBERS, PROCESS_MESSAGE, PROCESS_GAP, PROCESS_GAP_SEQUENCE_NUMBERS, FIND_NEXT_VALID_IN_BITMAP, - PROCESS_PL, CHECK_DEFAULT, LATCH_STRING_LENGTH, COMPARE_STRING, RXO_DURABILITY, RXO_DEADLINE, RXO_LIVELINESS, RXO_LEASE_DURATION, LATCH_LEASE_DURATION, + PROCESS_PL, CHECK_DEFAULT, SELECT_LOCATOR, LATCH_STRING_LENGTH, COMPARE_STRING, RXO_DURABILITY, RXO_DEADLINE, RXO_LIVELINESS, RXO_LEASE_DURATION, LATCH_LEASE_DURATION, RXO_RELIABILITY, RXO_DESTINATION_ORDER, RXO_OWNERSHIP, RXO_PRESENTATION, RXO_PARTITION, RXO_LATENCY_BUDGET, CHECK_MAX_SIZE_SERIALIZED, MATCH_DOMAIN_ID, MATCH_PROTOCOL_VERSION, LATCH_LOCATOR, LATCH_EXPECTS_INLINE_QOS, MATCH_GUID, CHECK_REMOTE_BUILTIN_ENDPOINTS, CHECK_STATUS_INFO, PARTICIPANT_MATCH_STAGE, INFORM_ENDPOINTS_MATCH, INFORM_ENDPOINTS_UNMATCH, INFORM_ENDPOINTS_PARTICIPANT_UNMATCH, PARTICIPANT_STALE_CHECK, @@ -274,6 +275,8 @@ architecture arch of rtps_builtin_endpoint is signal is_subscriber, is_subscriber_next : std_logic; -- Signifies that the read Locator is a Metatraffic Locator signal is_meta_addr, is_meta_addr_next : std_logic; + -- Signifies that the read Locator is a Multicast Locator + signal is_multicast_addr, is_multicast_addr_next : std_logic; -- General Purpose counter signal cnt, cnt_next : natural range 0 to max(23, STRING_WORD_ARRAY_TYPE'length); -- NOTE: In order to avoid synthesizing indexing for the full range of the OUTPUT_DATA_TYPE, we explicitly use counters constrained to the actual size @@ -332,14 +335,22 @@ architecture arch of rtps_builtin_endpoint is signal string_content, string_content_next : STRING_CONTENT_TYPE; -- Reader Flags of remote Reader signal reader_flags, reader_flags_next : std_logic_vector(READER_FLAGS_WIDTH-1 downto 0); - -- Endpoint Locator IPv4 Address Latch - signal def_addr, def_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); - -- Metatraffic Locator IPv4 Address Latch - signal meta_addr, meta_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); - -- Endpoint UDPv4 Port Latch - signal def_port, def_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); - -- Metatraffic UDPv4 Port Latch - signal meta_port, meta_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); + -- Endpoint Multicast Locator IPv4 Address Latch + signal def_mc_addr, def_mc_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); + -- Metatraffic Multicast Locator IPv4 Address Latch + signal meta_mc_addr, meta_mc_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); + -- Endpoint Multicast UDPv4 Port Latch + signal def_mc_port, def_mc_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); + -- Metatraffic Multicast UDPv4 Port Latch + signal meta_mc_port, meta_mc_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); + -- Endpoint Unicast Locator IPv4 Address Latch + signal def_uc_addr, def_uc_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); + -- Metatraffic Unicast Locator IPv4 Address Latch + signal meta_uc_addr, meta_uc_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); + -- Endpoint Unicast UDPv4 Port Latch + signal def_uc_port, def_uc_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); + -- Metatraffic Unicast UDPv4 Port Latch + signal meta_uc_port, meta_uc_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); -- Participant Lease Duration Latch signal lease_duration, lease_duration_next : DURATION_TYPE; -- General Purpose Long latch @@ -436,6 +447,16 @@ architecture arch of rtps_builtin_endpoint is alias gap_list_end : SEQUENCENUMBER_TYPE is sn_latch_3; alias gap_list_end_next : SEQUENCENUMBER_TYPE is sn_latch_3_next; + -- TARGET LOCATOR + alias def_addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) is def_uc_addr; + alias def_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) is def_uc_addr_next; + alias meta_addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) is meta_uc_addr; + alias meta_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) is meta_uc_addr_next; + alias def_port : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) is def_uc_port; + alias def_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) is def_uc_port_next; + alias meta_port : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) is meta_uc_port; + alias meta_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) is meta_uc_port_next; + --*****FUNCTION DECLARATION***** -- Helper function to convert BITMAP_TYPE to std_logic_vector @@ -565,6 +586,7 @@ begin -- PARTICIPANT_STALE_CHECK Check memory for remote stale Participant Entries (Lease Duration Exceeded, HEARTBEAT/ACKNACK timeout passed) and take appropriate action. -- PROCESS_PL Parse RTPS Parameter List -- CHECK_DEFAULT Match local endpoints against non-received QoS (default values) of remote + -- SELECT_LOCATOR Select the appropriate Locator (in respect to configured defaults and generics) -- LATCH_STRING_LENGTH Store String Length -- COMPARE_STRING Compare string to constants depending on string contents. -- MATCH_GUID Compare GUID Prefix to source GUID Prefix of Packet @@ -628,11 +650,16 @@ begin participant_match_next <= participant_match; is_subscriber_next <= is_subscriber; lease_duration_next <= lease_duration; - def_addr_next <= def_addr; - meta_addr_next <= meta_addr; - def_port_next <= def_port; - meta_port_next <= meta_port; + def_mc_addr_next <= def_mc_addr; + def_uc_addr_next <= def_uc_addr; + meta_mc_addr_next <= meta_mc_addr; + meta_uc_addr_next <= meta_uc_addr; + def_mc_port_next <= def_mc_port; + def_uc_port_next <= def_uc_port; + meta_mc_port_next <= meta_mc_port; + meta_uc_port_next <= meta_uc_port; is_meta_addr_next <= is_meta_addr; + is_multicast_addr_next <= is_multicast_addr; cnt_next <= cnt; reader_flags_next <= reader_flags; stale_check_next <= stale_check; @@ -767,10 +794,14 @@ begin stage_next <= PACKET_HEADER; -- Reset Latches - def_addr_next <= (others => '0'); - meta_addr_next <= DEFAULT_IPv4_META_ADDRESS; - def_port_next <= (others => '0'); - meta_port_next <= META_IPv4_MULTICAST_PORT; + meta_mc_addr_next <= IPv4_ADDRESS_INVALID; + meta_uc_addr_next <= IPv4_ADDRESS_INVALID; + def_mc_addr_next <= IPv4_ADDRESS_INVALID; + def_uc_addr_next <= IPv4_ADDRESS_INVALID; + meta_mc_port_next <= UDP_PORT_INVALID; + meta_uc_port_next <= UDP_PORT_INVALID; + def_mc_port_next <= UDP_PORT_INVALID; + def_uc_port_next <= UDP_PORT_INVALID; lease_duration_next <= DEFAULT_PARTICIPANT_LEASE_DURATION; reader_flags_next <= (READER_EXPECTS_INLINE_QOS_FLAG => DEFAULT_EXPECTS_INLINE_QOS, READER_EXPECTS_HISTORICAL_DATA_FLAG => DEFAULT_EXPECTS_HISTORICAL_DATA_FLAG, READER_IS_BEST_EFFORT_FLAG => DEFAULT_IS_BEST_EFFORT_FLAG, others => '0'); rcvd_next <= (others => '0'); @@ -2025,7 +2056,9 @@ begin if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; + is_meta_addr_next <= '0'; + is_multicast_addr_next <= '0'; end if; when PID_DEFAULT_MULTICAST_LOCATOR => -- Ignore in-line QoS @@ -2033,7 +2066,9 @@ begin if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; + is_meta_addr_next <= '0'; + is_multicast_addr_next <= '1'; end if; when PID_METATRAFFIC_UNICAST_LOCATOR => -- Ignore in-line QoS @@ -2041,7 +2076,9 @@ begin if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; + is_meta_addr_next <= '1'; + is_multicast_addr_next <= '0'; end if; when PID_METATRAFFIC_MULTICAST_LOCATOR => -- Ignore in-line QoS @@ -2049,7 +2086,9 @@ begin if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; + is_meta_addr_next <= '1'; + is_multicast_addr_next <= '1'; end if; when PID_PARTICIPANT_LEASE_DURATION => -- Ignore in-line QoS @@ -2158,8 +2197,9 @@ begin if(qos_flag = '0' and message_type = EDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; - -- Mark Latch 1 for storing + is_meta_addr_next <= '0'; + is_multicast_addr_next <= '0'; end if; when PID_MULTICAST_LOCATOR => -- Ignore in-line QoS @@ -2167,8 +2207,9 @@ begin if(qos_flag = '0' and message_type = EDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; - -- Mark Latch 1 for storing + is_meta_addr_next <= '0'; + is_multicast_addr_next <= '1'; end if; when PID_ENDPOINT_GUID => -- Ignore in-line QoS @@ -2299,7 +2340,7 @@ begin end if; when CHECK_DEFAULT => -- DEFAULT - stage_next <= PARTICIPANT_MATCH_STAGE; + stage_next <= SELECT_LOCATOR; case (message_type) is when PDP => @@ -2345,6 +2386,110 @@ begin when others => null; end case; + when SELECT_LOCATOR => + -- NOTE: If port is set to something other than UDP_PORT_INVALID, the addr is also guarranteed to be unequal IPv4_ADDRESS_INVALID (and vice versa) + -- We compare only the port to save on resources (If necessary we could define a bit for that). + + -- DEFAULT + stage_next <= PARTICIPANT_MATCH_STAGE; + + case (message_type) is + -- Participant Data + when PDP => + if (PREFER_MULTICAST) then + --*METATRAFIC* + -- Multicast Locator Valid + if (meta_mc_port /= UDP_PORT_INVALID) then + meta_addr_next <= meta_mc_addr; + meta_port_next <= meta_mc_port; + -- Fallback to given Unicast Locator + elsif (meta_uc_port /= UDP_PORT_INVALID) then + meta_addr_next <= meta_uc_addr; + meta_port_next <= meta_uc_port; + -- Fallback to Protocol Locator + else + meta_addr_next <= DEFAULT_IPv4_META_ADDRESS; + meta_port_next <= META_IPv4_MULTICAST_PORT; + end if; + --*DEFAULT* + -- Multicast Locator Valid + if (def_mc_port /= UDP_PORT_INVALID) then + def_addr_next <= def_mc_addr; + def_port_next <= def_mc_port; + -- Fallback to given Unicast Locator + elsif (def_uc_port /= UDP_PORT_INVALID) then + def_addr_next <= def_uc_addr; + def_port_next <= def_uc_port; + -- Fallback to Protocol Locator + else + def_addr_next <= DEFAULT_IPv4_META_ADDRESS; + def_port_next <= USER_IPv4_MULTICAST_PORT; + end if; + else + --*METATRAFIC* + -- Unicast Locator Valid + if (meta_uc_port /= UDP_PORT_INVALID) then + meta_addr_next <= meta_uc_addr; + meta_port_next <= meta_uc_port; + -- Fallback to given Multicast Locator + elsif (meta_mc_port /= UDP_PORT_INVALID) then + meta_addr_next <= meta_mc_addr; + meta_port_next <= meta_mc_port; + -- Fallback to Protocol Locator + else + meta_addr_next <= DEFAULT_IPv4_META_ADDRESS; + meta_port_next <= META_IPv4_UNICAST_PORT; + end if; + --*DEFAULT* + -- Unicast Locator Valid + if (def_uc_port /= UDP_PORT_INVALID) then + def_addr_next <= def_uc_addr; + def_port_next <= def_uc_port; + -- Fallback to given Multicast Locator + elsif (def_mc_port /= UDP_PORT_INVALID) then + def_addr_next <= def_mc_addr; + def_port_next <= def_mc_port; + -- Fallback to Protocol Locator + else + def_addr_next <= DEFAULT_IPv4_META_ADDRESS; + def_port_next <= USER_IPv4_UNICAST_PORT; + end if; + end if; + -- Endpoint Data + when EDP => + if (PREFER_MULTICAST) then + -- Multicast Locator Valid + if (def_mc_port /= UDP_PORT_INVALID) then + def_addr_next <= def_mc_addr; + def_port_next <= def_mc_port; + -- Fallback to given Unicast Locator + elsif (def_uc_port /= UDP_PORT_INVALID) then + def_addr_next <= def_uc_addr; + def_port_next <= def_uc_port; + else + -- Participant Default will be used + def_addr_next <= IPv4_ADDRESS_INVALID; + def_port_next <= UDP_PORT_INVALID; + end if; + else + -- Unicast Locator Valid + if (def_uc_port /= UDP_PORT_INVALID) then + def_addr_next <= def_uc_addr; + def_port_next <= def_uc_port; + -- Fallback to given Multicast Locator + elsif (def_mc_port /= UDP_PORT_INVALID) then + def_addr_next <= def_mc_addr; + def_port_next <= def_mc_port; + -- Fallback to Protocol Locator + else + -- Participant Default will be used + def_addr_next <= IPv4_ADDRESS_INVALID; + def_port_next <= UDP_PORT_INVALID; + end if; + end if; + when others => + null; + end case; when LATCH_STRING_LENGTH => -- Input FIFO Guard if (empty = '0') then @@ -2492,16 +2637,30 @@ begin -- Latch Src Addr -- SANITY CHECK: Check if IPv4 Address valid if (data_in_swapped /= IPv4_ADDRESS_INVALID) then - if (is_meta_addr = '0') then - def_addr_next <= data_in; - def_port_next <= long_latch(def_port'length-1 downto 0); + if (is_meta_addr = '1') then + if (is_multicast_addr = '1') then + -- Metatraffic Multicast + meta_mc_addr_next <= data_in; + meta_mc_port_next <= long_latch(meta_mc_port'length-1 downto 0); + else + -- Metatraffic Unicast + meta_uc_addr_next <= data_in; + meta_uc_port_next <= long_latch(meta_uc_port'length-1 downto 0); + end if; else - meta_addr_next <= data_in; - meta_port_next <= long_latch(meta_port'length-1 downto 0); + if (is_multicast_addr = '1') then + -- Endpoint Multicast + def_mc_addr_next <= data_in; + def_mc_port_next <= long_latch(def_mc_port'length-1 downto 0); + else + -- Endpoint Unicast + def_uc_addr_next <= data_in; + def_uc_port_next <= long_latch(def_uc_port'length-1 downto 0); + end if; end if; end if; -- DONE - stage_next <= SKIP_PARAMETER; + stage_next <= SKIP_PARAMETER; when others => null; end case; @@ -2960,7 +3119,7 @@ begin -- IPv4 Address when 5 => -- If Endpoint did not set Address, use Participant Default - if (def_addr /= (def_addr'reverse_range => '0')) then + if (def_port /= UDP_PORT_INVALID) then -- (See SELECT_LOCATOR on why we check the port) data_out_sig <= def_addr; else data_out_sig <= participant_data.def_addr; @@ -2973,7 +3132,7 @@ begin last_word_out_sig <= '1'; -- If Endpoint did not set Port, use Participant Default - if (def_port /= (def_port'reverse_range => '0')) then + if (def_port /= UDP_PORT_INVALID) then data_out_sig(31 downto 16) <= def_port; else data_out_sig(31 downto 16) <= participant_data.def_port; @@ -5918,11 +6077,15 @@ begin message_type <= NONE; string_content <= DOMAIN_TAG_TYPE; src_addr <= IPv4_ADDRESS_INVALID; - def_addr <= IPv4_ADDRESS_INVALID; - meta_addr <= IPv4_ADDRESS_INVALID; + def_mc_addr <= IPv4_ADDRESS_INVALID; + def_uc_addr <= IPv4_ADDRESS_INVALID; + meta_mc_addr <= IPv4_ADDRESS_INVALID; + meta_uc_addr <= IPv4_ADDRESS_INVALID; + def_mc_port <= UDP_PORT_INVALID; + def_uc_port <= UDP_PORT_INVALID; + meta_mc_port <= UDP_PORT_INVALID; + meta_uc_port <= UDP_PORT_INVALID; src_port <= UDP_PORT_INVALID; - def_port <= UDP_PORT_INVALID; - meta_port <= UDP_PORT_INVALID; guid <= GUID_UNKNOWN; src_entityid <= ENTITYID_UNKNOWN; dest_entityid <= ENTITYID_UNKNOWN; @@ -5956,6 +6119,7 @@ begin participant_match <= '0'; is_subscriber <= '0'; is_meta_addr <= '0'; + is_multicast_addr <= '0'; stale_check <= '0'; is_live_assert <= '0'; last_word_in_latch <= '0'; @@ -5980,11 +6144,15 @@ begin message_type <= message_type_next; string_content <= string_content_next; src_addr <= src_addr_next; - def_addr <= def_addr_next; - meta_addr <= meta_addr_next; + def_mc_addr <= def_mc_addr_next; + def_uc_addr <= def_uc_addr_next; + meta_mc_addr <= meta_mc_addr_next; + meta_uc_addr <= meta_uc_addr_next; + def_mc_port <= def_mc_port_next; + def_uc_port <= def_uc_port_next; + meta_mc_port <= meta_mc_port_next; + meta_uc_port <= meta_uc_port_next; src_port <= src_port_next; - def_port <= def_port_next; - meta_port <= meta_port_next; guid <= guid_next; src_entityid <= src_entityid_next; dest_entityid <= dest_entityid_next; @@ -6018,6 +6186,7 @@ begin participant_match <= participant_match_next; is_subscriber <= is_subscriber_next; is_meta_addr <= is_meta_addr_next; + is_multicast_addr <= is_multicast_addr_next; stale_check <= stale_check_next; is_live_assert <= is_live_assert_next; last_word_in_latch <= last_word_in_latch_next; diff --git a/src/rtps_test_package.vhd b/src/rtps_test_package.vhd index 8233522..756f8dc 100644 --- a/src/rtps_test_package.vhd +++ b/src/rtps_test_package.vhd @@ -202,6 +202,8 @@ package rtps_test_package is match : MATCH_TYPE; -- Denotes the Position in the Memory of this Participant Data nr : natural; + -- Denotes which locator is to be used (Same as PREFER_MULTICAST generic of rtps_builtin_endpoint) + PREFER_MULTICAST : boolean; end record; constant DEFAULT_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE; -- Deferred to Package Body @@ -772,7 +774,8 @@ package body rtps_test_package is builtinEndpointQoS => (others => '0'), availableBuiltinEndpoints => (DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER => '1', DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR => '1', BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER => '1', BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER => '1', others => '0'), match => MATCH, - nr => 0 + nr => 0, + PREFER_MULTICAST => FALSE ); constant THIS_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE := ( @@ -793,7 +796,8 @@ package body rtps_test_package is builtinEndpointQoS => (others => '0'), availableBuiltinEndpoints => (DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER => '1', DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR => '1', BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER => '1', BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER => '1', DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER => '1', DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR => '1', DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER => '1', DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR => '1', others => '0'), match => MATCH, - nr => 0 + nr => 0, + PREFER_MULTICAST => FALSE ); constant DEFAULT_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := ( @@ -1052,39 +1056,96 @@ package body rtps_test_package is end function; function get_loc (ref : PARTICIPANT_DATA_TYPE; meta : boolean) return LOCATOR_TYPE is + variable ret : LOCATOR_TYPE := EMPTY_LOCATOR; begin + --*METATRAFFIC* if (meta) then - if (is_valid_loc(get_loc(ref.metatrafficUnicastLocatorList))) then - return get_loc(ref.metatrafficUnicastLocatorList); - elsif (is_valid_loc(get_loc(ref.metatrafficMulticastLocatorList))) then - return get_loc(ref.metatrafficMulticastLocatorList); + if (ref.PREFER_MULTICAST) then + -- Multicast Locator valid + if (is_valid_loc(get_loc(ref.metatrafficMulticastLocatorList))) then + return get_loc(ref.metatrafficMulticastLocatorList); + -- Fallback to given Unicast Locator + elsif (is_valid_loc(get_loc(ref.metatrafficUnicastLocatorList))) then + return get_loc(ref.metatrafficUnicastLocatorList); + -- Fallback to Protocol Locator + else + ret.kind := LOCATOR_KIND_UDPv4; + ret.addr := (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_META_ADDRESS; + ret.portn := (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & META_IPv4_MULTICAST_PORT; + return ret; + end if; else - return DEST_LOC.meta.locator(0); + -- Unicast Locator valid + if (is_valid_loc(get_loc(ref.metatrafficUnicastLocatorList))) then + return get_loc(ref.metatrafficUnicastLocatorList); + -- Fallback to given Multicast Locator + elsif (is_valid_loc(get_loc(ref.metatrafficMulticastLocatorList))) then + return get_loc(ref.metatrafficMulticastLocatorList); + -- Fallback to Protocol Locator + else + ret.kind := LOCATOR_KIND_UDPv4; + ret.addr := (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_META_ADDRESS; + ret.portn := (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & META_IPv4_UNICAST_PORT; + return ret; + end if; end if; + --*DEFAULT* else - if (is_valid_loc(get_loc(ref.defaultUnicastLocatorList))) then - return get_loc(ref.defaultUnicastLocatorList); - elsif (is_valid_loc(get_loc(ref.defaultMulticastLocatorList))) then - return get_loc(ref.defaultMulticastLocatorList); + if (ref.PREFER_MULTICAST) then + -- Multicast Locator valid + if (is_valid_loc(get_loc(ref.defaultMulticastLocatorList))) then + return get_loc(ref.defaultMulticastLocatorList); + -- Fallback to given Unicast Locator + elsif (is_valid_loc(get_loc(ref.defaultUnicastLocatorList))) then + return get_loc(ref.defaultUnicastLocatorList); + -- Fallback to Protocol Locator + else + ret.kind := LOCATOR_KIND_UDPv4; + ret.addr := (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_META_ADDRESS; + ret.portn := (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & USER_IPv4_MULTICAST_PORT; + return ret; + end if; else - return EMPTY_LOCATOR; + -- Unicast Locator valid + if (is_valid_loc(get_loc(ref.defaultUnicastLocatorList))) then + return get_loc(ref.defaultUnicastLocatorList); + -- Fallback to given Multicast Locator + elsif (is_valid_loc(get_loc(ref.defaultMulticastLocatorList))) then + return get_loc(ref.defaultMulticastLocatorList); + -- Fallback to Protocol Locator + else + ret.kind := LOCATOR_KIND_UDPv4; + ret.addr := (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_META_ADDRESS; + ret.portn := (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & USER_IPv4_UNICAST_PORT; + return ret; + end if; end if; end if; end function; function get_loc (ref : ENDPOINT_DATA_TYPE) return LOCATOR_TYPE is begin - if (is_valid_loc(get_loc(ref.unicastLocatorList))) then - return get_loc(ref.unicastLocatorList); - elsif (is_valid_loc(get_loc(ref.multicastLocatorList))) then - return get_loc(ref.multicastLocatorList); - elsif (is_valid_loc(get_loc(ref.participant.defaultUnicastLocatorList))) then - return get_loc(ref.participant.defaultUnicastLocatorList); - elsif (is_valid_loc(get_loc(ref.participant.defaultMulticastLocatorList))) then - return get_loc(ref.participant.defaultMulticastLocatorList); + if (ref.participant.PREFER_MULTICAST) then + -- Multicast Locator valid + if (is_valid_loc(get_loc(ref.multicastLocatorList))) then + return get_loc(ref.multicastLocatorList); + -- Fallback to given unicast Locator + elsif (is_valid_loc(get_loc(ref.unicastLocatorList))) then + return get_loc(ref.unicastLocatorList); + -- Fallback to Participant default + else + return get_loc(ref.participant, FALSE); + end if; else - assert FALSE report "Endpoint has no valid Locators" severity FAILURE; - return EMPTY_LOCATOR; + -- Unicast Locator valid + if (is_valid_loc(get_loc(ref.unicastLocatorList))) then + return get_loc(ref.unicastLocatorList); + -- Fallback to given Multicast Locator + elsif (is_valid_loc(get_loc(ref.multicastLocatorList))) then + return get_loc(ref.multicastLocatorList); + else + return get_loc(ref.participant, FALSE); + end if; end if; end function; diff --git a/syn/syn_config.vhd b/syn/syn_config.vhd index 2b7183c..2ee73e5 100644 --- a/syn/syn_config.vhd +++ b/syn/syn_config.vhd @@ -15,6 +15,8 @@ package user_config is constant MAX_REMOTE_PARTICIPANTS : natural := 50; -- Maximum number of supported remote Endpoints (Affects generated Memory Size) constant MAX_REMOTE_ENDPOINTS : natural := 50; + -- If Multicast Locators should be used instead of Unicast Locators + constant PREFER_MULTICAST_LOCATORS : boolean := FALSE; -- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.90] constant DEFAULT_IPv4_ADDRESS : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := x"C0A8005A";