diff --git a/src/TODO.txt b/src/TODO.txt index 3a3d135..90e5c29 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -79,9 +79,9 @@ * Since the Instance Handle has to be Unique but also orderable, we could use the actual Instance Memory Base Address. Since the Instances are in a list, we also have implicitly an order to all registered Instances. [It may be necessary to add a PREV pointer to the IMF to better support the read_previous_isntance operation] * Does the DEADLINE_QOS apply also to NOT_ALIVE Instances? (Current implementation makes no distinction) * Does TIME_BASED_FILTER also apply to meta-samples (DISPOSED, NO_WRITERS)? That is an easy way to not get convergent state in different DDS Readers. What do other implementations do? -* In rtps_builtin_endpoint we initiate a participant memory search ASAP (in the PACKET_SRC_GUIDPREFIX stage). Further down we branch to several different branches, which each needing different Participant Data Fields. Currently we are fetching ALL needed Fields from ALL branches. Would it make sense to delay the search until the PACKET_DEST_ENTITYID/CHECK_SRC_ENTITYID stage, and only fetch the relevant Fields? * The Participant GUID of the ParticipantMessageData is theoretically not needed, since it is the same as the source GUID of the Packet. This is done, so that the ParticipantMessageData has a key and can be decrypted as every other DATA Message. Our implementation checks if it is the expected GUID and drops it otherwise. - see (https://issues.omg.org/issues/DDSIRTP21-4) +* The RTPS Builtin Endpoint skips a Packet it doesn't understand. The RTPS Builtin Endpoint does not parse "serialized key" of DATA messages (since the specification does not actually define what the serialized key even is). So a SPDP DATA Packet with in-line QoS (PID_STATUS_INFO) and serialized key will be dropped if the RTPS Builtin Endpoint does not know the GUID, and that may stall the whole process pipeline (since the SN will be never acknowledged) * Fast-RTPS does not follow DDSI-RTPS Specification - Open Github Issue diff --git a/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1.vhd b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1.vhd index 54d1359..a07b317 100644 --- a/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1.vhd +++ b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test1.vhd @@ -16,6 +16,7 @@ use work.rtps_test_package.all; -- * 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 @@ -545,6 +546,26 @@ begin 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; + 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); diff --git a/src/Tests/Level_0/L0_rtps_builtin_endpoint_test2.vhd b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test2.vhd index b0acbea..4cd4335 100644 --- a/src/Tests/Level_0/L0_rtps_builtin_endpoint_test2.vhd +++ b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test2.vhd @@ -93,7 +93,8 @@ use work.rtps_test_package.all; -- * DESTINATION_ORDER BY_SOURCE_TIMESTAMP -- The testbench announces 3 remote Participants. Participant 0 and 1 contain the same endpoints as our local Participant, but Participant 1 announces everything in Little Endian format. --- Participant 2 announces extra endpoints to test matching for Readers/Writers with unsupported/ignored QoS +-- Participant 2 announces extra endpoints to test matching for Readers/Writers with unsupported/ignored QoS. +-- The testbench also tests endpoint unmatching by Unregister/Dispose Status Updates. entity L0_rtps_builtin_endpoint_test2 is @@ -831,6 +832,41 @@ begin sub_s.data := EMPTY_TEST_PACKET; p2_sns := p2_sns + 1; + Log("Unmatch Participant 2 Writer [Unregister/Dispose]", INFO); + endpoint := e1; + sub_p.writerSN := p2_snp; + sub_p.flags := (SUBMESSAGE_INLINE_QOS_FLAG_POS => '1', others => '0'); + gen_inline_qos(NOT_ALIVE_DISPOSED, to_key_hash(to_guid(endpoint.participant.guidPrefix,endpoint.entityId)), sub_p.inlineQos); + gen_sentinel(sub_p.inlineQos); + gen_rtps_handler_out(sub_p, endpoint, stimulus); + wr_sig := (others => '0'); + push_endpoint_reference; + start_test; + wait_on_complete; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + sub_p.inlineQos := EMPTY_TEST_PACKET; + p2_snp := p2_snp + 1; + sub_p.flags := (SUBMESSAGE_DATA_FLAG_POS => '1', others => '0'); + + + Log("Unmatch Participant 2 Reader [Unregister/Dispose]", INFO); + endpoint := e2; + sub_s.writerSN := p2_sns; + sub_s.flags := (SUBMESSAGE_INLINE_QOS_FLAG_POS => '1', others => '0'); + gen_inline_qos(NOT_ALIVE_UNREGISTERED, to_key_hash(to_guid(endpoint.participant.guidPrefix,endpoint.entityId)), sub_s.inlineQos); + gen_sentinel(sub_s.inlineQos); + gen_rtps_handler_out(sub_s, endpoint, stimulus); + wr_sig := (others => '0'); + push_endpoint_reference; + start_test; + wait_on_complete; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + sub_s.inlineQos := EMPTY_TEST_PACKET; + p2_sns := p2_sns + 1; + sub_s.flags := (SUBMESSAGE_DATA_FLAG_POS => '1', others => '0'); + stim_done <= '1'; wait until check_done = '1'; TranscriptOpen(RESULTS_FILE, APPEND_MODE); diff --git a/src/Tests/Level_0/L0_rtps_builtin_endpoint_test3.vhd b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test3.vhd index d4c0a91..3d6a69b 100644 --- a/src/Tests/Level_0/L0_rtps_builtin_endpoint_test3.vhd +++ b/src/Tests/Level_0/L0_rtps_builtin_endpoint_test3.vhd @@ -40,6 +40,8 @@ use work.rtps_test_package.all; -- * PID_DATA_MAX_SIZE_SERIALIZED -- * PID_UNICAST_LOCATOR -- * PID_MULTICAST_LOCATOR +-- * PID_KEY_HASH +-- * PID_STATUS_INFO entity L0_rtps_builtin_endpoint_test3 is end entity; @@ -1116,6 +1118,37 @@ begin sub_p.data := EMPTY_TEST_PACKET; p_snp := p_snp + 1; + -- *PID_KEY_HASH* + Log("Ignore Endpoint Status Update [Invalid PID_KEY_HASH]", INFO); + sub_p.writerSN := p_snp; + sub_p.flags := (SUBMESSAGE_INLINE_QOS_FLAG_POS => '1', others => '0'); + gen_inline_qos(NOT_ALIVE_DISPOSED, to_key_hash(to_guid(endpoint.participant.guidPrefix,endpoint.entityId)), sub_p.inlineQos, PID_KEY_HASH, -1); + gen_sentinel(sub_p.inlineQos); + gen_rtps_handler_out(sub_p, endpoint, stimulus); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + sub_p.inlineQos := EMPTY_TEST_PACKET; + + Log("Unmatch Endpoint [Extra Bytes in PID_KEY_HASH]", INFO); + sub_p.writerSN := p_snp; + gen_inline_qos(NOT_ALIVE_DISPOSED, to_key_hash(to_guid(endpoint.participant.guidPrefix,endpoint.entityId)), sub_p.inlineQos, PID_KEY_HASH, +1); + gen_sentinel(sub_p.inlineQos); + gen_rtps_handler_out(sub_p, endpoint, stimulus); + wr_sig := (others => '0'); + push_endpoint_reference; + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + sub_p.inlineQos := EMPTY_TEST_PACKET; + p_snp := p_snp + 1; + sub_p.flags := (SUBMESSAGE_DATA_FLAG_POS => '1', others => '0'); + + -- *PID_MULTICAST_LOCATOR* Log("Ignore Endpoint [Invalid PID_MULTICAST_LOCATOR]", INFO); sub_p.writerSN := p_snp; @@ -1152,6 +1185,36 @@ begin sub_p.data := EMPTY_TEST_PACKET; p_snp := p_snp + 1; + -- *PID_STATUS_INFO* + Log("Ignore Endpoint Status Info [Invalid PID_STATUS_INFO]", INFO); + sub_p.writerSN := p_snp; + sub_p.flags := (SUBMESSAGE_INLINE_QOS_FLAG_POS => '1', others => '0'); + gen_inline_qos(NOT_ALIVE_UNREGISTERED, to_key_hash(to_guid(endpoint.participant.guidPrefix,endpoint.entityId)), sub_p.inlineQos, PID_STATUS_INFO, -1); + gen_sentinel(sub_p.inlineQos); + gen_rtps_handler_out(sub_p, endpoint, stimulus); + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + sub_p.inlineQos := EMPTY_TEST_PACKET; + + Log("Match Endpoint [Extra Bytes in PID_MULTICAST_LOCATOR]", INFO); + sub_p.writerSN := p_snp; + gen_inline_qos(NOT_ALIVE_UNREGISTERED, to_key_hash(to_guid(endpoint.participant.guidPrefix,endpoint.entityId)), sub_p.inlineQos, PID_STATUS_INFO, +1); + gen_sentinel(sub_p.inlineQos); + gen_rtps_handler_out(sub_p, endpoint, stimulus); + wr_sig := (others => '0'); + push_endpoint_reference; + start_test; + wait_on_sent; + wait_on_mem_check; + stimulus := EMPTY_TEST_PACKET; + reference := EMPTY_TEST_PACKET; + sub_p.inlineQos := EMPTY_TEST_PACKET; + p_snp := p_snp + 1; + sub_p.flags := (SUBMESSAGE_DATA_FLAG_POS => '1', others => '0'); + stim_done <= '1'; wait_on_complete; TranscriptOpen(RESULTS_FILE, APPEND_MODE); diff --git a/src/rtps_builtin_endpoint.vhd b/src/rtps_builtin_endpoint.vhd index e02d417..b9fac0e 100644 --- a/src/rtps_builtin_endpoint.vhd +++ b/src/rtps_builtin_endpoint.vhd @@ -127,7 +127,7 @@ architecture arch of rtps_builtin_endpoint is 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, 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, + 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, LATCH_REMOVED_GUIDPREFIX, PROCESS_HEARTBEAT, PROCESS_HEARTBEAT_SEQUENCE_NUMBERS, SEND_ACKNACK, SEND_HEARTBEAT, PROCESS_ACKNACK, PROCESS_ACKNACK_SEQUENCE_NUMBERS, FIND_PARTICIPANT_DEST, SEND_HEADER, SEND_PARTICIPANT_ANNOUNCEMENT, SEND_PUB_DATA, SEND_SUB_DATA, @@ -349,6 +349,8 @@ architecture arch of rtps_builtin_endpoint is signal res_time : TIME_TYPE := TIME_INVALID; -- Test signal used for testbench synchronisation signal idle_sig : std_logic := '0'; + -- Signifies that we received an Unregister/Dispose Status Info + signal ud_status, ud_status_next : std_logic := '0'; -- *MEMORY PROCESS* -- Memory FSM State @@ -580,6 +582,7 @@ begin -- RXO_PARTITION Check Compatibility of Partition QoS -- RXO_LATENCY_BUDGET Check Compatibility of Latency Budget QoS -- CHECK_MAX_SIZE_SERIALIZED Check if Publishers Max sent Payload Size is Compatible + -- CHECK_STATUS_INFO Check inline QoS Status Info for Unregister/Dispose Status -- PARTICIPANT_MATCH_STAGE Add compatible remote and remove incompatible remote Participants to and from memory. Update stored Sequence Numbers respectively (also for EDP) -- INFORM_ENDPOINTS_MATCH Propagate local Endpoint matches -- INFORM_ENDPOINTS_UNMATCH Propagate local Endpoint unmatches @@ -655,6 +658,7 @@ begin bitmap_cnt_next <= bitmap_cnt; bitmap_latch_next <= bitmap_latch; bitmap_pos_next <= bitmap_pos; + ud_status_next <= ud_status; -- DEFAULT Unregistered rd_sig <= '0'; rd_guard := '0'; @@ -759,17 +763,18 @@ 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; - 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'); + def_addr_next <= (others => '0'); + meta_addr_next <= DEFAULT_IPv4_META_ADDRESS; + def_port_next <= (others => '0'); + meta_port_next <= META_IPv4_MULTICAST_PORT; + 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'); + ud_status_next <= '0'; -- NOTE: We work with a "mark by default, and unmark on first missmatch" System. -- This assumes that each RxO QoS parameter occur only once in the list, else the behavior is undefined. - participant_match_next <= '1'; - endpoint_mask_next <= (others => '1'); + participant_match_next <= '1'; + endpoint_mask_next <= (others => '1'); end if; when PACKET_HEADER => -- Input FIFO Guard @@ -812,7 +817,7 @@ begin guid_next(1) <= data_in; when 2 => guid_next(2) <= data_in; - guid_next(3) <= (others => '0'); + guid_next(3) <= ENTITYID_PARTICIPANT; stage_next <= PACKET_SRC_ENTITYID; when others => @@ -1273,6 +1278,28 @@ begin null; end case; end if; + elsif (ud_status = '1') then + -- NOTE: If the DATA message has a paylaod with DATA, the parsed in-line QoS (i.e. PID_STATUS_INFO) is ignored + -- NOTE: A Sanity check is made on the GUID. It is expected that the GUID is correctly configured by parsing of an PID_KEY_HASH. + -- According to the specification the PID_KEY_HASH is not a requirement, and the Key should be sent as serialized key in the DATA + -- message payload. We do not parse the serialized key (because, quite frankly, we can't since we do not have a definition of it...) + -- This means that if the sender does not send a PID_KEY_HASH and the sanity check here fails, the Packet will be skipped, and thus + -- processing from the sender will effectively stall, since the SN will never be acknowledged. + -- Participant Unamtch + if (message_type = PDP and guid(3) = ENTITYID_PARTICIPANT) then + participant_match_next <= '0'; + stage_next <= PARTICIPANT_MATCH_STAGE; + -- Endpoint Unmatch + elsif (message_type = EDP and guid(3)(ENTITY_KIND_H_RANGE) /= BUILT_IN_ENTITY) then + endpoint_mask_next <= (others => '0'); + stage_next <= PARTICIPANT_MATCH_STAGE; + else + -- Skip + stage_next <= SKIP_PACKET; + end if; + else + -- Skip + stage_next <= SKIP_PACKET; end if; when PROCESS_MESSAGE_SEQUENCE_NUMBERS => -- Precondition: participant_data set (PMF_MES_SEQ_NR_FLAG) @@ -2179,11 +2206,10 @@ begin -- Ignore null; when PID_KEY_HASH => - -- Ignore - null; + stage_next <= MATCH_GUID; + cnt_next <= 0; when PID_STATUS_INFO => - -- Ignore - null; + stage_next <= CHECK_STATUS_INFO; when PID_PAD => -- Ignore null; @@ -2706,6 +2732,19 @@ begin if (is_subscriber = '0' and unsigned(data_in_swapped) > to_unsigned(UDP_MAX_SIZE_SERIALIZED, CDR_LONG_WIDTH)) then endpoint_mask_next <= (others => '0'); end if; + -- DONE + stage_next <= SKIP_PARAMETER; + end if; + when CHECK_STATUS_INFO => + -- Input FIFO Guard + if (empty = '0') then + rd_guard := '1'; + + -- Mark if Unregister/Disposed Status + if (data_in(STATUS_INFO_DISPOSED_FLAG) = '1' or data_in(STATUS_INFO_UNREGISTERED_FLAG) = '1') then + ud_status_next <= '1'; + end if; + -- DONE stage_next <= SKIP_PARAMETER; end if; @@ -5749,6 +5788,7 @@ begin stale_check <= '0'; is_live_assert <= '0'; last_word_in_latch <= '0'; + ud_status <= '0'; parameter_end <= (others => '1'); opcode <= (others => '0'); flags <= (others => '0'); @@ -5810,6 +5850,7 @@ begin stale_check <= stale_check_next; is_live_assert <= is_live_assert_next; last_word_in_latch <= last_word_in_latch_next; + ud_status <= ud_status_next; parameter_end <= parameter_end_next; opcode <= opcode_next; flags <= flags_next; diff --git a/src/rtps_package.vhd b/src/rtps_package.vhd index ad97505..b243fdb 100644 --- a/src/rtps_package.vhd +++ b/src/rtps_package.vhd @@ -460,6 +460,7 @@ 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; + function to_key_hash (A : GUID_TYPE) return KEY_HASH_TYPE; -- *OVERLOAD FUNCTIONS* function convert_from_double_word (input: DOUBLE_WORD_ARRAY) return unsigned; @@ -696,6 +697,16 @@ package body rtps_package is return ret; end function; + function to_key_hash (A : GUID_TYPE) return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := HANDLE_NIL; + begin + assert (GUID_TYPE'length = KEY_HASH_TYPE'length) severity FAILURE; + for i in 0 to GUID_TYPE'length-1 loop + ret(i) := A(i); + end loop; + return ret; + end function; + function to_unsigned(input : KEY_HASH_TYPE) return unsigned is variable ret : unsigned(KEY_HASH_WIDTH-1 downto 0) := (others => '0'); begin diff --git a/src/rtps_test_package.vhd b/src/rtps_test_package.vhd index 9f603cc..fa47808 100644 --- a/src/rtps_test_package.vhd +++ b/src/rtps_test_package.vhd @@ -438,10 +438,14 @@ package rtps_test_package is -- The Parameter Field represented by "pid" is always written, not depending on if it has Default value. "Offset" modifies the Parameter Length of the "pid" and represents how -- many 4-Byte Words to add/subtract from the original value. -- This allows to generate invalid parameter lists - -- NOTE: "expectsInlineQoS" takes precedence over "pid" (I.e. if expectsInlineQoS=TRUE and pid is Endpoint related, the PID Element will not be generated) + -- NOTE: "expectsInlineQoS" takes precedence over "pid" (I.e. if expectsInlineQoS=FALSE and pid is Endpoint related, the PID Element will not be generated) procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; endpoint : in ENDPOINT_DATA_TYPE; expectsInlineQoS : in boolean; littleEndian : in std_logic; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer); -- Like previous procedure, but no Endpoint Data related PIDs are generated (only PID_KEY_HASH, PID_STATUS_INFO) procedure gen_inline_qos(ref : in CACHE_CHANGE_TYPE; output : inout TEST_PACKET_TYPE); + -- Like previous procedure, but the data for PID_STATUS_INFO andf PID_KEY_HASH are given directly. + procedure gen_inline_qos(status : in CACHE_CHANGE_KIND_TYPE; key : in INSTANCE_HANDLE_TYPE; output : inout TEST_PACKET_TYPE); + -- Like previous procedure but with "pid" and "offset" parameters. + procedure gen_inline_qos(status : in CACHE_CHANGE_KIND_TYPE; key : in INSTANCE_HANDLE_TYPE; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer); -- Generate Parameter List Element -- pid Parameter ID of element -- data Parameter Data of element @@ -2877,6 +2881,19 @@ package body rtps_test_package is gen_inline_qos(ref,DEFAULT_ENDPOINT_DATA,FALSE,'0',output,PID_PAD,0); end procedure; + procedure gen_inline_qos(status : in CACHE_CHANGE_KIND_TYPE; key : in INSTANCE_HANDLE_TYPE; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer) is + variable tmp : CACHE_CHANGE_TYPE := DEFAULT_CACHE_CHANGE; + begin + tmp.kind := status; + tmp.instance := key; + gen_inline_qos(tmp,DEFAULT_ENDPOINT_DATA,FALSE,'0',output,pid,offset); + end procedure; + + procedure gen_inline_qos(status : in CACHE_CHANGE_KIND_TYPE; key : in INSTANCE_HANDLE_TYPE; output : inout TEST_PACKET_TYPE) is + begin + gen_inline_qos(status,key,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