3453 lines
188 KiB
VHDL
3453 lines
188 KiB
VHDL
-- altera vhdl_input_version vhdl_2008
|
|
-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html)
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
library osvvm; -- Utility Library
|
|
context osvvm.OsvvmContext;
|
|
|
|
use work.math_pkg.all;
|
|
use work.rtps_package.all;
|
|
use work.user_config.all;
|
|
use work.rtps_config_package.all;
|
|
|
|
package rtps_test_package is
|
|
|
|
constant TEST_CLOCK_PERIOD : time := 50 ns;
|
|
|
|
-- File were the Test Results are stored
|
|
constant RESULTS_FILE : string := "./Test_Results.txt";
|
|
|
|
-- Frame Sizes have to be specified, so that direct memory probing is possible
|
|
-- rtps_builtin_endpoint Participant Frame Size
|
|
constant PARTICIPANT_FRAME_SIZE : natural := 24;
|
|
-- rtps_reader Endpoint Frame Size (RELIABLE=TRUE)
|
|
constant WRITER_ENDPOINT_FRAME_SIZE_A : natural := 14;
|
|
-- rtps_reader Endpoint Frame Size (RELIABLE=FALSE)
|
|
constant WRITER_ENDPOINT_FRAME_SIZE_B : natural := 10;
|
|
-- rtps_writer Endpoint Frame Size (RELIABLE=TRUE)
|
|
constant READER_ENDPOINT_FRAME_SIZE_A : natural := 15;
|
|
-- rtps_writer Endpoint Frame Size (RELIABLE=FALSE)
|
|
constant READER_ENDPOINT_FRAME_SIZE_B : natural := 6;
|
|
|
|
constant DEFAULT_GUIDPREFIX : GUIDPREFIX_TYPE; -- Deferred to Package Body
|
|
constant DEFAULT_READER_ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0); -- Deferred to Package Body
|
|
constant DEFAULT_WRITER_ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0); -- Deferred to Package Body
|
|
|
|
type MATCH_TYPE is (MATCH, UNMATCH);
|
|
|
|
-- General Purpose 32-bit wide data container
|
|
type TEST_PACKET_TYPE is record
|
|
-- Limit Packet Size to 2^16 (IPv4 size limit)
|
|
data : WORD_ARRAY_TYPE(0 to (2**16)/4);
|
|
-- Last Word Indicator
|
|
last : std_logic_vector(0 to (2**16)/4);
|
|
-- Length of Packet
|
|
length : natural;
|
|
end record;
|
|
|
|
constant EMPTY_TEST_PACKET : TEST_PACKET_TYPE; -- Deferred to Package Body
|
|
|
|
-- Memory Element Representation
|
|
type TEST_MEMORY_ELEMENT_TYPE is record
|
|
addr : natural;
|
|
data : std_logic_vector(WORD_WIDTH-1 downto 0);
|
|
end record;
|
|
|
|
type TEST_MEMORY_TYPE is array (natural range <>) of TEST_MEMORY_ELEMENT_TYPE;
|
|
|
|
subtype TEST_PARTICIPANT_MEMORY_FRAME_TYPE is TEST_MEMORY_TYPE(0 to PARTICIPANT_FRAME_SIZE-1);
|
|
subtype TEST_WRITER_ENDPOINT_MEMORY_FRAME_TYPE_A is TEST_MEMORY_TYPE(0 to WRITER_ENDPOINT_FRAME_SIZE_A-1);
|
|
subtype TEST_WRITER_ENDPOINT_MEMORY_FRAME_TYPE_B is TEST_MEMORY_TYPE(0 to WRITER_ENDPOINT_FRAME_SIZE_B-1);
|
|
subtype TEST_READER_ENDPOINT_MEMORY_FRAME_TYPE_A is TEST_MEMORY_TYPE(0 to READER_ENDPOINT_FRAME_SIZE_A-1);
|
|
subtype TEST_READER_ENDPOINT_MEMORY_FRAME_TYPE_B is TEST_MEMORY_TYPE(0 to READER_ENDPOINT_FRAME_SIZE_B-1);
|
|
|
|
|
|
constant LOCATOR_PORT_WIDTH : natural := CDR_LONG_WIDTH;
|
|
constant LOCATOR_ADDR_WIDTH : natural := 4*CDR_LONG_WIDTH;
|
|
|
|
type LOCATOR_TYPE is record
|
|
kind : std_logic_vector(LOCATOR_KIND_WIDTH-1 downto 0);
|
|
portn : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
addr : std_logic_vector(LOCATOR_ADDR_WIDTH-1 downto 0);
|
|
end record;
|
|
|
|
constant EMPTY_LOCATOR : LOCATOR_TYPE; -- Deferred to Package Body
|
|
|
|
-- Limit Number of Locators to maximum number that fits in a maximum length RTPS Submessage
|
|
type LOCATOR_TYPE_ARRAY is array (0 to ((2**16)/4)/6) of LOCATOR_TYPE;
|
|
|
|
type LOCATOR_LIST_TYPE is record
|
|
numLocators : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
locator : LOCATOR_TYPE_ARRAY;
|
|
end record;
|
|
|
|
constant EMPTY_LOCATOR_LIST : LOCATOR_LIST_TYPE; -- Deferred to Package Body
|
|
|
|
type SEQUENCENUMBER_SET_TYPE is record
|
|
base : SEQUENCENUMBER_TYPE;
|
|
numBits : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
bitmap : std_logic_vector(0 to 255);
|
|
end record;
|
|
|
|
constant DEFAULT_SEQUENCENUMBER_SET : SEQUENCENUMBER_SET_TYPE; -- Deferred to package Body
|
|
|
|
type FRAGMENTNUMBER_SET_TYPE is record
|
|
base : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
numBits : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
bitmap : std_logic_vector(0 to 255);
|
|
end record;
|
|
|
|
constant DEFAULT_FRAGMENTNUMBER_SET : FRAGMENTNUMBER_SET_TYPE; -- Deferred to Package Body
|
|
|
|
-- Valid Destination Locators
|
|
type DEST_LOCATOR_LIST_TYPE is record
|
|
meta : LOCATOR_LIST_TYPE;
|
|
user : LOCATOR_LIST_TYPE;
|
|
end record;
|
|
|
|
constant DEST_LOC : DEST_LOCATOR_LIST_TYPE; -- Deferred to Package Body
|
|
|
|
type OUTPUT_HEADER_TYPE is record
|
|
src : LOCATOR_TYPE;
|
|
dest : LOCATOR_TYPE;
|
|
end record;
|
|
|
|
constant DEFAULT_OUTPUT_HEADER : OUTPUT_HEADER_TYPE; -- Deferred to Package Body
|
|
|
|
type RTPS_HEADER_TYPE is record
|
|
protocol : std_logic_vector(PROTOCOL_WIDTH-1 downto 0);
|
|
version : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0);
|
|
vendorId : std_logic_vector(VENDORID_WIDTH-1 downto 0);
|
|
guidPrefix : GUIDPREFIX_TYPE;
|
|
end record;
|
|
|
|
constant DEFAULT_RTPS_HEADER : RTPS_HEADER_TYPE; -- Deferred to Package Body
|
|
|
|
-- Generic RTPS Submessage Container
|
|
type RTPS_SUBMESSAGE_TYPE is record
|
|
-- ALL
|
|
submessageID : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0);
|
|
flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0);
|
|
submessageLength : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0);
|
|
-- ACKNACK/DATA/GAP/HEARTBEAT/DATAFRAG/NACKFRAG
|
|
readerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0);
|
|
writerId : std_logic_vector(ENTITYID_WIDTH-1 downto 0);
|
|
-- DATA/DATAFRAG/HEARTBEATFRAG/NACKFRAG
|
|
writerSN : SEQUENCENUMBER_TYPE;
|
|
-- DATA/DATAFRAG
|
|
inlineQos : TEST_PACKET_TYPE;
|
|
data : TEST_PACKET_TYPE;
|
|
-- DATA
|
|
extraFlags : std_logic_vector(SUBMESSAGE_DATA_EXTRA_FLAGS_WIDTH-1 downto 0);
|
|
octetsToInlineQos : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0);
|
|
-- DATAFRAG
|
|
fragmentStartingNumber : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
fragmentsInSubmessage : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
|
|
fragmentSize : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
|
|
sampleSize : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
-- HEARTBEAT/HEARTBEATFRAG/NACKFRAG/ACKNACK
|
|
count : std_logic_vector(COUNT_WIDTH-1 downto 0);
|
|
-- HEARTBEAT
|
|
firstSN : SEQUENCENUMBER_TYPE;
|
|
lastSN : SEQUENCENUMBER_TYPE;
|
|
-- HEARTBEATFRAG
|
|
lastFragmentNum : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
-- NACKFRAG
|
|
fragmentNumberState : FRAGMENTNUMBER_SET_TYPE;
|
|
-- ACKNACK
|
|
readerSNState : SEQUENCENUMBER_SET_TYPE;
|
|
-- GAP
|
|
gapStart : SEQUENCENUMBER_TYPE;
|
|
gapList : SEQUENCENUMBER_SET_TYPE;
|
|
-- INFO_REPLY
|
|
unicastLocatorList : LOCATOR_LIST_TYPE;
|
|
multicastLocatorList : LOCATOR_LIST_TYPE;
|
|
-- INFO_DEST/INFO_SRC
|
|
guidPrefix : GUIDPREFIX_TYPE;
|
|
-- INFO_SRC
|
|
unused : std_logic_vector(31 downto 0);
|
|
version : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0);
|
|
vendorId : std_logic_vector(VENDORID_WIDTH-1 downto 0);
|
|
-- INFO_TS
|
|
timestamp : TIME_TYPE;
|
|
-- INFO_REPLY_IP4
|
|
unicastLocator : LOCATOR_TYPE;
|
|
multicastLocator : LOCATOR_TYPE;
|
|
end record;
|
|
|
|
constant DEFAULT_RTPS_SUBMESSAGE : RTPS_SUBMESSAGE_TYPE; -- Deferred to Package Body
|
|
|
|
type PARTICIPANT_DATA_TYPE is record
|
|
-- Signifies if the Data should be written in Little Endian
|
|
littleEndian : std_logic;
|
|
domainId : std_logic_vector(DOMAIN_ID_WIDTH-1 downto 0);
|
|
domainTag : STRING_WORD_ARRAY_TYPE;
|
|
protocolVersion : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0);
|
|
vendorId : std_logic_vector(VENDORID_WIDTH-1 downto 0);
|
|
guidPrefix : GUIDPREFIX_TYPE;
|
|
entityId : std_logic_vector(ENTITYID_WIDTH-1 downto 0);
|
|
expectsInlineQoS : std_logic_vector(CDR_BOOLEAN_WIDTH-1 downto 0);
|
|
metatrafficUnicastLocatorList : LOCATOR_LIST_TYPE;
|
|
metatrafficMulticastLocatorList : LOCATOR_LIST_TYPE;
|
|
defaultUnicastLocatorList : LOCATOR_LIST_TYPE;
|
|
defaultMulticastLocatorList : LOCATOR_LIST_TYPE;
|
|
leaseDuration : DURATION_TYPE;
|
|
manualLivelinessCount : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
builtinEndpointQoS : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
availableBuiltinEndpoints : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
-- Signifies if the Participant represented by this Record is a match
|
|
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
|
|
constant THIS_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE; -- Deferred to Package Body
|
|
|
|
-- Generic RTPS Endpoint Container
|
|
type ENDPOINT_DATA_TYPE is record
|
|
-- Signifies if the Endoint Data represented by this Record is a Reader Endpoint
|
|
reader : boolean;
|
|
-- Signifies if the Data should be written in Little Endian
|
|
littleEndian : std_logic;
|
|
participant : PARTICIPANT_DATA_TYPE;
|
|
entityId : std_logic_vector(ENTITYID_WIDTH-1 downto 0);
|
|
topic_name : STRING_WORD_ARRAY_TYPE;
|
|
type_name : STRING_WORD_ARRAY_TYPE;
|
|
durability : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
|
|
durability_service_cleanup_delay : DURATION_TYPE;
|
|
durability_service_history : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
|
|
durability_service_history_depth : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
durability_service_max_samples : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
durability_service_max_instances : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
durability_service_max_samples_per_instances : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
presentation : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
|
|
coherent_access : std_logic_vector(CDR_BOOLEAN_WIDTH-1 downto 0);
|
|
ordered_access : std_logic_vector(CDR_BOOLEAN_WIDTH-1 downto 0);
|
|
deadline : DURATION_TYPE;
|
|
latency_budget : DURATION_TYPE;
|
|
ownership : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
|
|
ownership_strength : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
liveliness : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
|
|
leaseDuration : DURATION_TYPE;
|
|
time_based_filter : DURATION_TYPE;
|
|
reliability : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
|
|
max_blocking_time : DURATION_TYPE;
|
|
lifespan : DURATION_TYPE;
|
|
destination_order : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
|
|
expectsInlineQoS : std_logic_vector(CDR_BOOLEAN_WIDTH-1 downto 0);
|
|
unicastLocatorList : LOCATOR_LIST_TYPE;
|
|
multicastLocatorList : LOCATOR_LIST_TYPE;
|
|
max_size_serialized : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
-- Represent Data as Strings (Ease of Use)
|
|
user_data : STRING_WORD_ARRAY_TYPE;
|
|
topic_data : STRING_WORD_ARRAY_TYPE;
|
|
group_data : STRING_WORD_ARRAY_TYPE;
|
|
-- Signifies if the Endpoint represented by this Record is a match
|
|
match : MATCH_TYPE;
|
|
-- Denotes the Position in the Memory of this Participant Data
|
|
nr : natural;
|
|
end record;
|
|
|
|
constant DEFAULT_ENDPOINT_DATA : ENDPOINT_DATA_TYPE; -- Deferred to Package Body
|
|
type ENDPOINT_DATA_ARRAY_TYPE is array (natural range <>) of ENDPOINT_DATA_TYPE;
|
|
|
|
-- Cache Change Representation
|
|
type CACHE_CHANGE_TYPE is record
|
|
-- Denotes if the CC contains the Serialized Key
|
|
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; -- Deferred to Package Body
|
|
|
|
-- DDS Sample Representation
|
|
type SAMPLE_TYPE is record
|
|
-- Instance (KEY_HASH)
|
|
inst : INSTANCE_HANDLE_TYPE;
|
|
data : TEST_PACKET_TYPE;
|
|
-- Sample State
|
|
sstate : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0);
|
|
-- Instance State
|
|
istate : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
|
|
-- View State
|
|
vstate : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
|
|
-- Disposed Generation Count
|
|
dis_gen_cnt : natural;
|
|
-- No Writers Generation Count
|
|
no_w_gen_cnt : natural;
|
|
-- Sample Rank
|
|
srank : natural;
|
|
-- Generation Rank
|
|
grank : natural;
|
|
-- Absolut Generation Rank
|
|
agrank : natural;
|
|
-- Source Timestamp
|
|
ts : TIME_TYPE;
|
|
end record;
|
|
|
|
constant DEFAULT_SAMPLE : SAMPLE_TYPE; -- Deferred to Package Body
|
|
|
|
-- NOTE: The array is currently limited to 15 Samples to limit memory allocation
|
|
type SAMPLE_ARRAY_TYPE is array (0 to 15) of SAMPLE_TYPE;
|
|
|
|
-- Representation of a DDS Reader Sample Collection
|
|
type COLLECTION_TYPE is record
|
|
s : SAMPLE_ARRAY_TYPE;
|
|
len : natural;
|
|
end record;
|
|
|
|
constant DEFAULT_COLLECTION : COLLECTION_TYPE; -- Deferred to Package Body
|
|
|
|
-- Representation of DDS Reader Instance State
|
|
type INSTANCE_CACHE_TYPE is record
|
|
-- Instance (KEY_HASH)
|
|
inst : INSTANCE_HANDLE_TYPE;
|
|
-- Instance State
|
|
istate : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
|
|
-- Vies State
|
|
vstate : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
|
|
-- Disposed Generation Count
|
|
dis_gen_cnt : natural;
|
|
-- No Writers Geneation Count
|
|
no_w_gen_cnt : natural;
|
|
end record;
|
|
|
|
constant DEFAULT_INSTANCE_CACHE_TYPE : INSTANCE_CACHE_TYPE; -- Deferred to Package Body
|
|
|
|
type INSTANCE_CACHE_ARRAY_TYPE is array (0 to 15) of INSTANCE_CACHE_TYPE;
|
|
|
|
-- Representation of DDS Reader internal Memory
|
|
type DDS_READER_MEM_TYPE is record
|
|
-- Sample Memory
|
|
s : SAMPLE_ARRAY_TYPE;
|
|
slen : natural;
|
|
-- Instance Memory
|
|
inst : INSTANCE_CACHE_ARRAY_TYPE;
|
|
ilen : natural;
|
|
end record;
|
|
|
|
constant DEFAULT_DDS_READER_MEM : DDS_READER_MEM_TYPE; -- Deferred to Package Body
|
|
|
|
-- Representation of DDS Reader Operations
|
|
type DDS_READER_TEST_TYPE is record
|
|
-- OPERATION & ARGUMENTS
|
|
opcode : DDS_READER_OPCODE_TYPE;
|
|
sstate : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0);
|
|
istate : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
|
|
vstate : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
|
|
max_samples : natural;
|
|
-- NOTE: Instance is used as Operation Arguments & Expected Return (Last Rejected Instance)
|
|
inst : INSTANCE_HANDLE_TYPE;
|
|
-- EXPECTED RETURN
|
|
ret_code : std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
|
|
-- STATUS Operation Count
|
|
count : natural;
|
|
-- STATUS Operation Count Change
|
|
change : natural;
|
|
-- STATUS Operation Last Rejected Reason
|
|
last_reason : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
|
|
end record;
|
|
|
|
constant DEFAULT_DDS_READER_TEST : DDS_READER_TEST_TYPE; -- Deferred to Package Body
|
|
|
|
-- Represntation of RTPS Writer Operations
|
|
type RTPS_WRITER_TEST_TYPE is record
|
|
opcode : HISTORY_CACHE_OPCODE_TYPE;
|
|
cc : CACHE_CHANGE_TYPE;
|
|
ret_code : HISTORY_CACHE_RESPONSE_TYPE;
|
|
end record;
|
|
|
|
constant DEFAULT_RTPS_WRITER_TEST : RTPS_WRITER_TEST_TYPE; -- Deferred to Package Body
|
|
|
|
-- Representation of RTPS Reader Operations
|
|
type RTPS_READER_TEST_TYPE is record
|
|
opcode : HISTORY_CACHE_OPCODE_TYPE;
|
|
cc : CACHE_CHANGE_TYPE;
|
|
lifespan : DURATION_TYPE;
|
|
writer_pos : natural;
|
|
ret_code : HISTORY_CACHE_RESPONSE_TYPE;
|
|
end record;
|
|
|
|
constant DEFAULT_RTPS_READER_TEST : RTPS_READER_TEST_TYPE; -- Deferred to Package Body
|
|
|
|
-- Representation of DDS Writer Operation
|
|
type DDS_WRITER_TEST_TYPE is record
|
|
-- OPERATION & ARGUMENTS
|
|
opcode : DDS_WRITER_OPCODE_TYPE;
|
|
cc : CACHE_CHANGE_TYPE;
|
|
-- NOTE: Instance is used as Operation Arguments & Expected Return (Deadline Missed Instance)
|
|
inst : INSTANCE_HANDLE_TYPE;
|
|
-- Liveliness Assertion
|
|
assertion : std_logic;
|
|
-- EXPECTED RETURN
|
|
ret_code : std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
|
|
-- STATUS Operation Count
|
|
count : natural;
|
|
-- STATUS Operation Count Change
|
|
change : natural;
|
|
end record;
|
|
|
|
constant DEFAULT_DDS_WRITER_TEST : DDS_WRITER_TEST_TYPE; -- Deferred to Package Body
|
|
|
|
|
|
-- *RTPS SPECIFICATION*
|
|
-- Writes RTPS Output Header based on "ref" to "output"
|
|
procedure gen_output_header(ref : in OUTPUT_HEADER_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Fixes the "Packet Length" Field of the RTPS Output Reader with the current Packet Length
|
|
-- This function should be called to fnalize the RTPS packet
|
|
procedure fix_output_packet(output : inout TEST_PACKET_TYPE);
|
|
-- Writes RTPS Header based on "ref" to "output"
|
|
procedure gen_rtps_header( ref : in RTPS_HEADER_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Write RTPS Submessage based on "ref" to "output"
|
|
procedure gen_rtps_submessage( ref : in RTPS_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Writes Participant Data based on "ref" to "output"
|
|
procedure gen_participant_data( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Like previous procedure, but allows modification of the generated output.
|
|
-- 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
|
|
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);
|
|
-- Writes Endpoint Data based on "ref" to "output"
|
|
procedure gen_endpoint_data( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Like previous procedure, but allows modification of the generated output.
|
|
-- 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
|
|
procedure gen_endpoint_data( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer);
|
|
-- Generate Participant Message Data
|
|
-- participant participant to assert Liveliness
|
|
-- manual TRUE if MANUAL_LIVELINESS_UPDATE, FALSE if AUTOMATIC_LIVELINESS_UPDATE
|
|
-- extra_data Extra Data in Participant Message
|
|
-- output Destination of generated ouput
|
|
procedure gen_liveliness_assertion(participant : in PARTICIPANT_DATA_TYPE; manual : in boolean; extra_data : in TEST_PACKET_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Same as previous procedure, but extra_data is EMPTY
|
|
procedure gen_liveliness_assertion(participant : in PARTICIPANT_DATA_TYPE; manual : in boolean; output : inout TEST_PACKET_TYPE);
|
|
-- Generate DATA Submessage InLine QoS
|
|
-- ref Cache Change (Used for PID_KEY_HASH, PID_STATUS_INFO)
|
|
-- endpoint Endpoint Data
|
|
-- expectsInlineQoS The Endpoint Data related PIDs are only generated if this is TRUE
|
|
-- littleEndian If TRUE the generated Data is in little Endian, else in Big Endian
|
|
-- output Destination of generated output
|
|
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);
|
|
-- Like previous procedure, but allows modification of the generated output.
|
|
-- 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=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 [NOTE: Dat has to be in the correct endianness]
|
|
-- pid Parameter ID of element
|
|
-- data Parameter Data of element
|
|
-- littleEndian If TRUE the generated Data is in little Endian, else in Big Endian
|
|
-- output Destination of generated output
|
|
procedure gen_parameter(pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); data : in TEST_PACKET_TYPE; littleEndian : in std_logic; output : inout TEST_PACKET_TYPE);
|
|
-- Generate Parameter List Sentinel. This procedure should be used to finalize Parameter Lists
|
|
-- littleEndian If TRUE the generated Data is in little Endian, else in Big Endian
|
|
-- output Destination of generated output
|
|
procedure gen_sentinel(littleEndian : in std_logic; output : inout TEST_PACKET_TYPE);
|
|
-- Shortcut of previous procedure in Big Endian
|
|
procedure gen_sentinel(output : inout TEST_PACKET_TYPE);
|
|
|
|
|
|
-- *RTPS_READER*
|
|
-- Generates RTPS Reader ADD_CACHE_CHANGE output (DDS Reader Input)
|
|
-- ref Cache Change
|
|
-- lifespan_deadline Lifespan Deadline of Sample
|
|
-- pos ID (Memory Position) of Source Remote Writer
|
|
-- output Destination of generated output
|
|
procedure gen_add_cache_change_dds(ref : in CACHE_CHANGE_TYPE; lifespan_deadline : in TIME_TYPE; pos : in natural; output : inout TEST_PACKET_TYPE);
|
|
-- Generate a rtps_writer memory Participant Frame based on "ref". (A Version)
|
|
function gen_writer_endpoint_mem_frame_a (ref : ENDPOINT_DATA_TYPE) return TEST_WRITER_ENDPOINT_MEMORY_FRAME_TYPE_A;
|
|
-- Generate a rtps_writer memory Participant Frame based on "ref". (B Version)
|
|
function gen_writer_endpoint_mem_frame_b (ref : ENDPOINT_DATA_TYPE) return TEST_WRITER_ENDPOINT_MEMORY_FRAME_TYPE_B;
|
|
|
|
|
|
-- *RTPS WRITER*
|
|
-- Generate a rtps_reader memory Participant Frame based on "ref". (A Version)
|
|
function gen_reader_endpoint_mem_frame_a (ref : ENDPOINT_DATA_TYPE) return TEST_READER_ENDPOINT_MEMORY_FRAME_TYPE_A;
|
|
-- Generate a rtps_reader memory Participant Frame based on "ref". (B Version)
|
|
function gen_reader_endpoint_mem_frame_b (ref : ENDPOINT_DATA_TYPE) return TEST_READER_ENDPOINT_MEMORY_FRAME_TYPE_B;
|
|
|
|
|
|
-- *RTPS_HANDLER*
|
|
-- Generates RTPS_HANDLER output
|
|
-- ref RTPS Submessage
|
|
-- loc Source Locator of RTPS Submessage
|
|
-- is_meta Indicates if the RTPS Submessage is metatraffic (Destined for Built-in Endpoints)
|
|
-- ts Source Timestamp of RTPS Submessage
|
|
-- src_guid Source GUID of RTPS Submessage
|
|
-- output Destination of generated output
|
|
procedure gen_rtps_handler_out(ref : in RTPS_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; is_meta : in boolean; ts : in TIME_TYPE; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Like the previous procedure, but the source locator & GUID is extracted from the "participant". Timestamp is INVALID and is_meta is set to TRUE.
|
|
procedure gen_rtps_handler_out(ref : in RTPS_SUBMESSAGE_TYPE; participant : PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Like the previous procedure, but the source locator & GUID is extracted from the "endpoint". Timestamp is INVALID and is_meta is set to TRUE.
|
|
procedure gen_rtps_handler_out(ref : in RTPS_SUBMESSAGE_TYPE; endpoint : ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE);
|
|
|
|
|
|
-- *RTPS_BUILTIN_ENDPOINT*
|
|
-- Generate a rtps_builtin_endpoint memory Participant Frame based on "ref".
|
|
function gen_participant_mem_frame (ref : PARTICIPANT_DATA_TYPE) return TEST_PARTICIPANT_MEMORY_FRAME_TYPE;
|
|
-- Writes a rtps_builtin_endpoint Endpoint Match Frame based on "ref" to "output"
|
|
procedure gen_endpoint_match_frame( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Writes a rtps_builtin_endpoint Participant Match Frame based on "ref" to "output"
|
|
procedure gen_participant_match_frame( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE);
|
|
-- Writes a rtps_builtin_endpoint Endpoint Liveliness Update Frame based on "ref" to "output"
|
|
procedure gen_liveliness_update_frame( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE);
|
|
|
|
|
|
-- *DDS_READER*
|
|
-- Add Instance to Memory
|
|
-- inst Instance (KEY_HASH)
|
|
-- istate Instance State
|
|
-- mem Target Memory
|
|
procedure add_instance(inst : in INSTANCE_HANDLE_TYPE; istate : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); mem : inout DDS_READER_MEM_TYPE);
|
|
-- Change Instance State of Instance in Memory
|
|
-- inst Instance to be modified (KEY_HASH)
|
|
-- istate New instance State
|
|
-- mem Target Memory
|
|
procedure change_istate(inst : INSTANCE_HANDLE_TYPE; istate : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); mem : inout DDS_READER_MEM_TYPE);
|
|
-- Add Sample to Memory
|
|
-- sample Sample to be added
|
|
-- mem Target Memory
|
|
-- DESTINATION_ORDER_QOS Determines the position where the Sample is added to the memory. If BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS the Sample is added
|
|
-- to the end of the memory. If BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS the Sample is positioned according to the source timestamp
|
|
-- of the Sample (Earliest first).
|
|
-- NOTE: This function sets the View State, Disposed Generation Count, and No Writers Generation Count of the added Sample
|
|
procedure add_sample(sample : inout SAMPLE_TYPE; mem : inout DDS_READER_MEM_TYPE; DESTINATION_ORDER_QOS : in std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0));
|
|
-- Remove Sample from Memory
|
|
-- ind Index position of Sample to be removed
|
|
-- mem Target Memory
|
|
procedure remove_sample(ind : in natural; mem : inout DDS_READER_MEM_TYPE);
|
|
-- Remove Instance from Memory
|
|
-- inst Instance to be removed (KEY_HASH)
|
|
-- mem Target Memory
|
|
procedure remove_inst(inst : in INSTANCE_HANDLE_TYPE; mem : inout DDS_READER_MEM_TYPE);
|
|
-- Check Instance State. returns TRUE if "istate" and "vstate" are equal to the instance State and View State of "inst" in "mem"
|
|
function check_instance(istate : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); vstate : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0); mem : DDS_READER_MEM_TYPE; inst : INSTANCE_HANDLE_TYPE) return boolean;
|
|
-- Return index position of Instance "inst" in "mem"
|
|
function find_instance(mem : DDS_READER_MEM_TYPE; inst : INSTANCE_HANDLE_TYPE) return natural;
|
|
-- Generate DDS Reader Sample Collection
|
|
-- mem Source Memory
|
|
-- col Generated Collection
|
|
-- inst Target Instance of samples in collection (Use HANDLE_NIL for all Instances)
|
|
-- sstate Target Sample State of samples in collection
|
|
-- istate Target Instance State of samples in collection
|
|
-- vstate Target View State of samples in collection
|
|
-- max_samples Maximum number of Samples in collection
|
|
-- remove If TRUE the selected samples are removed from the source memory "mem"
|
|
-- sort If TRUE the collection is sorted by Instance (Samples of the same Instance are consecutive, not depending on their in-memory order)
|
|
procedure gen_collection (mem : inout DDS_READER_MEM_TYPE; col : inout COLLECTION_TYPE; inst : INSTANCE_HANDLE_TYPE; sstate : in std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0); istate : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); vstate : in std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0); max_samples : in natural; remove : in boolean; sort : in boolean);
|
|
-- Wrapper of previous procedure. Extracts arguments from DDS Operation
|
|
-- mem Source Memory
|
|
-- col Generate Collection
|
|
-- opcode DDS Reader Operation
|
|
-- PRESENTATION_QOS Target PRESENTATION_QOS
|
|
-- ordered Ordered Value of PRESENTATION_QOS
|
|
procedure gen_collection (mem : inout DDS_READER_MEM_TYPE; col : inout COLLECTION_TYPE; opcode : in DDS_READER_TEST_TYPE; PRESENTATION_QOS : in std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); ordered : in boolean);
|
|
|
|
|
|
-- *HELPER FUNCTIONS*
|
|
-- Generate Random Locator
|
|
-- RV OSVVM Random Variable
|
|
-- ret Generated Random Locator
|
|
procedure gen_rand_loc(RV : inout RandomPType; ret : out LOCATOR_TYPE);
|
|
-- Generate Random EntityID
|
|
-- RV OSVVM Random Variable
|
|
-- reader If TRUE the generated ID has the prefix for Reader EntityIDs, else for Writer
|
|
-- ret Generated Random EntityID
|
|
procedure gen_rand_entityid(RV : inout RandomPType; reader : boolean; ret : out std_logic_vector(ENTITYID_WIDTH-1 downto 0));
|
|
-- Generate SLV from Integer
|
|
-- n Unsigned Value of generated SLV
|
|
-- width Width of generated SLV
|
|
function int(n : integer; width : natural) return std_logic_vector;
|
|
-- to_string Function for ScoreBoardPkg_builtin_endpoint
|
|
function to_string1 (input : std_logic_vector) return string;
|
|
-- Find first valid Locator of Particiapnt Data
|
|
-- ref Participant Data to extract Locator from
|
|
-- meta If TRUE extracts metatraffic Locator
|
|
-- NOTE: This assumes a specific sending order (Multicast before Unicast)!
|
|
function get_loc (ref : PARTICIPANT_DATA_TYPE; meta : boolean) return LOCATOR_TYPE;
|
|
-- Find first valid Locator of Endpoint Data
|
|
-- ref Endpoint Data to extract Locator from
|
|
function get_loc (ref : ENDPOINT_DATA_TYPE) return LOCATOR_TYPE;
|
|
-- Extract Data from Cache Change "cc" to generate a Sample.
|
|
-- cc Cache Change
|
|
-- istate Instance State of Sample
|
|
function to_sample(cc : CACHE_CHANGE_TYPE; istate : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0)) return SAMPLE_TYPE;
|
|
-- Return TRUE if both memory segments are equal, else FALSE
|
|
function test_memory_match (A,B : TEST_MEMORY_TYPE) return boolean;
|
|
-- Returns String with Length, Start Address, and End Address of the memory Segment
|
|
function to_string (input : TEST_MEMORY_TYPE) return string;
|
|
-- Generate Endpoint Data based on "id" of the test_config Package
|
|
function gen_endpoint(id : natural) return ENDPOINT_DATA_TYPE;
|
|
-- Generate all Reader (or Writer if "reader" is FALSE) Endpoints of the test_config Package
|
|
function gen_endpoint_array(readers : boolean) return ENDPOINT_DATA_ARRAY_TYPE;
|
|
-- Extract Data from RTPS Submessage (Sequence Number, Payload, Serialized_Key) and generate Cache Change
|
|
function gen_cache_change(ref : RTPS_SUBMESSAGE_TYPE) return CACHE_CHANGE_TYPE;
|
|
|
|
procedure gen_CDR(input : std_logic_vector; target_align : ALIGN_TYPE; align_offset : inout unsigned; output : inout TEST_PACKET_TYPE);
|
|
end package;
|
|
|
|
package body rtps_test_package is
|
|
|
|
-- *UTILITY FUNCTIONS*
|
|
procedure gen_rand_loc(RV : inout RandomPType; ret : out LOCATOR_TYPE) is
|
|
begin
|
|
ret := EMPTY_LOCATOR;
|
|
ret.kind := LOCATOR_KIND_UDPv4;
|
|
ret.portn(UDP_PORT_WIDTH-1 downto 0) := RV.RandSlv(UDP_PORT_WIDTH);
|
|
ret.addr(IPv4_ADDRESS_WIDTH-1 downto 0) := RV.RandSlv(IPv4_ADDRESS_WIDTH);
|
|
end procedure;
|
|
|
|
procedure gen_rand_entityid(RV : inout RandomPType; reader : boolean; ret : out std_logic_vector(ENTITYID_WIDTH-1 downto 0)) is
|
|
begin
|
|
ret := RV.RandSlv(ENTITYID_WIDTH);
|
|
ret(ENTITY_KIND_H_RANGE):= USER_DEFINED_ENTITY;
|
|
if (reader) then
|
|
ret(ENTITY_KIND_L_RANGE):= READER_NO_KEY;
|
|
else
|
|
ret(ENTITY_KIND_L_RANGE):= WRITER_NO_KEY;
|
|
end if;
|
|
end procedure;
|
|
|
|
function int(n : integer; width : natural) return std_logic_vector is
|
|
begin
|
|
return std_logic_vector(to_signed(n, width));
|
|
end function;
|
|
|
|
-- *DEFERRED DEFINITIONS*
|
|
|
|
constant DEFAULT_GUIDPREFIX : GUIDPREFIX_TYPE := (0 => x"da27cc3c", 1 => x"687ddcde", 2 => x"88bce3d1");
|
|
|
|
constant DEFAULT_READER_ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := x"b9cbad04";
|
|
constant DEFAULT_WRITER_ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := x"b9cbad03";
|
|
|
|
constant EMPTY_TEST_PACKET : TEST_PACKET_TYPE := (length => 0, data => (others => (others => '0')), last => (others => '0'));
|
|
|
|
constant EMPTY_LOCATOR : LOCATOR_TYPE := (
|
|
kind => LOCATOR_KIND_INVALID,
|
|
portn => (others => '0'),
|
|
addr => (others => '0')
|
|
);
|
|
|
|
constant EMPTY_LOCATOR_LIST : LOCATOR_LIST_TYPE := (
|
|
numLocators => (others => '0'),
|
|
locator => (others => EMPTY_LOCATOR)
|
|
);
|
|
|
|
constant DEFAULT_SEQUENCENUMBER_SET : SEQUENCENUMBER_SET_TYPE := (
|
|
base => FIRST_SEQUENCENUMBER,
|
|
numBits => (others => '0'),
|
|
bitmap => (others => '0')
|
|
);
|
|
|
|
constant DEFAULT_FRAGMENTNUMBER_SET : FRAGMENTNUMBER_SET_TYPE := (
|
|
base => int(1,CDR_LONG_WIDTH),
|
|
numBits => (others => '0'),
|
|
bitmap => (others => '0')
|
|
);
|
|
|
|
constant DEST_LOC : DEST_LOCATOR_LIST_TYPE := (
|
|
meta => (
|
|
numLocators => int(4,CDR_LONG_WIDTH),
|
|
locator => (
|
|
0 => (
|
|
kind => LOCATOR_KIND_UDPv4,
|
|
portn => (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & META_IPv4_MULTICAST_PORT,
|
|
addr => (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_META_ADDRESS
|
|
),
|
|
1 => (
|
|
kind => LOCATOR_KIND_UDPv4,
|
|
portn => (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & META_IPv4_UNICAST_PORT,
|
|
addr => (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_META_ADDRESS
|
|
),
|
|
2 => (
|
|
kind => LOCATOR_KIND_UDPv4,
|
|
portn => (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & META_IPv4_MULTICAST_PORT,
|
|
addr => (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_ADDRESS
|
|
),
|
|
3 => (
|
|
kind => LOCATOR_KIND_UDPv4,
|
|
portn => (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & META_IPv4_UNICAST_PORT,
|
|
addr => (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_ADDRESS
|
|
),
|
|
others => EMPTY_LOCATOR
|
|
)
|
|
),
|
|
user => (
|
|
numLocators => int(2,CDR_LONG_WIDTH),
|
|
locator => (
|
|
0 => (
|
|
kind => LOCATOR_KIND_UDPv4,
|
|
portn => (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & USER_IPv4_MULTICAST_PORT,
|
|
addr => (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_ADDRESS
|
|
),
|
|
1 => (
|
|
kind => LOCATOR_KIND_UDPv4,
|
|
portn => (UDP_PORT_WIDTH to LOCATOR_PORT_WIDTH-1 => '0') & USER_IPv4_UNICAST_PORT,
|
|
addr => (IPv4_ADDRESS_WIDTH to LOCATOR_ADDR_WIDTH-1 => '0') & DEFAULT_IPv4_ADDRESS
|
|
),
|
|
others => EMPTY_LOCATOR
|
|
)
|
|
)
|
|
);
|
|
|
|
constant DEFAULT_OUTPUT_HEADER : OUTPUT_HEADER_TYPE := (
|
|
src => EMPTY_LOCATOR,
|
|
dest => EMPTY_LOCATOR
|
|
);
|
|
|
|
constant DEFAULT_RTPS_HEADER : RTPS_HEADER_TYPE := (
|
|
protocol => PROTOCOL_RTPS,
|
|
version => PROTOCOLVERSION_2_4,
|
|
vendorId => VENDORID_UNKNOWN,
|
|
guidPrefix => DEFAULT_GUIDPREFIX
|
|
);
|
|
|
|
constant DEFAULT_RTPS_SUBMESSAGE : RTPS_SUBMESSAGE_TYPE := (
|
|
submessageID => (others => '0'),
|
|
flags => (others => '0'),
|
|
submessageLength => (others => '1'),
|
|
readerId => ENTITYID_UNKNOWN,
|
|
writerId => ENTITYID_UNKNOWN,
|
|
readerSNState => DEFAULT_SEQUENCENUMBER_SET,
|
|
count => int(1,COUNT_WIDTH),
|
|
extraFlags => (others => '0'),
|
|
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),
|
|
fragmentSize => (others => '0'),
|
|
sampleSize => (others => '0'),
|
|
gapStart => FIRST_SEQUENCENUMBER,
|
|
gapList => DEFAULT_SEQUENCENUMBER_SET,
|
|
firstSN => FIRST_SEQUENCENUMBER,
|
|
lastSN => (others => (others => '0')),
|
|
lastFragmentNum => int(1,CDR_LONG_WIDTH),
|
|
guidPrefix => DEFAULT_GUIDPREFIX,
|
|
unicastLocatorList => EMPTY_LOCATOR_LIST,
|
|
multicastLocatorList => EMPTY_LOCATOR_LIST,
|
|
unicastLocator => EMPTY_LOCATOR,
|
|
multicastLocator => EMPTY_LOCATOR,
|
|
unused => (others => '0'),
|
|
version => PROTOCOLVERSION_2_4,
|
|
vendorId => VENDORID_UNKNOWN,
|
|
timestamp => TIME_ZERO
|
|
);
|
|
|
|
constant DEFAULT_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE := (
|
|
littleEndian => '0',
|
|
domainId => DOMAIN_ID,
|
|
domainTag => DOMAIN_TAG,
|
|
protocolVersion => PROTOCOLVERSION_2_4,
|
|
vendorId => VENDORID_UNKNOWN,
|
|
guidPrefix => GUIDPREFIX_UNKNOWN,
|
|
entityId => ENTITYID_PARTICIPANT,
|
|
expectsInlineQoS => (others => '0'),
|
|
metatrafficUnicastLocatorList => EMPTY_LOCATOR_LIST,
|
|
metatrafficMulticastLocatorList => EMPTY_LOCATOR_LIST,
|
|
defaultUnicastLocatorList => EMPTY_LOCATOR_LIST, -- NOTE: Has to be initialized
|
|
defaultMulticastLocatorList => EMPTY_LOCATOR_LIST,
|
|
leaseDuration => PARTICIPANT_LEASE_DURATION,
|
|
manualLivelinessCount => (others => '0'),
|
|
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,
|
|
PREFER_MULTICAST => FALSE
|
|
);
|
|
|
|
constant THIS_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE := (
|
|
littleEndian => '0',
|
|
domainId => DOMAIN_ID,
|
|
domainTag => DOMAIN_TAG,
|
|
protocolVersion => PROTOCOLVERSION_2_4,
|
|
vendorId => VENDORID_UNKNOWN,
|
|
guidPrefix => GUIDPREFIX,
|
|
entityId => ENTITYID_PARTICIPANT,
|
|
expectsInlineQoS => (others => '0'),
|
|
metatrafficUnicastLocatorList => (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => DEST_LOC.meta.locator(3), others => EMPTY_LOCATOR)),
|
|
metatrafficMulticastLocatorList => (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => DEST_LOC.meta.locator(2), others => EMPTY_LOCATOR)),
|
|
defaultUnicastLocatorList => (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => DEST_LOC.user.locator(1), others => EMPTY_LOCATOR)),
|
|
defaultMulticastLocatorList => (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => DEST_LOC.user.locator(0), others => EMPTY_LOCATOR)),
|
|
leaseDuration => PARTICIPANT_LEASE_DURATION,
|
|
manualLivelinessCount => (others => '0'),
|
|
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,
|
|
PREFER_MULTICAST => FALSE
|
|
);
|
|
|
|
constant DEFAULT_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := (
|
|
reader => TRUE,
|
|
littleEndian => '0',
|
|
participant => DEFAULT_PARTICIPANT_DATA,
|
|
entityId => DEFAULT_READER_ENTITYID,
|
|
topic_name => EMPTY_STRING,
|
|
type_name => EMPTY_STRING,
|
|
durability => DEFAULT_DURABILITY_QOS,
|
|
durability_service_cleanup_delay => DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY,
|
|
durability_service_history => DEFAULT_DURABILITY_SERVICE_HISTORY,
|
|
durability_service_history_depth => DEFAULT_DURABILITY_SERVICE_HISTORY_DEPTH,
|
|
durability_service_max_samples => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES,
|
|
durability_service_max_instances => DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES,
|
|
durability_service_max_samples_per_instances => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE,
|
|
presentation => DEFAULT_PRESENTATION_QOS,
|
|
coherent_access => (0 => boolean_to_std_logic(DEFAULT_COHERENT_ACCESS), others => '0'),
|
|
ordered_access => (0 => boolean_to_std_logic(DEFAULT_ORDERED_ACCESS), others => '0'),
|
|
deadline => DEFAULT_DEADLINE_QOS,
|
|
latency_budget => DEFAULT_LATENCY_BUDGET_QOS,
|
|
ownership => DEFAULT_OWNERSHIP_QOS,
|
|
ownership_strength => DEFAULT_OWNERSHIP_STRENGTH_QOS,
|
|
liveliness => DEFAULT_LIVELINESS_QOS,
|
|
leaseDuration => DEFAULT_LEASE_DURATION,
|
|
time_based_filter => DEFAULT_TIME_BASED_FILTER_QOS,
|
|
reliability => DEFAULT_RELIABILITY_QOS_R,
|
|
max_blocking_time => DEFAULT_MAX_BLOCKING_TIME,
|
|
lifespan => DEFAULT_LIFESPAN_QOS,
|
|
destination_order => DEFAULT_DESTINATION_ORDER_QOS,
|
|
user_data => EMPTY_STRING,
|
|
topic_data => EMPTY_STRING,
|
|
group_data => EMPTY_STRING,
|
|
expectsInlineQoS => (others => '0'),
|
|
unicastLocatorList => EMPTY_LOCATOR_LIST,
|
|
multicastLocatorList => EMPTY_LOCATOR_LIST,
|
|
max_size_serialized => (others => '0'),
|
|
match => MATCH,
|
|
nr => 0
|
|
);
|
|
|
|
constant DEFAULT_CACHE_CHANGE : CACHE_CHANGE_TYPE := (
|
|
serialized_key => FALSE,
|
|
kind => ALIVE,
|
|
writer_guid => GUID_UNKNOWN,
|
|
instance => HANDLE_NIL,
|
|
seq_nr => SEQUENCENUMBER_UNKNOWN,
|
|
src_timestamp => TIME_INVALID,
|
|
payload => EMPTY_TEST_PACKET
|
|
);
|
|
|
|
constant DEFAULT_SAMPLE : SAMPLE_TYPE := (
|
|
inst => HANDLE_NIL,
|
|
data => EMPTY_TEST_PACKET,
|
|
sstate => NOT_READ_SAMPLE_STATE,
|
|
istate => ALIVE_INSTANCE_STATE,
|
|
vstate => NEW_VIEW_STATE,
|
|
dis_gen_cnt => 0,
|
|
no_w_gen_cnt => 0,
|
|
srank => 0,
|
|
grank => 0,
|
|
agrank => 0,
|
|
ts => TIME_INVALID
|
|
);
|
|
|
|
constant DEFAULT_COLLECTION : COLLECTION_TYPE := (
|
|
s => (others => DEFAULT_SAMPLE),
|
|
len => 0
|
|
);
|
|
|
|
constant DEFAULT_INSTANCE_CACHE_TYPE : INSTANCE_CACHE_TYPE := (
|
|
inst => HANDLE_NIL,
|
|
istate => ALIVE_INSTANCE_STATE,
|
|
vstate => NEW_VIEW_STATE,
|
|
dis_gen_cnt => 0,
|
|
no_w_gen_cnt => 0
|
|
);
|
|
|
|
constant DEFAULT_DDS_READER_MEM : DDS_READER_MEM_TYPE := (
|
|
s => (others => DEFAULT_SAMPLE),
|
|
slen => 0,
|
|
inst => (others => DEFAULT_INSTANCE_CACHE_TYPE),
|
|
ilen => 0
|
|
);
|
|
|
|
constant DEFAULT_DDS_READER_TEST : DDS_READER_TEST_TYPE := (
|
|
opcode => NOP,
|
|
sstate => ANY_SAMPLE_STATE,
|
|
istate => ANY_INSTANCE_STATE,
|
|
vstate => ANY_VIEW_STATE,
|
|
max_samples => 1,
|
|
inst => HANDLE_NIL,
|
|
ret_code => RETCODE_OK,
|
|
count => 0,
|
|
change => 0,
|
|
last_reason => NOT_REJECTED
|
|
);
|
|
|
|
constant DEFAULT_RTPS_WRITER_TEST : RTPS_WRITER_TEST_TYPE := (
|
|
opcode => NOP,
|
|
cc => DEFAULT_CACHE_CHANGE,
|
|
ret_code => OK
|
|
);
|
|
|
|
constant DEFAULT_RTPS_READER_TEST : RTPS_READER_TEST_TYPE := (
|
|
opcode => NOP,
|
|
cc => DEFAULT_CACHE_CHANGE,
|
|
lifespan => DURATION_INFINITE,
|
|
writer_pos => 0,
|
|
ret_code => OK
|
|
);
|
|
|
|
constant DEFAULT_DDS_WRITER_TEST : DDS_WRITER_TEST_TYPE := (
|
|
opcode => NOP,
|
|
cc => DEFAULT_CACHE_CHANGE,
|
|
ret_code => RETCODE_OK,
|
|
count => 0,
|
|
change => 0,
|
|
inst => HANDLE_NIL,
|
|
assertion => '0'
|
|
);
|
|
|
|
-- *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
|
|
begin
|
|
output.data(output.length)((BYTE_WIDTH*out_off)+BYTE_WIDTH-1 downto (BYTE_WIDTH*out_off)) := input((BYTE_WIDTH*in_off)+BYTE_WIDTH-1 downto (BYTE_WIDTH*in_off));
|
|
end procedure;
|
|
|
|
procedure gen_output_header(ref : in OUTPUT_HEADER_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- IPv4 Source Address
|
|
output.data(output.length) := ref.src.addr(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
output.length := output.length + 1;
|
|
-- IPv4 Destination Address
|
|
output.data(output.length) := ref.dest.addr(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
output.length := output.length + 1;
|
|
-- Source Port & Destination Port
|
|
output.data(output.length) := ref.src.portn(UDP_PORT_WIDTH-1 downto 0) & ref.dest.portn(UDP_PORT_WIDTH-1 downto 0);
|
|
output.length := output.length + 1;
|
|
-- Packet Length
|
|
output.data(output.length) := (others => '0');
|
|
output.length := output.length + 1;
|
|
end procedure;
|
|
|
|
procedure fix_output_packet(output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
assert (output.length < 2**UDP_PORT_WIDTH) report "Exceeded maximum UDP Packet Size" severity error;
|
|
-- Fix Packet Length
|
|
output.data(3) := int(output.length-4, WORD_WIDTH);
|
|
end procedure;
|
|
|
|
procedure gen_rtps_header( ref : in RTPS_HEADER_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- Protocol
|
|
output.data(output.length) := ref.protocol;
|
|
output.length := output.length + 1;
|
|
-- Protocol Version & Vendor ID
|
|
output.data(output.length) := ref.version & ref.vendorId;
|
|
output.length := output.length + 1;
|
|
-- GUID Prefix
|
|
output.data(output.length) := ref.guidPrefix(0);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(1);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(2);
|
|
output.length := output.length + 1;
|
|
end procedure;
|
|
|
|
procedure write_sequence_ns(input : in SEQUENCENUMBER_SET_TYPE; littleEndian : in std_logic; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- Sequence Number State (Base)
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(input.base(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(input.base(1)));
|
|
output.length := output.length + 1;
|
|
-- Sequence Number State (NumBits)
|
|
assert (unsigned(input.numBits) <= 256) report "SequenceNS.numbits is higher than 256." severity warning;
|
|
output.data(output.length) := endian_swap(littleEndian, input.numBits);
|
|
output.length := output.length + 1;
|
|
-- Sequence Number State (Bitmap)
|
|
for i in 0 to round_div(to_integer(unsigned(input.numBits)),WORD_WIDTH)-1 loop
|
|
if (i < MAX_BITMAP_WIDTH/WORD_WIDTH) then
|
|
output.data(output.length) := endian_swap(littleEndian, input.bitmap(i*32 to i*32+31));
|
|
output.length := output.length + 1;
|
|
end if;
|
|
end loop;
|
|
end procedure;
|
|
|
|
procedure write_fragment_ns(input : in FRAGMENTNUMBER_SET_TYPE; littleEndian : in std_logic; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- Sequence Number State (Base)
|
|
output.data(output.length) := endian_swap(littleEndian, input.base);
|
|
output.length := output.length + 1;
|
|
-- Sequence Number State (NumBits)
|
|
assert (unsigned(input.numBits) <= 256) report "SequenceNS.numbits is higher than 256." severity warning;
|
|
output.data(output.length) := endian_swap(littleEndian, input.numBits);
|
|
output.length := output.length + 1;
|
|
-- Sequence Number State (Bitmap)
|
|
for i in 0 to round_div(to_integer(unsigned(input.numBits)),WORD_WIDTH)-1 loop
|
|
if (i < MAX_BITMAP_WIDTH/WORD_WIDTH) then
|
|
output.data(output.length) := endian_swap(littleEndian, input.bitmap(i*32 to i*32+31));
|
|
output.length := output.length + 1;
|
|
end if;
|
|
end loop;
|
|
end procedure;
|
|
|
|
procedure write_locator_list(input : in LOCATOR_LIST_TYPE; littleEndian : in std_logic; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- NumLocators
|
|
output.data(output.length) := endian_swap(littleEndian, input.numLocators);
|
|
output.length := output.length + 1;
|
|
for i in 0 to to_integer(unsigned(input.numLocators))-1 loop
|
|
-- Kind
|
|
output.data(output.length) := endian_swap(littleEndian, input.locator(i).kind);
|
|
output.length := output.length + 1;
|
|
-- Port
|
|
output.data(output.length) := endian_swap(littleEndian, input.locator(i).portn);
|
|
output.length := output.length + 1;
|
|
-- Address
|
|
output.data(output.length) := input.locator(i).addr(127 downto 96);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := input.locator(i).addr(95 downto 64);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := input.locator(i).addr(63 downto 32);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := input.locator(i).addr(31 downto 0);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
end procedure;
|
|
|
|
function is_valid_loc (ref : LOCATOR_TYPE) return boolean is
|
|
begin
|
|
if (ref.kind /= LOCATOR_KIND_UDPv4) then
|
|
return FALSE;
|
|
elsif (ref.addr(IPv4_ADDRESS_WIDTH-1 downto 0) = IPv4_ADDRESS_INVALID) then
|
|
return FALSE;
|
|
elsif (ref.portn(UDP_PORT_WIDTH-1 downto 0) = UDP_PORT_INVALID) then
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
end if;
|
|
end function;
|
|
|
|
function get_loc (ref : LOCATOR_LIST_TYPE) return LOCATOR_TYPE is
|
|
variable ret : LOCATOR_TYPE := EMPTY_LOCATOR;
|
|
begin
|
|
for i in 0 to to_integer(unsigned(ref.numLocators))-1 loop
|
|
if (is_valid_loc(ref.locator(i))) then
|
|
ret := ref.locator(i);
|
|
end if;
|
|
end loop;
|
|
|
|
return ret;
|
|
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 (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
|
|
-- 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 (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
|
|
-- 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 (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
|
|
-- 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;
|
|
|
|
procedure gen_rtps_submessage( ref : in RTPS_SUBMESSAGE_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
variable start : natural := 0;
|
|
variable tmp : natural := 0;
|
|
begin
|
|
-- *GENERAL*
|
|
start := output.length;
|
|
-- Submessage ID & Submessage Flags & Submessage Length
|
|
output.data(output.length) := ref.submessageID & ref.flags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.submessageLength);
|
|
output.length := output.length + 1;
|
|
|
|
-- *DATA/DATA_FRAG*
|
|
if (ref.submessageID = SID_DATA or ref.submessageID = SID_DATA_FRAG) then
|
|
-- Extra Flags & octetsToInlineQos
|
|
output.data(output.length) := ref.extraFlags & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.octetsToInlineQos);
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- *ACKNACK/NACK_FRAG/HEARTBEAT/HEARTBEAT_FRAG/GAP/DATA/DATA_FRAG*
|
|
if (ref.submessageID = SID_ACKNACK or ref.submessageID = SID_NACK_FRAG or ref.submessageID = SID_HEARTBEAT or ref.submessageID = SID_HEARTBEAT_FRAG or ref.submessageID = SID_GAP or ref.submessageID = SID_DATA or ref.submessageID = SID_DATA_FRAG) then
|
|
-- Reader ID
|
|
output.data(output.length) := ref.readerId;
|
|
output.length := output.length + 1;
|
|
-- Writer ID
|
|
output.data(output.length) := ref.writerId;
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- *NACK_FRAG/DATA/DATA_FRAG/HEARTBEAT_FRAG*
|
|
if (ref.submessageID = SID_NACK_FRAG or ref.submessageID = SID_DATA or ref.submessageID = SID_DATA_FRAG or ref.submessageID = SID_HEARTBEAT_FRAG) then
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.writerSN(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.writerSN(1)));
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- *ACKNACK*
|
|
if (ref.submessageID = SID_ACKNACK) then
|
|
-- Reader State
|
|
write_sequence_ns(ref.readerSNState, ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), output);
|
|
-- *NACK_FRAG*
|
|
elsif (ref.submessageID = SID_NACK_FRAG) then
|
|
-- Fragment Number State
|
|
write_fragment_ns(ref.fragmentNumberState, ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), output);
|
|
-- *HEARTBEAT*
|
|
elsif (ref.submessageID = SID_HEARTBEAT) then
|
|
-- First Sequence Number
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.firstSN(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.firstSN(1)));
|
|
output.length := output.length + 1;
|
|
-- Last Sequence Number
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.lastSN(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.lastSN(1)));
|
|
output.length := output.length + 1;
|
|
-- *HEARTBEAT_FRAG*
|
|
elsif (ref.submessageID = SID_HEARTBEAT_FRAG) then
|
|
-- Last Fargment Number
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.lastFragmentNum);
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- *ACKNACK/NACK_FRAG/HEARTBEAT/HEARTBEAT_FRAG*
|
|
if (ref.submessageID = SID_ACKNACK or ref.submessageID = SID_HEARTBEAT or ref.submessageID = SID_NACK_FRAG or ref.submessageID = SID_HEARTBEAT_FRAG) then
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.count);
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- *GAP*
|
|
if (ref.submessageID = SID_GAP) then
|
|
-- Gap Start
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.gapStart(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.gapStart(1)));
|
|
output.length := output.length + 1;
|
|
-- Gap List
|
|
write_sequence_ns(ref.gapList, ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), output);
|
|
end if;
|
|
|
|
-- *DATA_FRAG*
|
|
if (ref.submessageID = SID_DATA_FRAG) then
|
|
-- Fragment Number
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.fragmentStartingNumber);
|
|
output.length := output.length + 1;
|
|
-- FragmentsinSubmessage & FragmentSize
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.fragmentsInSubmessage) & endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.fragmentSize);
|
|
output.length := output.length + 1;
|
|
-- Sample Size
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.sampleSize);
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- *DATA/DATA_FRAG*
|
|
if (ref.submessageID = SID_DATA or ref.submessageID = SID_DATA_FRAG) then
|
|
-- EXTRA HEADER
|
|
tmp := to_integer(unsigned(ref.octetsToInlineQos)) - 16;
|
|
if (tmp > 0) then
|
|
for i in 0 to tmp-1 loop
|
|
store_byte((i+1) mod 4, x"DEADBEEF", (i+1) mod 4, output);
|
|
if (i mod 4 = 3) then
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := (others => '0');
|
|
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
|
|
store_byte((i+tmp) mod 4, ref.data.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;
|
|
-- Fix Alignement
|
|
if ((tmp + (ref.data.length*4)) mod 4 /= 0) then
|
|
output.length := output.length + 1;
|
|
end if;
|
|
end if;
|
|
|
|
-- *INFO_SRC*
|
|
if (ref.submessageID = SID_INFO_SRC) then
|
|
-- UNUSED
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.unused);
|
|
output.length := output.length + 1;
|
|
-- Protocol Version & Vendor ID
|
|
output.data(output.length) := ref.version & ref.vendorId;
|
|
output.length := output.length + 1;
|
|
-- *INFO_REPLY*
|
|
elsif (ref.submessageID = SID_INFO_REPLY) then
|
|
write_locator_list(ref.unicastLocatorList, ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), output);
|
|
if (ref.flags(SUBMESSAGE_MULTICAST_FLAG_POS) = '1') then
|
|
write_locator_list(ref.multicastLocatorList, ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), output);
|
|
end if;
|
|
-- *INFO_REPLY_IP4*
|
|
elsif (ref.submessageID = SID_INFO_REPLY_IP4) then
|
|
-- Unicast Locator (Address)
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.unicastLocator.addr(CDR_LONG_WIDTH-1 downto 0));
|
|
output.length := output.length + 1;
|
|
-- Unicast Locator (Port)
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.unicastLocator.portn);
|
|
output.length := output.length + 1;
|
|
if (ref.flags(SUBMESSAGE_MULTICAST_FLAG_POS) = '1') then
|
|
-- Multicast Locator (Address)
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.multicastLocator.addr(CDR_LONG_WIDTH-1 downto 0));
|
|
output.length := output.length + 1;
|
|
-- Multicast Locator (Port)
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), ref.multicastLocator.portn);
|
|
output.length := output.length + 1;
|
|
end if;
|
|
-- *INFO_TS*
|
|
elsif (ref.submessageID = SID_INFO_TS) then
|
|
-- Timestamp
|
|
if (ref.flags(SUBMESSAGE_INVALIDATE_FLAG_POS) = '0') then
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.timestamp(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), std_logic_vector(ref.timestamp(1)));
|
|
output.length := output.length + 1;
|
|
end if;
|
|
end if;
|
|
|
|
-- *INFO_DEST/INFO_SRC*
|
|
if (ref.submessageID = SID_INFO_DST or ref.submessageID = SID_INFO_SRC) then
|
|
-- GUID Prefix
|
|
output.data(output.length) := ref.guidPrefix(0);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(1);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(2);
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- *ACKNACK/NACK_FRAG/HEARTBEAT/HEARTBEAT_FRAG/GAP/DATA/DATA_FRAG*
|
|
if (ref.submessageID = SID_ACKNACK or ref.submessageID = SID_NACK_FRAG or ref.submessageID = SID_HEARTBEAT or ref.submessageID = SID_HEARTBEAT_FRAG or ref.submessageID = SID_GAP or ref.submessageID = SID_DATA or ref.submessageID = SID_DATA_FRAG or ref.submessageID = SID_INFO_TS or ref.submessageID = SID_INFO_SRC or ref.submessageID = SID_INFO_DST or ref.submessageID = SID_INFO_REPLY or ref.submessageID =SID_INFO_REPLY_IP4) then
|
|
-- NOTE: A Submessage Length of 0 is left as is.
|
|
-- Fix Submessage Length
|
|
if (ref.submessageLength = (ref.submessageLength'reverse_range => '1')) then
|
|
output.data(start)(SUBMESSAGE_LENGTH_WIDTH-1 downto 0) := endian_swap(ref.flags(SUBMESSAGE_ENDIAN_FLAG_POS), int((output.length-start-1)*4,SUBMESSAGE_LENGTH_WIDTH));
|
|
-- Fix(Truncate/Extend) Packet Length to specified Length
|
|
elsif (ref.submessageLength /= (ref.submessageLength'reverse_range => '0')) then
|
|
output.length := start + to_integer(unsigned(ref.submessageLength));
|
|
end if;
|
|
-- *PAD/UKNOWN*
|
|
else
|
|
-- Padding
|
|
tmp := to_integer(unsigned(ref.submessageLength));
|
|
assert (tmp mod 4 = 0) report "Padding Length has to be multiple of four" severity FAILURE;
|
|
for i in 0 to (tmp/4)-1 loop
|
|
output.data(output.length) := (others => '0');
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
end if;
|
|
end procedure;
|
|
|
|
procedure gen_rtps_handler_out(ref : in RTPS_SUBMESSAGE_TYPE; loc : in LOCATOR_TYPE; is_meta : in boolean; ts : in TIME_TYPE; src_guid : in GUIDPREFIX_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- Opcode & Flags & Source Port
|
|
output.data(output.length) := ref.submessageID & ref.flags & loc.portn(UDP_PORT_WIDTH-1 downto 0);
|
|
output.length := output.length + 1;
|
|
-- Source Address
|
|
output.data(output.length) := loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
output.length := output.length + 1;
|
|
-- Source GUID Prefix
|
|
output.data(output.length) := src_guid(0);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := src_guid(1);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := src_guid(2);
|
|
output.length := output.length + 1;
|
|
-- Source Entity ID
|
|
if (ref.submessageID = SID_ACKNACK or ref.submessageID = SID_NACK_FRAG) then
|
|
output.data(output.length) := ref.readerId;
|
|
output.length := output.length + 1;
|
|
else
|
|
output.data(output.length) := ref.writerId;
|
|
output.length := output.length + 1;
|
|
end if;
|
|
-- Destination Enity ID
|
|
if (is_meta) then
|
|
if (ref.submessageID = SID_ACKNACK or ref.submessageID = SID_NACK_FRAG) then
|
|
output.data(output.length) := ref.writerId;
|
|
output.length := output.length + 1;
|
|
else
|
|
output.data(output.length) := ref.readerId;
|
|
output.length := output.length + 1;
|
|
end if;
|
|
end if;
|
|
|
|
-- *DATA*
|
|
if (ref.submessageID = SID_DATA) then
|
|
-- Sequence Number
|
|
output.data(output.length) := std_logic_vector(ref.writerSN(0));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := std_logic_vector(ref.writerSN(1));
|
|
output.length := output.length + 1;
|
|
-- Timestamp
|
|
if (not is_meta) then
|
|
output.data(output.length) := std_logic_vector(ts(0));
|
|
output.length := output.length + 1;
|
|
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
|
|
output.data(output.length) := ref.data.data(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
end if;
|
|
end if;
|
|
|
|
-- *ACKNACK*
|
|
if (ref.submessageID = SID_ACKNACK) then
|
|
-- Reader State
|
|
write_sequence_ns(ref.readerSNState, '0', output);
|
|
-- *HEARTBEAT*
|
|
elsif (ref.submessageID = SID_HEARTBEAT) then
|
|
-- First Sequence Number
|
|
output.data(output.length) := std_logic_vector(ref.firstSN(0));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := std_logic_vector(ref.firstSN(1));
|
|
output.length := output.length + 1;
|
|
-- Last Sequence Number
|
|
output.data(output.length) := std_logic_vector(ref.lastSN(0));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := std_logic_vector(ref.lastSN(1));
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- *ACKNACK/HEARTBEAT*
|
|
if (ref.submessageID = SID_ACKNACK or ref.submessageID = SID_HEARTBEAT) then
|
|
output.data(output.length) := ref.count;
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- *GAP*
|
|
if (ref.submessageID = SID_GAP) then
|
|
-- Gap Start
|
|
output.data(output.length) := std_logic_vector(ref.gapStart(0));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := std_logic_vector(ref.gapStart(1));
|
|
output.length := output.length + 1;
|
|
-- Gap List
|
|
write_sequence_ns(ref.gapList, '0', output);
|
|
-- UNUSED
|
|
output.data(output.length) := (others => '0');
|
|
output.length := output.length + 1;
|
|
end if;
|
|
|
|
-- Mark Last Word
|
|
output.last(output.length-1) := '1';
|
|
end procedure;
|
|
|
|
procedure gen_rtps_handler_out(ref : in RTPS_SUBMESSAGE_TYPE; participant : PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
gen_rtps_handler_out(ref, get_loc(participant, TRUE), TRUE, TIME_INVALID, participant.guidPrefix, output);
|
|
end procedure;
|
|
|
|
procedure gen_rtps_handler_out(ref : in RTPS_SUBMESSAGE_TYPE; endpoint : ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
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_DATA_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
|
|
output.data(output.length) := CDR_BE & x"0000";
|
|
output.length := output.length + 1;
|
|
-- GUID Prefix
|
|
output.data(output.length) := participant.guidPrefix(0);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := participant.guidPrefix(1);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := participant.guidPrefix(2);
|
|
output.length := output.length + 1;
|
|
-- Participant Message Kind
|
|
if (manual) then
|
|
output.data(output.length) := PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE;
|
|
else
|
|
output.data(output.length) := PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE;
|
|
end if;
|
|
output.length := output.length + 1;
|
|
-- DATA Length
|
|
output.data(output.length) := int(extra_data.length, WORD_WIDTH);
|
|
output.length := output.length + 1;
|
|
for i in 0 to extra_data.length-1 loop
|
|
output.data(output.length) := extra_data.data(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
end procedure;
|
|
|
|
procedure gen_liveliness_assertion(participant : in PARTICIPANT_DATA_TYPE; manual : in boolean; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
gen_liveliness_assertion(participant, manual, EMPTY_TEST_PACKET, output);
|
|
end procedure;
|
|
|
|
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) is
|
|
variable tmp : natural := 0;
|
|
begin
|
|
-- Representation Identifier & Representation Options
|
|
if (ref.littleEndian = '0') then
|
|
output.data(output.length) := PL_CDR_BE & x"0000";
|
|
else
|
|
output.data(output.length) := PL_CDR_LE & x"0000";
|
|
end if;
|
|
output.length := output.length + 1;
|
|
-- GUID
|
|
if (pid = PID_PARTICIPANT_GUID) then
|
|
assert (16+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PARTICIPANT_GUID) & endian_swap(ref.littleEndian, int(16+(offset*4), PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PARTICIPANT_GUID) & endian_swap(ref.littleEndian, int(16, PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(0);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(1);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(2);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.entityId;
|
|
output.length := output.length + 1;
|
|
if (pid = PID_PARTICIPANT_GUID) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
-- DOMAIN ID
|
|
if (pid = PID_DOMAIN_ID) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DOMAIN_ID) & endian_swap(ref.littleEndian, int(4+(offset*4), PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DOMAIN_ID) & endian_swap(ref.littleEndian, int(4, PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.domainId);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DOMAIN_ID) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
-- DOMAIN TAG
|
|
if (ref.domainTag /= DEFAULT_DOMAIN_TAG or pid = PID_DOMAIN_TAG) then
|
|
tmp := string_len(ref.domainTag);
|
|
if (pid = PID_DOMAIN_TAG) then
|
|
assert (((round_div(tmp,4)+1)*4)+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DOMAIN_TAG) & endian_swap(ref.littleEndian, int(((round_div(tmp,4)+1)*4)+(offset*4), PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DOMAIN_TAG) & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4, PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, int(tmp, CDR_LONG_WIDTH));
|
|
output.length := output.length + 1;
|
|
for i in 0 to round_div(tmp,4)-1 loop
|
|
output.data(output.length) := ref.domainTag(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
if (pid = PID_DOMAIN_TAG) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- PROTOCOL VERSION
|
|
if (pid = PID_PROTOCOL_VERSION) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PROTOCOL_VERSION) & endian_swap(ref.littleEndian, int(4+(offset*4), PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PROTOCOL_VERSION) & endian_swap(ref.littleEndian, int(4, PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := (others => '0');
|
|
output.data(output.length)(31 downto 16) := ref.protocolVersion;
|
|
output.length := output.length + 1;
|
|
if (pid = PID_PROTOCOL_VERSION) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
-- VENDORID
|
|
if (pid = PID_VENDORID) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_VENDORID) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_VENDORID) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := (others => '0');
|
|
output.data(output.length)(31 downto 16) := ref.vendorId;
|
|
output.length := output.length + 1;
|
|
if (pid = PID_VENDORID) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
-- EXPECTS IN-LINE QOS
|
|
if (ref.expectsInlineQoS(0) /= DEFAULT_EXPECTS_INLINE_QOS or pid = PID_EXPECTS_INLINE_QOS) then
|
|
if (pid = PID_EXPECTS_INLINE_QOS) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_EXPECTS_INLINE_QOS) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_EXPECTS_INLINE_QOS) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := (others => '0');
|
|
output.data(output.length)(31 downto 24) := ref.expectsInlineQoS; -- 1 Byte, No endian swap
|
|
output.length := output.length + 1;
|
|
if (pid = PID_EXPECTS_INLINE_QOS) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- METATRAFFIC MULTICAST LOCATOR
|
|
if (ref.metatrafficMulticastLocatorList.numLocators /= (ref.metatrafficMulticastLocatorList.numLocators'reverse_range => '0')) then
|
|
tmp := to_integer(unsigned(ref.metatrafficMulticastLocatorList.numLocators));
|
|
for i in 0 to tmp-1 loop
|
|
if (pid = PID_METATRAFFIC_MULTICAST_LOCATOR) then
|
|
assert (24+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_METATRAFFIC_MULTICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_METATRAFFIC_MULTICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.locator(i).kind);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficMulticastLocatorList.locator(i).portn);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(127 downto 96);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(95 downto 64);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(63 downto 32);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.metatrafficMulticastLocatorList.locator(i).addr(31 downto 0);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_METATRAFFIC_MULTICAST_LOCATOR) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
-- METATRAFFIC UNICAST LOCATOR
|
|
if (ref.metatrafficUnicastLocatorList.numLocators /= (ref.metatrafficUnicastLocatorList.numLocators'reverse_range => '0')) then
|
|
tmp := to_integer(unsigned(ref.metatrafficUnicastLocatorList.numLocators));
|
|
for i in 0 to tmp-1 loop
|
|
if (pid = PID_METATRAFFIC_UNICAST_LOCATOR) then
|
|
assert (24+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_METATRAFFIC_UNICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_METATRAFFIC_UNICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficUnicastLocatorList.locator(i).kind);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.metatrafficUnicastLocatorList.locator(i).portn);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.metatrafficUnicastLocatorList.locator(i).addr(127 downto 96);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.metatrafficUnicastLocatorList.locator(i).addr(95 downto 64);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.metatrafficUnicastLocatorList.locator(i).addr(63 downto 32);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.metatrafficUnicastLocatorList.locator(i).addr(31 downto 0);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_METATRAFFIC_UNICAST_LOCATOR) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
-- DEFAULT MULTICAST LOCATOR
|
|
if (ref.defaultMulticastLocatorList.numLocators /= (ref.defaultMulticastLocatorList.numLocators'reverse_range => '0')) then
|
|
tmp := to_integer(unsigned(ref.defaultMulticastLocatorList.numLocators));
|
|
for i in 0 to tmp-1 loop
|
|
if (pid = PID_DEFAULT_MULTICAST_LOCATOR) then
|
|
assert (24+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DEFAULT_MULTICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DEFAULT_MULTICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.locator(i).kind);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultMulticastLocatorList.locator(i).portn);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(127 downto 96);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(95 downto 64);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(63 downto 32);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.defaultMulticastLocatorList.locator(i).addr(31 downto 0);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DEFAULT_MULTICAST_LOCATOR) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
-- DEFAULT UNICAST LOCATOR
|
|
assert (unsigned(ref.defaultUnicastLocatorList.numLocators) > 0) report "PARTICIPANT_DATA: Participant needs to have at least one Default Unicast Locator." severity error;
|
|
if (ref.defaultUnicastLocatorList.numLocators /= (ref.defaultUnicastLocatorList.numLocators'reverse_range => '0')) then
|
|
tmp := to_integer(unsigned(ref.defaultUnicastLocatorList.numLocators));
|
|
for i in 0 to tmp-1 loop
|
|
if (pid = PID_DEFAULT_UNICAST_LOCATOR) then
|
|
assert (24+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DEFAULT_UNICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DEFAULT_UNICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultUnicastLocatorList.locator(i).kind);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.defaultUnicastLocatorList.locator(i).portn);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.defaultUnicastLocatorList.locator(i).addr(127 downto 96);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.defaultUnicastLocatorList.locator(i).addr(95 downto 64);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.defaultUnicastLocatorList.locator(i).addr(63 downto 32);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.defaultUnicastLocatorList.locator(i).addr(31 downto 0);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DEFAULT_UNICAST_LOCATOR) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
-- LEASE DURATION
|
|
if (ref.leaseDuration /= DEFAULT_PARTICIPANT_LEASE_DURATION or pid = PID_PARTICIPANT_LEASE_DURATION) then
|
|
if (pid = PID_PARTICIPANT_LEASE_DURATION) then
|
|
assert (8+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PARTICIPANT_LEASE_DURATION) & endian_swap(ref.littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PARTICIPANT_LEASE_DURATION) & 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(ref.leaseDuration(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.leaseDuration(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_PARTICIPANT_LEASE_DURATION) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- AVAILABLE ENDPOINTS
|
|
if (pid = PID_BUILTIN_ENDPOINT_SET) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_BUILTIN_ENDPOINT_SET) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_BUILTIN_ENDPOINT_SET) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.availableBuiltinEndpoints);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_BUILTIN_ENDPOINT_SET) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
-- BUILTIN ENDPOINT QOS
|
|
if (ref.builtinEndpointQoS /= DEFAULT_BUILTIN_ENDPOINT_QOS or pid = PID_BUILTIN_ENDPOINT_QOS) then
|
|
if (pid = PID_BUILTIN_ENDPOINT_QOS) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_BUILTIN_ENDPOINT_QOS) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_BUILTIN_ENDPOINT_QOS) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.builtinEndpointQoS);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_BUILTIN_ENDPOINT_QOS) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- MANUAL LIVELINESS COUNT
|
|
if (pid = PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.manualLivelinessCount);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end procedure;
|
|
|
|
procedure gen_participant_data( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
gen_participant_data(ref, output, PID_PAD, 0);
|
|
end procedure;
|
|
|
|
function gen_participant_mem_frame (ref : PARTICIPANT_DATA_TYPE) return TEST_PARTICIPANT_MEMORY_FRAME_TYPE is
|
|
variable ret : TEST_PARTICIPANT_MEMORY_FRAME_TYPE;
|
|
variable start : natural;
|
|
variable meta_loc : LOCATOR_TYPE;
|
|
variable user_loc : LOCATOR_TYPE;
|
|
begin
|
|
ret := (others => (addr => 0, data => (others => '0')));
|
|
|
|
-- Calculate Start Address
|
|
start := PARTICIPANT_FRAME_SIZE * ref.nr;
|
|
|
|
-- Fetch relevant Locators
|
|
meta_loc := get_loc (ref, TRUE);
|
|
user_loc := get_loc (ref, FALSE);
|
|
|
|
for i in 0 to PARTICIPANT_FRAME_SIZE-1 loop
|
|
ret(i).addr := start + i;
|
|
case (i) is
|
|
-- GUID Prefix 1/3
|
|
when 1 =>
|
|
ret(i).data := ref.guidPrefix(0);
|
|
-- GUID Prefix 2/3
|
|
when 2 =>
|
|
ret(i).data := ref.guidPrefix(1);
|
|
-- GUID Prefix 3/3
|
|
when 3 =>
|
|
ret(i).data := ref.guidPrefix(2);
|
|
-- METATRAFFIC IPv4 Address
|
|
when 4 =>
|
|
ret(i).data := meta_loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
-- DEFAULT IPv4 Address
|
|
when 5 =>
|
|
ret(i).data := user_loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
-- METATRAFFIC & DEFAULT UDP Port
|
|
when 6 =>
|
|
ret(i).data := meta_loc.portn(UDP_PORT_WIDTH-1 downto 0) & user_loc.portn(UDP_PORT_WIDTH-1 downto 0);
|
|
-- Lease Duration 1/2
|
|
when 9 =>
|
|
ret(i).data := std_logic_vector(ref.leaseDuration(0));
|
|
-- Lease Duration 2/2
|
|
when 10 =>
|
|
ret(i).data := std_logic_vector(ref.leaseDuration(1));
|
|
-- Other Fields Ignored
|
|
when others =>
|
|
ret(i).data := (others => '-');
|
|
end case;
|
|
end loop;
|
|
return ret;
|
|
end function;
|
|
|
|
function gen_writer_endpoint_mem_frame_a (ref : ENDPOINT_DATA_TYPE) return TEST_WRITER_ENDPOINT_MEMORY_FRAME_TYPE_A is
|
|
variable ret : TEST_WRITER_ENDPOINT_MEMORY_FRAME_TYPE_A;
|
|
variable start : natural;
|
|
variable user_loc : LOCATOR_TYPE;
|
|
begin
|
|
ret := (others => (addr => 0, data => (others => '0')));
|
|
|
|
-- Calculate Start Address
|
|
start := WRITER_ENDPOINT_FRAME_SIZE_A * ref.nr;
|
|
|
|
-- Fetch relevant Locators
|
|
user_loc := get_loc (ref);
|
|
|
|
for i in 0 to WRITER_ENDPOINT_FRAME_SIZE_A-1 loop
|
|
ret(i).addr := start + i;
|
|
case (i) is
|
|
-- Entity ID
|
|
when 0 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.entityId;
|
|
else
|
|
ret(i).data := (others => '0');
|
|
end if;
|
|
-- GUID Prefix 1/3
|
|
when 1 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(0);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- GUID Prefix 2/3
|
|
when 2 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(1);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- GUID Prefix 3/3
|
|
when 3 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(2);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- IPv4 Address
|
|
when 4 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := user_loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- UDP Port
|
|
when 5 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := user_loc.portn(UDP_PORT_WIDTH-1 downto 0) & UDP_PORT_INVALID;
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- Lifespan Duration 1/2
|
|
when 10 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := std_logic_vector(ref.lifespan(0));
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- Lifespan Duration 2/2
|
|
when 11 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := std_logic_vector(ref.lifespan(1));
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- Other Fields Ignored
|
|
when others =>
|
|
ret(i).data := (others => '-');
|
|
end case;
|
|
end loop;
|
|
return ret;
|
|
end function;
|
|
|
|
|
|
function gen_writer_endpoint_mem_frame_b (ref : ENDPOINT_DATA_TYPE) return TEST_WRITER_ENDPOINT_MEMORY_FRAME_TYPE_B is
|
|
variable ret : TEST_WRITER_ENDPOINT_MEMORY_FRAME_TYPE_B;
|
|
variable start : natural;
|
|
variable user_loc : LOCATOR_TYPE;
|
|
begin
|
|
ret := (others => (addr => 0, data => (others => '0')));
|
|
|
|
-- Calculate Start Address
|
|
start := WRITER_ENDPOINT_FRAME_SIZE_B * ref.nr;
|
|
|
|
-- Fetch relevant Locators
|
|
user_loc := get_loc (ref);
|
|
|
|
for i in 0 to WRITER_ENDPOINT_FRAME_SIZE_B-1 loop
|
|
ret(i).addr := start + i;
|
|
case (i) is
|
|
-- Entity ID
|
|
when 0 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.entityId;
|
|
else
|
|
ret(i).data := (others => '0');
|
|
end if;
|
|
-- GUID Prefix 1/3
|
|
when 1 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(0);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- GUID Prefix 2/3
|
|
when 2 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(1);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- GUID Prefix 3/3
|
|
when 3 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(2);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- Lifespan Duration 1/2
|
|
when 8 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := std_logic_vector(ref.lifespan(0));
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- Lifespan Duration 2/2
|
|
when 9 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := std_logic_vector(ref.lifespan(1));
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- Other Fields Ignored
|
|
when others =>
|
|
ret(i).data := (others => '-');
|
|
end case;
|
|
end loop;
|
|
return ret;
|
|
end function;
|
|
|
|
function gen_reader_endpoint_mem_frame_a (ref : ENDPOINT_DATA_TYPE) return TEST_READER_ENDPOINT_MEMORY_FRAME_TYPE_A is
|
|
variable ret : TEST_READER_ENDPOINT_MEMORY_FRAME_TYPE_A;
|
|
variable start : natural;
|
|
variable user_loc : LOCATOR_TYPE;
|
|
begin
|
|
ret := (others => (addr => 0, data => (others => '0')));
|
|
|
|
-- Calculate Start Address
|
|
start := READER_ENDPOINT_FRAME_SIZE_A * ref.nr;
|
|
|
|
-- Fetch relevant Locators
|
|
user_loc := get_loc (ref);
|
|
|
|
for i in 0 to READER_ENDPOINT_FRAME_SIZE_A-1 loop
|
|
ret(i).addr := start + i;
|
|
case (i) is
|
|
-- Entity ID
|
|
when 0 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.entityId;
|
|
else
|
|
ret(i).data := (others => '0');
|
|
end if;
|
|
-- GUID Prefix 1/3
|
|
when 1 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(0);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- GUID Prefix 2/3
|
|
when 2 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(1);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- GUID Prefix 3/3
|
|
when 3 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(2);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- IPv4 Address
|
|
when 4 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := user_loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- UDP Port
|
|
when 5 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := user_loc.portn(UDP_PORT_WIDTH-1 downto 0) & UDP_PORT_INVALID;
|
|
ret(i).data(READER_EXPECTS_INLINE_QOS_FLAG) := ref.expectsInlineQoS(0);
|
|
ret(i).data(READER_EXPECTS_HISTORICAL_DATA_FLAG) := '1' when (ref.durability /= VOLATILE_DURABILITY_QOS) else '0';
|
|
ret(i).data(READER_IS_BEST_EFFORT_FLAG) := '1' when (ref.reliability = BEST_EFFORT_RELIABILITY_QOS) else '0';
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- Other Fields Ignored
|
|
when others =>
|
|
ret(i).data := (others => '-');
|
|
end case;
|
|
end loop;
|
|
return ret;
|
|
end function;
|
|
|
|
function gen_reader_endpoint_mem_frame_b (ref : ENDPOINT_DATA_TYPE) return TEST_READER_ENDPOINT_MEMORY_FRAME_TYPE_B is
|
|
variable ret : TEST_READER_ENDPOINT_MEMORY_FRAME_TYPE_B;
|
|
variable start : natural;
|
|
variable user_loc : LOCATOR_TYPE;
|
|
begin
|
|
ret := (others => (addr => 0, data => (others => '0')));
|
|
|
|
-- Calculate Start Address
|
|
start := READER_ENDPOINT_FRAME_SIZE_B * ref.nr;
|
|
|
|
-- Fetch relevant Locators
|
|
user_loc := get_loc (ref);
|
|
|
|
for i in 0 to READER_ENDPOINT_FRAME_SIZE_B-1 loop
|
|
ret(i).addr := start + i;
|
|
case (i) is
|
|
-- Entity ID
|
|
when 0 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.entityId;
|
|
else
|
|
ret(i).data := (others => '0');
|
|
end if;
|
|
-- GUID Prefix 1/3
|
|
when 1 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(0);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- GUID Prefix 2/3
|
|
when 2 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(1);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- GUID Prefix 3/3
|
|
when 3 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := ref.participant.guidPrefix(2);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- IPv4 Address
|
|
when 4 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := user_loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- UDP Port
|
|
when 5 =>
|
|
if (ref.match = MATCH) then
|
|
ret(i).data := user_loc.portn(UDP_PORT_WIDTH-1 downto 0) & UDP_PORT_INVALID;
|
|
ret(i).data(READER_EXPECTS_INLINE_QOS_FLAG) := ref.expectsInlineQoS(0);
|
|
ret(i).data(READER_EXPECTS_HISTORICAL_DATA_FLAG) := '1' when (ref.durability /= VOLATILE_DURABILITY_QOS) else '0';
|
|
ret(i).data(READER_IS_BEST_EFFORT_FLAG) := '1' when (ref.reliability = BEST_EFFORT_RELIABILITY_QOS) else '0';
|
|
else
|
|
ret(i).data := (others => '-');
|
|
end if;
|
|
-- Other Fields Ignored
|
|
when others =>
|
|
ret(i).data := (others => '-');
|
|
end case;
|
|
end loop;
|
|
return ret;
|
|
end function;
|
|
|
|
procedure gen_participant_match_frame( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- OPCODE
|
|
case (ref.match) is
|
|
when MATCH =>
|
|
report "No Endpoint Frame generated on Participant match" severity WARNING;
|
|
return;
|
|
when UNMATCH =>
|
|
output.data(output.length) := EMO_PARTICIPANT_UNMATCH;
|
|
output.length := output.length + 1;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
-- GUID Prefix
|
|
output.data(output.length) := ref.guidPrefix(0);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(1);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(2);
|
|
output.length := output.length + 1;
|
|
|
|
-- Mark Last Word
|
|
output.last(output.length-1) := '1';
|
|
end procedure;
|
|
|
|
procedure gen_liveliness_update_frame( ref : in PARTICIPANT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- OPCODE
|
|
output.data(output.length) := EMO_LIVELINESS_UPDATE;
|
|
output.length := output.length + 1;
|
|
-- GUID Prefix
|
|
output.data(output.length) := ref.guidPrefix(0);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(1);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.guidPrefix(2);
|
|
output.length := output.length + 1;
|
|
|
|
-- Mark Last Word
|
|
output.last(output.length-1) := '1';
|
|
end procedure;
|
|
|
|
procedure gen_endpoint_data( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE; pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); offset : in integer) is
|
|
variable tmp : natural := 0;
|
|
begin
|
|
-- Representation Identifier & Representation Options
|
|
if (ref.littleEndian = '0') then
|
|
output.data(output.length) := PL_CDR_BE & x"0000";
|
|
else
|
|
output.data(output.length) := PL_CDR_LE & x"0000";
|
|
end if;
|
|
output.length := output.length + 1;
|
|
-- GUID
|
|
if (pid = PID_ENDPOINT_GUID) then
|
|
assert (16+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_ENDPOINT_GUID) & endian_swap(ref.littleEndian, int(16+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_ENDPOINT_GUID) & endian_swap(ref.littleEndian, int(16,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.participant.guidPrefix(0);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.participant.guidPrefix(1);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.participant.guidPrefix(2);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.entityId;
|
|
output.length := output.length + 1;
|
|
if (pid = PID_ENDPOINT_GUID) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
-- EXPECTS IN-LINE QOS
|
|
if (ref.reader) then
|
|
if (ref.expectsInlineQoS(0) /= DEFAULT_EXPECTS_INLINE_QOS or pid = PID_EXPECTS_INLINE_QOS) then
|
|
if (pid = PID_EXPECTS_INLINE_QOS) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_EXPECTS_INLINE_QOS) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_EXPECTS_INLINE_QOS) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := (others => '0');
|
|
output.data(output.length)(31 downto 24) := ref.expectsInlineQoS; -- 1 Byte, No endian swap
|
|
output.length := output.length + 1;
|
|
if (pid = PID_EXPECTS_INLINE_QOS) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- TOPIC NAME
|
|
tmp := string_len(ref.topic_name);
|
|
if (pid = PID_TOPIC_NAME) then
|
|
assert (((round_div(tmp,4)+1)*4)+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_TOPIC_NAME) & endian_swap(ref.littleEndian, int(((round_div(tmp,4)+1)*4)+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_TOPIC_NAME) & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, int(tmp, CDR_LONG_WIDTH));
|
|
output.length := output.length + 1;
|
|
for i in 0 to round_div(tmp,4)-1 loop
|
|
output.data(output.length) := ref.topic_name(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
if (pid = PID_TOPIC_NAME) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
-- TYPE NAME
|
|
tmp := string_len(ref.type_name);
|
|
if (pid = PID_TYPE_NAME) then
|
|
assert (((round_div(tmp,4)+1)*4)+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_TYPE_NAME) & endian_swap(ref.littleEndian, int(((round_div(tmp,4)+1)*4)+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_TYPE_NAME) & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, int(tmp,CDR_LONG_WIDTH));
|
|
output.length := output.length + 1;
|
|
for i in 0 to round_div(tmp,4)-1 loop
|
|
output.data(output.length) := ref.type_name(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
if (pid = PID_TYPE_NAME) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
-- DURABILITY
|
|
if (ref.durability /= DEFAULT_DURABILITY_QOS or pid = PID_DURABILITY) then
|
|
if (pid = PID_DURABILITY) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DURABILITY) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DURABILITY) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.durability);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DURABILITY) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- DURABILITY SERVICE
|
|
if (ref.durability_service_cleanup_delay /= DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY or ref.durability_service_history /= DEFAULT_DURABILITY_SERVICE_HISTORY or
|
|
ref.durability_service_history_depth /= DEFAULT_DURABILITY_SERVICE_HISTORY_DEPTH or ref.durability_service_max_samples /= DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES or
|
|
ref.durability_service_max_instances /= DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES or ref.durability_service_max_samples_per_instances /= DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE or pid = PID_DURABILITY_SERVICE) then
|
|
if (pid = PID_DURABILITY_SERVICE) then
|
|
assert (28+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DURABILITY_SERVICE) & endian_swap(ref.littleEndian, int(28+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DURABILITY_SERVICE) & endian_swap(ref.littleEndian, int(28,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.durability_service_cleanup_delay(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.durability_service_cleanup_delay(1)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.durability_service_history);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.durability_service_history_depth);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.durability_service_max_samples);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.durability_service_max_instances);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.durability_service_max_samples_per_instances);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DURABILITY_SERVICE) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- PRESENTATION
|
|
if (ref.presentation /= DEFAULT_PRESENTATION_QOS or ref.coherent_access(0) /= boolean_to_std_logic(DEFAULT_COHERENT_ACCESS) or ref.ordered_access(0) /= boolean_to_std_logic(DEFAULT_ORDERED_ACCESS) or pid = PID_PRESENTATION) then
|
|
if (pid = PID_PRESENTATION) then
|
|
assert (8+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PRESENTATION) & endian_swap(ref.littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_PRESENTATION) & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.presentation);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.coherent_access) & endian_swap(ref.littleEndian, ref.ordered_access) & (0 to 15 => '0');
|
|
output.length := output.length + 1;
|
|
if (pid = PID_PRESENTATION) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- DEADLINE
|
|
if (ref.deadline /= DEFAULT_DEADLINE_QOS or pid = PID_DEADLINE) then
|
|
if (pid = PID_DEADLINE) then
|
|
assert (8+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DEADLINE) & endian_swap(ref.littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DEADLINE) & 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(ref.deadline(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.deadline(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DEADLINE) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- LATENCY BUDGET
|
|
if (ref.latency_budget /= DEFAULT_LATENCY_BUDGET_QOS or pid = PID_LATENCY_BUDGET) then
|
|
if (pid = PID_LATENCY_BUDGET) then
|
|
assert (8+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_LATENCY_BUDGET) & endian_swap(ref.littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_LATENCY_BUDGET) & 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(ref.latency_budget(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.latency_budget(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_LATENCY_BUDGET) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- OWNERSHIP
|
|
if (ref.ownership /= DEFAULT_OWNERSHIP_QOS or pid = PID_OWNERSHIP) then
|
|
if (pid = PID_OWNERSHIP) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_OWNERSHIP) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_OWNERSHIP) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.ownership);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_OWNERSHIP) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- OWNERSHIP STRENGTH
|
|
if (not ref.reader) then
|
|
if (ref.ownership_strength /= DEFAULT_OWNERSHIP_STRENGTH_QOS or pid = PID_OWNERSHIP_STRENGTH) then
|
|
if (pid = PID_OWNERSHIP_STRENGTH) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_OWNERSHIP_STRENGTH) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_OWNERSHIP_STRENGTH) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.ownership_strength);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_OWNERSHIP_STRENGTH) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- LIVELINESS
|
|
if (ref.liveliness /= DEFAULT_LIVELINESS_QOS or ref.leaseDuration /= DEFAULT_LEASE_DURATION or pid = PID_LIVELINESS) then
|
|
if (pid = PID_LIVELINESS) then
|
|
assert (12+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_LIVELINESS) & endian_swap(ref.littleEndian, int(12+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_LIVELINESS) & endian_swap(ref.littleEndian, int(12,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.liveliness);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.leaseDuration(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.leaseDuration(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_LIVELINESS) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- TIME BASED FILTER
|
|
if (ref.time_based_filter /= DEFAULT_TIME_BASED_FILTER_QOS or pid = PID_TIME_BASED_FILTER) then
|
|
if (pid = PID_TIME_BASED_FILTER) then
|
|
assert (8+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_TIME_BASED_FILTER) & endian_swap(ref.littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_TIME_BASED_FILTER) & 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(ref.time_based_filter(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.time_based_filter(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_TIME_BASED_FILTER) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- RELIABILITY
|
|
if ((ref.reader and ref.reliability /= DEFAULT_RELIABILITY_QOS_R) or ((not ref.reader) and ref.reliability /= DEFAULT_RELIABILITY_QOS_W) or ref.max_blocking_time /= DEFAULT_MAX_BLOCKING_TIME or pid = PID_RELIABILITY) then
|
|
if (pid = PID_RELIABILITY) then
|
|
assert (12+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_RELIABILITY) & endian_swap(ref.littleEndian, int(12+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_RELIABILITY) & endian_swap(ref.littleEndian, int(12,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.reliability);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.max_blocking_time(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.max_blocking_time(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_RELIABILITY) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- LIFESPAN
|
|
if (ref.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) := endian_swap(ref.littleEndian, PID_LIFESPAN) & endian_swap(ref.littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, 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(ref.lifespan(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.lifespan(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_LIFESPAN) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- DESTINATION ORDER
|
|
if (ref.destination_order /= DEFAULT_DESTINATION_ORDER_QOS or pid = PID_DESTINATION_ORDER) then
|
|
if (pid = PID_DESTINATION_ORDER) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DESTINATION_ORDER) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DESTINATION_ORDER) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.destination_order);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DESTINATION_ORDER) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- MULTICAST LOCATORS
|
|
if (unsigned(ref.multicastLocatorList.numLocators) > 0) then
|
|
tmp := to_integer(unsigned(ref.multicastLocatorList.numLocators));
|
|
for i in 0 to tmp-1 loop
|
|
if (pid = PID_MULTICAST_LOCATOR) then
|
|
assert (24+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_MULTICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_MULTICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.multicastLocatorList.locator(i).kind);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.multicastLocatorList.locator(i).portn);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.multicastLocatorList.locator(i).addr(127 downto 96);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.multicastLocatorList.locator(i).addr(95 downto 64);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.multicastLocatorList.locator(i).addr(63 downto 32);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.multicastLocatorList.locator(i).addr(31 downto 0);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_MULTICAST_LOCATOR) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
-- UNICAST LOCATORS
|
|
if (unsigned(ref.unicastLocatorList.numLocators) > 0) then
|
|
tmp := to_integer(unsigned(ref.unicastLocatorList.numLocators));
|
|
for i in 0 to tmp-1 loop
|
|
if (pid = PID_UNICAST_LOCATOR) then
|
|
assert (24+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_UNICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_UNICAST_LOCATOR) & endian_swap(ref.littleEndian, int(24,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.unicastLocatorList.locator(i).kind);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.unicastLocatorList.locator(i).portn);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.unicastLocatorList.locator(i).addr(127 downto 96);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.unicastLocatorList.locator(i).addr(95 downto 64);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.unicastLocatorList.locator(i).addr(63 downto 32);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.unicastLocatorList.locator(i).addr(31 downto 0);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_UNICAST_LOCATOR) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
-- USER DATA
|
|
tmp := string_len(ref.user_data);
|
|
if (tmp > 1) then
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_USER_DATA) & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, int(tmp, 32));
|
|
output.length := output.length + 1;
|
|
for i in 0 to round_div(tmp,4)-1 loop
|
|
output.data(output.length) := ref.user_data(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
end if;
|
|
-- TOPIC DATA
|
|
tmp := string_len(ref.topic_data);
|
|
if (tmp > 1) then
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_TOPIC_DATA) & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, int(tmp,32));
|
|
output.length := output.length + 1;
|
|
for i in 0 to round_div(tmp,4)-1 loop
|
|
output.data(output.length) := ref.topic_data(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
end if;
|
|
-- GROUP DATA
|
|
tmp := string_len(ref.group_data);
|
|
if (tmp > 1) then
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_GROUP_DATA) & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, int(tmp,32));
|
|
output.length := output.length + 1;
|
|
for i in 0 to round_div(tmp,4)-1 loop
|
|
output.data(output.length) := ref.group_data(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
end if;
|
|
-- MAX SIZE SERIALIZED
|
|
if (not ref.reader) then
|
|
-- NOTE: PID_DATA_MAX_SIZE_SERIALIZED has no default value, but we use the value zero as default for not sending the parameter
|
|
if (unsigned(ref.max_size_serialized) /= 0) then
|
|
if (pid = PID_DATA_MAX_SIZE_SERIALIZED) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DATA_MAX_SIZE_SERIALIZED) & endian_swap(ref.littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(ref.littleEndian, PID_DATA_MAX_SIZE_SERIALIZED) & endian_swap(ref.littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(ref.littleEndian, ref.max_size_serialized);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DATA_MAX_SIZE_SERIALIZED) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end procedure;
|
|
|
|
procedure gen_endpoint_data( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
gen_endpoint_data(ref, output, PID_PAD, 0);
|
|
end procedure;
|
|
|
|
procedure gen_endpoint_match_frame( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is
|
|
variable loc : LOCATOR_TYPE;
|
|
begin
|
|
-- Fetch relevant Locator
|
|
loc := get_loc(ref);
|
|
|
|
-- OPCODE
|
|
case (ref.match) is
|
|
when MATCH =>
|
|
output.data(output.length) := EMO_ENDPOINT_MATCH;
|
|
output.length := output.length + 1;
|
|
when UNMATCH =>
|
|
output.data(output.length) := EMO_ENDPOINT_UNMATCH;
|
|
output.length := output.length + 1;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
-- GUID Prefix
|
|
output.data(output.length) := ref.participant.guidPrefix(0);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.participant.guidPrefix(1);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := ref.participant.guidPrefix(2);
|
|
output.length := output.length + 1;
|
|
-- ENTITY ID
|
|
output.data(output.length) := ref.entityId;
|
|
output.length := output.length + 1;
|
|
if (ref.match = MATCH) then
|
|
-- IPv4 Address
|
|
output.data(output.length) := loc.addr(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
output.length := output.length + 1;
|
|
-- Port & expectsInlineQoS
|
|
output.data(output.length) := (others => '0');
|
|
output.data(output.length)(WORD_WIDTH-1 downto UDP_PORT_WIDTH) := loc.portn(UDP_PORT_WIDTH-1 downto 0);
|
|
if (ref.reader) then
|
|
output.data(output.length)(READER_EXPECTS_INLINE_QOS_FLAG) := ref.expectsInlineQoS(0);
|
|
output.data(output.length)(READER_EXPECTS_HISTORICAL_DATA_FLAG) := '0' when (ref.durability = VOLATILE_DURABILITY_QOS) else '1';
|
|
output.data(output.length)(READER_IS_BEST_EFFORT_FLAG) := '1' when (ref.reliability = BEST_EFFORT_RELIABILITY_QOS) else '0';
|
|
end if;
|
|
output.length := output.length + 1;
|
|
-- Lifespan Duration
|
|
if (not ref.reader) then
|
|
output.data(output.length) := std_logic_vector(ref.lifespan(0));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := std_logic_vector(ref.lifespan(1));
|
|
output.length := output.length + 1;
|
|
end if;
|
|
end if;
|
|
|
|
-- Mark Last Word
|
|
output.last(output.length-1) := '1';
|
|
end procedure;
|
|
|
|
procedure gen_sentinel(littleEndian : in std_logic; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
output.data(output.length) := endian_swap(littleEndian, PID_SENTINEL) & (0 to PARAMETER_LENGTH_WIDTH-1 => '0');
|
|
output.length := output.length + 1;
|
|
end procedure;
|
|
|
|
procedure gen_sentinel(output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
gen_sentinel('0', output);
|
|
end procedure;
|
|
|
|
procedure gen_parameter(pid : in std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0); data : in TEST_PACKET_TYPE; littleEndian : in std_logic; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- PARAMETER HEADER
|
|
output.data(output.length) := endian_swap(littleEndian, pid) & endian_swap(littleEndian, int(data.length*4, PARAMETER_LENGTH_WIDTH));
|
|
output.length := output.length + 1;
|
|
-- DATA
|
|
for i in 0 to data.length-1 loop
|
|
output.data(output.length) := data.data(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
end procedure;
|
|
|
|
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) is
|
|
variable tmp : natural := 0;
|
|
begin
|
|
-- *INLINE-ONLY*
|
|
-- 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) := endian_swap(littleEndian, PID_KEY_HASH) & endian_swap(littleEndian, int(16+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_KEY_HASH) & endian_swap(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;
|
|
-- 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) := endian_swap(littleEndian, PID_STATUS_INFO) & endian_swap(littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_STATUS_INFO) & endian_swap(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;
|
|
-- ENDPOINT DATA QOS
|
|
if (expectsInlineQoS) then
|
|
-- TOPIC NAME
|
|
tmp := string_len(endpoint.topic_name);
|
|
if (pid = PID_TOPIC_NAME) then
|
|
assert (((round_div(tmp,4)+1)*4)+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_TOPIC_NAME) & endian_swap(littleEndian, int(((round_div(tmp,4)+1)*4)+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_TOPIC_NAME) & endian_swap(littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, int(tmp, CDR_LONG_WIDTH));
|
|
output.length := output.length + 1;
|
|
for i in 0 to round_div(tmp,4)-1 loop
|
|
output.data(output.length) := endpoint.topic_name(i);
|
|
output.length := output.length + 1;
|
|
end loop;
|
|
if (pid = PID_TOPIC_NAME) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
-- DURABILITY
|
|
if (endpoint.durability /= DEFAULT_DURABILITY_QOS or pid = PID_DURABILITY) then
|
|
if (pid = PID_DURABILITY) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_DURABILITY) & endian_swap(littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_DURABILITY) & endian_swap(littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, endpoint.durability);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DURABILITY) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- PRESENTATION
|
|
if (endpoint.presentation /= DEFAULT_PRESENTATION_QOS or endpoint.coherent_access(0) /= boolean_to_std_logic(DEFAULT_COHERENT_ACCESS) or endpoint.ordered_access(0) /= boolean_to_std_logic(DEFAULT_ORDERED_ACCESS) or pid = PID_PRESENTATION) then
|
|
if (pid = PID_PRESENTATION) then
|
|
assert (8+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_PRESENTATION) & endian_swap(littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_PRESENTATION) & endian_swap(littleEndian, int(8,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, endpoint.presentation);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, endpoint.coherent_access) & endian_swap(littleEndian, endpoint.ordered_access) & (0 to 15 => '0');
|
|
output.length := output.length + 1;
|
|
if (pid = PID_PRESENTATION) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- DEADLINE
|
|
if (endpoint.deadline /= DEFAULT_DEADLINE_QOS or pid = PID_DEADLINE) then
|
|
if (pid = PID_DEADLINE) then
|
|
assert (8+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_DEADLINE) & endian_swap(littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_DEADLINE) & endian_swap(littleEndian, int(8,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.deadline(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.deadline(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DEADLINE) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- LATENCY BUDGET
|
|
if (endpoint.latency_budget /= DEFAULT_LATENCY_BUDGET_QOS or pid = PID_LATENCY_BUDGET) then
|
|
if (pid = PID_LATENCY_BUDGET) then
|
|
assert (8+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_LATENCY_BUDGET) & endian_swap(littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_LATENCY_BUDGET) & endian_swap(littleEndian, int(8,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.latency_budget(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.latency_budget(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_LATENCY_BUDGET) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- OWNERSHIP
|
|
if (endpoint.ownership /= DEFAULT_OWNERSHIP_QOS or pid = PID_OWNERSHIP) then
|
|
if (pid = PID_OWNERSHIP) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_OWNERSHIP) & endian_swap(littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_OWNERSHIP) & endian_swap(littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, endpoint.ownership);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_OWNERSHIP) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- OWNERSHIP STRENGTH
|
|
if (endpoint.ownership_strength /= DEFAULT_OWNERSHIP_STRENGTH_QOS or pid = PID_OWNERSHIP_STRENGTH) then
|
|
if (pid = PID_OWNERSHIP_STRENGTH) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_OWNERSHIP_STRENGTH) & endian_swap(littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_OWNERSHIP_STRENGTH) & endian_swap(littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, endpoint.ownership_strength);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_OWNERSHIP_STRENGTH) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- LIVELINESS
|
|
if (endpoint.liveliness /= DEFAULT_LIVELINESS_QOS or endpoint.leaseDuration /= DEFAULT_LEASE_DURATION or pid = PID_LIVELINESS) then
|
|
if (pid = PID_LIVELINESS) then
|
|
assert (12+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_LIVELINESS) & endian_swap(littleEndian, int(12+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_LIVELINESS) & endian_swap(littleEndian, int(12,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, endpoint.liveliness);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.leaseDuration(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.leaseDuration(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_LIVELINESS) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- RELIABILITY
|
|
if (endpoint.reliability /= DEFAULT_RELIABILITY_QOS_W or endpoint.max_blocking_time /= DEFAULT_MAX_BLOCKING_TIME or pid = PID_RELIABILITY) then
|
|
if (pid = PID_RELIABILITY) then
|
|
assert (12+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_RELIABILITY) & endian_swap(littleEndian, int(12+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_RELIABILITY) & endian_swap(littleEndian, int(12,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, endpoint.reliability);
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.max_blocking_time(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.max_blocking_time(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_RELIABILITY) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- LIFESPAN
|
|
if (endpoint.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) := endian_swap(littleEndian, PID_LIFESPAN) & endian_swap(littleEndian, int(8+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_LIFESPAN) & endian_swap(littleEndian, int(8,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.lifespan(0)));
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, std_logic_vector(endpoint.lifespan(1)));
|
|
output.length := output.length + 1;
|
|
if (pid = PID_LIFESPAN) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
-- DESTINATION ORDER
|
|
if (endpoint.destination_order /= DEFAULT_DESTINATION_ORDER_QOS or pid = PID_DESTINATION_ORDER) then
|
|
if (pid = PID_DESTINATION_ORDER) then
|
|
assert (4+(offset*4) >= 0) report "Parameter Length < 0" severity FAILURE;
|
|
output.data(output.length) := endian_swap(littleEndian, PID_DESTINATION_ORDER) & endian_swap(littleEndian, int(4+(offset*4),PARAMETER_LENGTH_WIDTH));
|
|
else
|
|
output.data(output.length) := endian_swap(littleEndian, PID_DESTINATION_ORDER) & endian_swap(littleEndian, int(4,PARAMETER_LENGTH_WIDTH));
|
|
end if;
|
|
output.length := output.length + 1;
|
|
output.data(output.length) := endian_swap(littleEndian, endpoint.destination_order);
|
|
output.length := output.length + 1;
|
|
if (pid = PID_DESTINATION_ORDER) then
|
|
output.length := output.length + offset;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end procedure;
|
|
|
|
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) is
|
|
begin
|
|
gen_inline_qos(ref,endpoint,expectsInlineQoS,littleEndian,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,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
|
|
return FALSE;
|
|
end if;
|
|
|
|
for i in 0 to A'length loop
|
|
if (A(i).addr /= B(i).addr or (A(i).data ?/= B(i).data) = '1') then
|
|
return FALSE;
|
|
end if;
|
|
end loop;
|
|
return TRUE;
|
|
end function;
|
|
|
|
function gen_endpoint(id : natural) return ENDPOINT_DATA_TYPE is
|
|
variable ret : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA;
|
|
begin
|
|
assert (id <= NUM_ENDPOINTS-1) report "ID outside bounds." severity FAILURE;
|
|
|
|
ret.reader := TRUE when (id < NUM_READERS) else FALSE;
|
|
ret.topic_name := ENDPOINT_TOPIC(id);
|
|
ret.type_name := ENDPOINT_TYPE(id);
|
|
ret.durability := ENDPOINT_CONFIG(id).DURABILITY_QOS;
|
|
ret.durability_service_cleanup_delay := ENDPOINT_CONFIG(id).DURABILITY_SERVICE_CLEANUP_DELAY;
|
|
ret.durability_service_history := ENDPOINT_CONFIG(id).DURABILITY_SERVICE_HISTORY;
|
|
ret.durability_service_history_depth := ENDPOINT_CONFIG(id).DURABILITY_SERVICE_HISTORY_DEPTH;
|
|
ret.durability_service_max_samples := ENDPOINT_CONFIG(id).DURABILITY_SERVICE_MAX_SAMPLES;
|
|
ret.durability_service_max_instances := ENDPOINT_CONFIG(id).DURABILITY_SERVICE_MAX_INSTANCES;
|
|
ret.durability_service_max_samples_per_instances := ENDPOINT_CONFIG(id).DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE;
|
|
ret.presentation := ENDPOINT_CONFIG(id).PRESENTATION_QOS;
|
|
ret.coherent_access(0) := boolean_to_std_logic(ENDPOINT_CONFIG(id).COHERENT_ACCESS);
|
|
ret.ordered_access(0) := boolean_to_std_logic(ENDPOINT_CONFIG(id).ORDERED_ACCESS);
|
|
ret.deadline := ENDPOINT_CONFIG(id).DEADLINE_QOS;
|
|
ret.latency_budget := ENDPOINT_CONFIG(id).LATENCY_BUDGET_QOS;
|
|
ret.ownership := ENDPOINT_CONFIG(id).OWNERSHIP_QOS;
|
|
ret.ownership_strength := ENDPOINT_CONFIG(id).OWNERSHIP_STRENGTH_QOS;
|
|
ret.liveliness := ENDPOINT_CONFIG(id).LIVELINESS_QOS;
|
|
ret.leaseDuration := ENDPOINT_CONFIG(id).LEASE_DURATION;
|
|
ret.time_based_filter := ENDPOINT_CONFIG(id).TIME_BASED_FILTER_QOS;
|
|
ret.reliability := ENDPOINT_CONFIG(id).RELIABILITY_QOS;
|
|
ret.max_blocking_time := ENDPOINT_CONFIG(id).MAX_BLOCKING_TIME;
|
|
ret.lifespan := ENDPOINT_CONFIG(id).LIFESPAN_QOS;
|
|
ret.destination_order := ENDPOINT_CONFIG(id).DESTINATION_ORDER_QOS;
|
|
ret.expectsInlineQoS(0) := DEFAULT_EXPECTS_INLINE_QOS when (id < NUM_READERS) else '0';
|
|
ret.participant := THIS_PARTICIPANT_DATA;
|
|
ret.entityId := ENTITYID(id);
|
|
ret.nr := id;
|
|
return ret;
|
|
end function;
|
|
|
|
function gen_endpoint_array(readers : boolean) return ENDPOINT_DATA_ARRAY_TYPE is
|
|
variable ret_readers : ENDPOINT_DATA_ARRAY_TYPE(0 to NUM_READERS-1) := (others => DEFAULT_ENDPOINT_DATA);
|
|
variable ret_writers : ENDPOINT_DATA_ARRAY_TYPE(0 to NUM_WRITERS-1) := (others => DEFAULT_ENDPOINT_DATA);
|
|
begin
|
|
if (readers) then
|
|
for i in 0 to NUM_READERS-1 loop
|
|
ret_readers(i) := gen_endpoint(i);
|
|
end loop;
|
|
return ret_readers;
|
|
else
|
|
for i in NUM_READERS to NUM_ENDPOINTS-1 loop
|
|
ret_writers(i-NUM_READERS) := gen_endpoint(i);
|
|
end loop;
|
|
return ret_writers;
|
|
end if;
|
|
end function;
|
|
|
|
function to_string (input : TEST_MEMORY_TYPE) return string is
|
|
begin
|
|
return "length: " & integer'image(input'length) & ", start_addr: " & integer'image(input(0).addr) & "end_addr: " & integer'image(input(input'length-1).addr);
|
|
end function;
|
|
|
|
function to_string1 (input : std_logic_vector) return string is
|
|
begin
|
|
return "wr: " & to_string(input(0 to NUM_ENDPOINTS-1)) & ", last_word: " & to_string(input(NUM_ENDPOINTS)) & ", data: " & to_hstring(input(NUM_ENDPOINTS+1 to input'length-1));
|
|
end function;
|
|
|
|
procedure add_instance(inst : in INSTANCE_HANDLE_TYPE; istate : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); mem : inout DDS_READER_MEM_TYPE) is
|
|
variable ind : natural := 0;
|
|
begin
|
|
-- Find Position
|
|
ind := mem.ilen;
|
|
for i in 0 to mem.ilen-1 loop
|
|
if (to_unsigned(inst) < to_unsigned(mem.inst(i).inst)) then
|
|
ind := i;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
|
|
-- Move elements to make Space
|
|
for i in mem.ilen-1 downto ind loop
|
|
mem.inst(i+1) := mem.inst(i);
|
|
end loop;
|
|
-- Insert at desired index
|
|
mem.inst(ind) := DEFAULT_INSTANCE_CACHE_TYPE;
|
|
mem.inst(ind).inst := inst;
|
|
mem.inst(ind).istate := istate;
|
|
mem.ilen := mem.ilen + 1;
|
|
end procedure;
|
|
|
|
function to_sample(cc : CACHE_CHANGE_TYPE; istate : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0)) return SAMPLE_TYPE is
|
|
variable ret : SAMPLE_TYPE := DEFAULT_SAMPLE;
|
|
begin
|
|
ret.inst := cc.instance;
|
|
if (not cc.serialized_key) then
|
|
ret.data := cc.payload;
|
|
end if;
|
|
ret.ts := cc.src_timestamp;
|
|
ret.istate := istate;
|
|
return ret;
|
|
end function;
|
|
|
|
procedure change_istate(inst : in INSTANCE_HANDLE_TYPE; istate : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); mem : inout DDS_READER_MEM_TYPE) is
|
|
begin
|
|
|
|
-- Check Instance State
|
|
for i in 0 to max(mem.ilen-1,0) loop
|
|
-- Instance Found
|
|
if (inst = mem.inst(i).inst) then
|
|
case (istate) is
|
|
when ALIVE_INSTANCE_STATE =>
|
|
case (mem.inst(i).istate) is
|
|
when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
|
|
mem.inst(i).dis_gen_cnt := mem.inst(i).dis_gen_cnt + 1;
|
|
mem.inst(i).istate := ALIVE_INSTANCE_STATE;
|
|
mem.inst(i).vstate := NEW_VIEW_STATE;
|
|
when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
|
|
mem.inst(i).no_w_gen_cnt := mem.inst(i).no_w_gen_cnt + 1;
|
|
mem.inst(i).istate := ALIVE_INSTANCE_STATE;
|
|
mem.inst(i).vstate := NEW_VIEW_STATE;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
|
|
case (mem.inst(i).istate) is
|
|
when ALIVE_INSTANCE_STATE =>
|
|
mem.inst(i).istate := NOT_ALIVE_DISPOSED_INSTANCE_STATE;
|
|
when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
|
|
mem.inst(i).istate := NOT_ALIVE_DISPOSED_INSTANCE_STATE;
|
|
mem.inst(i).no_w_gen_cnt := mem.inst(i).no_w_gen_cnt + 1;
|
|
mem.inst(i).vstate := NEW_VIEW_STATE;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
|
|
case (mem.inst(i).istate) is
|
|
when ALIVE_INSTANCE_STATE =>
|
|
mem.inst(i).istate := NOT_ALIVE_NO_WRITERS_INSTANCE_STATE;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
end procedure;
|
|
|
|
procedure add_sample(sample : inout SAMPLE_TYPE; mem : inout DDS_READER_MEM_TYPE; DESTINATION_ORDER_QOS : in std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0)) is
|
|
variable found : boolean := FALSE;
|
|
variable ind : natural := 0;
|
|
begin
|
|
-- Zero Meta Data
|
|
sample.dis_gen_cnt := 0;
|
|
sample.no_w_gen_cnt := 0;
|
|
sample.srank := 0;
|
|
sample.grank := 0;
|
|
sample.agrank := 0;
|
|
sample.sstate := NOT_READ_SAMPLE_STATE;
|
|
|
|
-- NOTE: We change the Instance State here, because we need the new Sample needs the updated Generation Counters/View State
|
|
change_istate(sample.inst, sample.istate, mem);
|
|
|
|
-- NOTE: We always check at least the first index for keyless cases (instance = HANDLE_NIL)
|
|
-- Check Instance State
|
|
for i in 0 to max(mem.ilen-1,0) loop
|
|
-- Instance Found
|
|
if (sample.inst = mem.inst(i).inst) then
|
|
found := TRUE;
|
|
sample.vstate := mem.inst(i).vstate;
|
|
sample.dis_gen_cnt := mem.inst(i).dis_gen_cnt;
|
|
sample.no_w_gen_cnt := mem.inst(i).no_w_gen_cnt;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
|
|
-- New Instance
|
|
if (not found) then
|
|
add_instance(sample.inst, sample.istate, mem);
|
|
end if;
|
|
|
|
-- Add Sample
|
|
ind := mem.slen;
|
|
case (DESTINATION_ORDER_QOS) is
|
|
when BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS =>
|
|
-- Insert at End of Array
|
|
mem.s(ind) := sample;
|
|
when BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS =>
|
|
-- Find Position
|
|
for i in mem.slen-1 downto 0 loop
|
|
if (sample.ts >= mem.s(i).ts) then
|
|
exit;
|
|
end if;
|
|
ind := i;
|
|
end loop;
|
|
|
|
-- Move elements to make Space
|
|
for i in mem.slen-1 downto ind loop
|
|
mem.s(i+1) := mem.s(i);
|
|
end loop;
|
|
-- Insert at desired index
|
|
mem.s(ind) := sample;
|
|
when others =>
|
|
assert FALSE report "Unkown DESTINATION_ORDER_QOS" severity FAILURE;
|
|
end case;
|
|
mem.slen := mem.slen + 1;
|
|
end procedure;
|
|
|
|
procedure remove_sample(ind : in natural; mem : inout DDS_READER_MEM_TYPE) is
|
|
begin
|
|
assert (ind < mem.slen) report "Index is out of Bounds" severity FAILURE;
|
|
assert (mem.slen /= 0) report "Remove on empty array" severity FAILURE;
|
|
|
|
for i in ind to mem.slen-2 loop
|
|
mem.s(i) := mem.s(i+1);
|
|
end loop;
|
|
mem.s(mem.slen-1) := DEFAULT_SAMPLE;
|
|
mem.slen := mem.slen - 1;
|
|
end procedure;
|
|
|
|
procedure remove_inst(inst : in INSTANCE_HANDLE_TYPE; mem : inout DDS_READER_MEM_TYPE) is
|
|
variable ind : natural := 0;
|
|
begin
|
|
assert (mem.ilen /= 0) report "Remove on empty array" severity FAILURE;
|
|
|
|
ind := mem.ilen;
|
|
for i in 0 to mem.ilen-1 loop
|
|
-- Instance Found
|
|
if (mem.inst(i).inst = inst) then
|
|
ind := i;
|
|
exit;
|
|
end if;
|
|
end loop;
|
|
|
|
if (ind /= mem.ilen) then
|
|
for i in ind to mem.ilen-2 loop
|
|
mem.inst(i) := mem.inst(i+1);
|
|
end loop;
|
|
mem.inst(mem.ilen-1) := DEFAULT_INSTANCE_CACHE_TYPE;
|
|
mem.ilen := mem.ilen - 1;
|
|
end if;
|
|
end procedure;
|
|
|
|
function check_instance(istate : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); vstate : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0); mem : DDS_READER_MEM_TYPE; inst : INSTANCE_HANDLE_TYPE) return boolean is
|
|
begin
|
|
-- NOTE: We always check at least the first index for keyless cases (instance = HANDLE_NIL)
|
|
for i in 0 to max(mem.ilen-1,0) loop
|
|
-- Instance Found
|
|
if (inst = mem.inst(i).inst) then
|
|
if (((mem.inst(i).istate and istate) /= (istate'reverse_range => '0')) and ((mem.inst(i).vstate and vstate) /= (vstate'reverse_range => '0'))) then
|
|
return TRUE;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
return FALSE;
|
|
end function;
|
|
|
|
function find_instance(mem : DDS_READER_MEM_TYPE; inst : INSTANCE_HANDLE_TYPE) return natural is
|
|
begin
|
|
-- NOTE: We always check at least the first index for keyless cases (instance = HANDLE_NIL)
|
|
for i in 0 to max(mem.ilen-1,0) loop
|
|
-- Instance Found
|
|
if (inst = mem.inst(i).inst) then
|
|
return i;
|
|
end if;
|
|
end loop;
|
|
assert FALSE report "Instance not in Memory" severity FAILURE;
|
|
return mem.ilen;
|
|
end function;
|
|
|
|
procedure gen_collection (mem : inout DDS_READER_MEM_TYPE; col : inout COLLECTION_TYPE; inst : INSTANCE_HANDLE_TYPE; sstate : in std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0); istate : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0); vstate : in std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0); max_samples : in natural; remove : in boolean; sort : in boolean) is
|
|
variable i,j : natural := 0;
|
|
variable tmp_inst : INSTANCE_HANDLE_TYPE := HANDLE_NIL;
|
|
variable rank, mrsic_gen, mrs_gen : natural := 0;
|
|
variable done : std_logic_vector(0 to max_samples-1) := (others => '0');
|
|
variable sel : std_logic_vector(0 to mem.slen-1) := (others => '0');
|
|
variable no_inst : boolean := TRUE;
|
|
begin
|
|
col := DEFAULT_COLLECTION;
|
|
|
|
i := 0;
|
|
loop
|
|
if (no_inst) then
|
|
-- Sample and Instance Compatible
|
|
if (((mem.s(i).sstate and sstate) /= (sstate'reverse_range => '0')) and check_instance(istate, vstate, mem, mem.s(i).inst) and ((inst /= HANDLE_NIL and inst = mem.s(i).inst) or inst = HANDLE_NIL) and (sel(i) /= '1')) then
|
|
col.s(col.len) := mem.s(i);
|
|
col.s(col.len).istate := mem.inst(find_instance(mem,mem.s(i).inst)).istate;
|
|
col.s(col.len).vstate := mem.inst(find_instance(mem,mem.s(i).inst)).vstate;
|
|
col.len := col.len + 1;
|
|
-- Change READ STATE
|
|
mem.s(i).sstate := READ_SAMPLE_STATE;
|
|
-- Mark as Selected
|
|
sel(i) := '1';
|
|
tmp_inst := mem.s(i).inst;
|
|
-- NOTE: If we sort by Instance, we need to first get all compatible Samples from one Instance, before moving to the next compatible Instance.
|
|
-- This is achieved by toggling no_inst.
|
|
if (sort) then
|
|
no_inst := FALSE;
|
|
end if;
|
|
end if;
|
|
-- Sample Compatible (and belonging to specified Instance)
|
|
elsif (((mem.s(i).sstate and sstate) /= (sstate'reverse_range => '0')) and (mem.s(i).inst = tmp_inst) and (sel(i) /= '1')) then
|
|
col.s(col.len) := mem.s(i);
|
|
col.s(col.len).istate := mem.inst(find_instance(mem,mem.s(i).inst)).istate;
|
|
col.s(col.len).vstate := mem.inst(find_instance(mem,mem.s(i).inst)).vstate;
|
|
col.len := col.len + 1;
|
|
-- Change READ STATE
|
|
mem.s(i).sstate := READ_SAMPLE_STATE;
|
|
-- Mark as Selected
|
|
sel(i) := '1';
|
|
tmp_inst := mem.s(i).inst;
|
|
end if;
|
|
i := i + 1;
|
|
|
|
-- Loop Exit Condition
|
|
if (col.len >= max_samples) then
|
|
exit;
|
|
elsif (i >= mem.slen) then
|
|
-- No more compatible Samples
|
|
if (no_inst) then
|
|
exit;
|
|
-- Check next instance
|
|
else
|
|
i := 0;
|
|
no_inst := TRUE;
|
|
tmp_inst := HANDLE_NIL;
|
|
end if;
|
|
end if;
|
|
end loop;
|
|
|
|
-- Remove Selected Samples
|
|
if (remove) then
|
|
for i in mem.slen-1 downto 0 loop
|
|
if (sel(i) = '1') then
|
|
remove_sample(i,mem);
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
|
|
if (col.len = 0) then
|
|
report "Empty Collection" severity NOTE;
|
|
return;
|
|
end if;
|
|
|
|
-- Calculate Ranks
|
|
i := col.len-1;
|
|
tmp_inst := col.s(i).inst;
|
|
j := find_instance(mem,tmp_inst);
|
|
rank := 1;
|
|
mrs_gen := mem.inst(j).dis_gen_cnt + mem.inst(j).no_w_gen_cnt;
|
|
mrsic_gen := col.s(i).dis_gen_cnt + col.s(i).no_w_gen_cnt;
|
|
col.s(i).agrank := mrs_gen - mrsic_gen;
|
|
if (mrs_gen - mrsic_gen = 0) then
|
|
-- Change VIEW STATE
|
|
mem.inst(j).vstate := NOT_NEW_VIEW_STATE;
|
|
end if;
|
|
done(col.len-1 to done'length-1) := (others => '1');
|
|
no_inst := FALSE;
|
|
-- Single Sample
|
|
if (col.len-1 = 0) then
|
|
return;
|
|
else
|
|
loop
|
|
i := i - 1;
|
|
-- Select Next Instance
|
|
if (no_inst) then
|
|
if (done(i) = '0') then
|
|
tmp_inst := col.s(i).inst;
|
|
j := find_instance(mem, tmp_inst);
|
|
no_inst := FALSE;
|
|
-- Reset
|
|
rank := 1;
|
|
mrs_gen := mem.inst(j).dis_gen_cnt + mem.inst(j).no_w_gen_cnt;
|
|
mrsic_gen := col.s(i).dis_gen_cnt + col.s(i).no_w_gen_cnt;
|
|
col.s(i).agrank := mrs_gen - mrsic_gen;
|
|
if (mrs_gen - mrsic_gen = 0) then
|
|
-- Change VIEW STATE
|
|
mem.inst(j).vstate := NOT_NEW_VIEW_STATE;
|
|
end if;
|
|
done(i) := '1';
|
|
end if;
|
|
elsif (done(i) = '0' and col.s(i).inst = tmp_inst) then
|
|
col.s(i).srank := rank;
|
|
rank := rank + 1;
|
|
col.s(i).grank := mrsic_gen - (col.s(i).dis_gen_cnt + col.s(i).no_w_gen_cnt);
|
|
col.s(i).agrank := mrs_gen - (col.s(i).dis_gen_cnt + col.s(i).no_w_gen_cnt);
|
|
done(i) := '1';
|
|
end if;
|
|
-- Exit Condition
|
|
if (done = (done'range => '1')) then
|
|
exit;
|
|
-- Reset
|
|
elsif (i = 0) then
|
|
tmp_inst := HANDLE_NIL;
|
|
no_inst := TRUE;
|
|
i := col.len-1;
|
|
end if;
|
|
end loop;
|
|
end if;
|
|
end procedure;
|
|
|
|
procedure gen_collection (mem : inout DDS_READER_MEM_TYPE; col : inout COLLECTION_TYPE; opcode : in DDS_READER_TEST_TYPE; PRESENTATION_QOS : in std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0); ordered : in boolean) is
|
|
variable sort : boolean := FALSE;
|
|
variable tmp_inst : INSTANCE_HANDLE_TYPE := HANDLE_NIL;
|
|
begin
|
|
col := DEFAULT_COLLECTION;
|
|
|
|
sort := TRUE when (not ordered or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) else FALSE;
|
|
|
|
case (opcode.opcode) is
|
|
when READ =>
|
|
gen_collection(mem, col, HANDLE_NIL, opcode.sstate, opcode.istate, opcode.vstate, opcode.max_samples, FALSE, sort);
|
|
when TAKE =>
|
|
gen_collection(mem, col, HANDLE_NIL, opcode.sstate, opcode.istate, opcode.vstate, opcode.max_samples, TRUE, sort);
|
|
when READ_NEXT_SAMPLE =>
|
|
gen_collection(mem, col, HANDLE_NIL, NOT_READ_SAMPLE_STATE, ANY_INSTANCE_STATE, ANY_VIEW_STATE, 1, FALSE, FALSE);
|
|
when TAKE_NEXT_SAMPLE =>
|
|
gen_collection(mem, col, HANDLE_NIL, NOT_READ_SAMPLE_STATE, ANY_INSTANCE_STATE, ANY_VIEW_STATE, 1, TRUE, FALSE);
|
|
when READ_INSTANCE =>
|
|
gen_collection(mem, col, opcode.inst, opcode.sstate, opcode.istate, opcode.vstate, opcode.max_samples, FALSE, sort);
|
|
when TAKE_INSTANCE =>
|
|
gen_collection(mem, col, opcode.inst, opcode.sstate, opcode.istate, opcode.vstate, opcode.max_samples, TRUE, sort);
|
|
when READ_NEXT_INSTANCE =>
|
|
tmp_inst := mem.inst(find_instance(mem,opcode.inst)+1).inst when (opcode.inst /= HANDLE_NIL) else mem.inst(0).inst;
|
|
if (tmp_inst /= HANDLE_NIL) then
|
|
gen_collection(mem, col, tmp_inst, opcode.sstate, opcode.istate, opcode.vstate, opcode.max_samples, FALSE, sort);
|
|
end if;
|
|
when TAKE_NEXT_INSTANCE =>
|
|
tmp_inst := mem.inst(find_instance(mem,opcode.inst)+1).inst when (opcode.inst /= HANDLE_NIL) else mem.inst(0).inst;
|
|
if (tmp_inst /= HANDLE_NIL) then
|
|
gen_collection(mem, col, tmp_inst, opcode.sstate, opcode.istate, opcode.vstate, opcode.max_samples, TRUE, sort);
|
|
end if;
|
|
when others =>
|
|
assert FALSE report "Unknown DDS Reader Operation" severity FAILURE;
|
|
end case;
|
|
end procedure;
|
|
|
|
procedure gen_CDR(input : std_logic_vector; target_align : ALIGN_TYPE; align_offset : inout unsigned; output : inout TEST_PACKET_TYPE) is
|
|
begin
|
|
-- Align Stream
|
|
while (not check_align(align_offset,target_align)) loop
|
|
output.data(output.length) := write_sub_vector(output.data(output.length),(BYTE_WIDTH-1 downto 0 => '0'), to_integer(align_offset(1 downto 0)), TRUE);
|
|
if (align_offset(1 downto 0) = "11") then
|
|
output.length := output.length + 1;
|
|
end if;
|
|
align_offset := align_offset + 1;
|
|
end loop;
|
|
|
|
for i in (input'length/BYTE_WIDTH)-1 downto 0 loop
|
|
output.data(output.length) := write_sub_vector(output.data(output.length),input(((i+1)*BYTE_WIDTH)-1 downto i*BYTE_WIDTH), to_integer(align_offset(1 downto 0)), TRUE);
|
|
if (align_offset(1 downto 0) = "11") then
|
|
output.length := output.length + 1;
|
|
end if;
|
|
align_offset := align_offset + 1;
|
|
end loop;
|
|
end procedure;
|
|
|
|
end package body;
|