* Add modelsim.ini File in gitignore

* Small change in rtps_builtin_endpoint_test1
	- Empty Signal was not toggling
* Added rtps_builtin_endpoint_test2
	- Compiling and Passing
* Update rtps_test_package
* Various bug Fixes in rtps_builtin_endpoint
This commit is contained in:
Greek 2020-11-26 18:02:14 +01:00
parent 521e2466f5
commit 32fd1ac31e
14 changed files with 1986 additions and 221 deletions

2
.gitignore vendored
View File

@ -14,6 +14,8 @@
#***MODELSIM***
#Do files
!*.do
#Modelsim INI File
!*modelsim.ini
#***QUARTUS***
#Project File
!*.qpf

326
sim/modelsim.ini Normal file
View File

@ -0,0 +1,326 @@
; Copyright 1991-2009 Mentor Graphics Corporation
;
; All Rights Reserved.
;
; THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS THE PROPERTY OF
; MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS SUBJECT TO LICENSE TERMS.
;
[Library]
others = $MODEL_TECH/../modelsim.ini
; Altera Primitive libraries
;
; VHDL Section
;
;
; Verilog Section
;
default = W:/HDL-SIM/OSVVM-Scripts/../sim/VHDL_LIBS/ModelSim-2020.02/default.lib
osvvm = W:/HDL-SIM/OSVVM-Scripts/../sim/VHDL_LIBS/ModelSim-2020.02/osvvm.lib
Level0-rtps_handler = W:/HDL-SIM/OSVVM-Scripts/../sim/VHDL_LIBS/ModelSim-2020.02/Level0-rtps_handler.lib
[vcom]
; VHDL93 variable selects language version as the default.
; Default is VHDL-2002.
; Value of 0 or 1987 for VHDL-1987.
; Value of 1 or 1993 for VHDL-1993.
; Default or value of 2 or 2002 for VHDL-2002.
; Default or value of 3 or 2008 for VHDL-2008.
VHDL93 = 2008
; Show source line containing error. Default is off.
; Show_source = 1
; Turn off unbound-component warnings. Default is on.
; Show_Warning1 = 0
; Turn off process-without-a-wait-statement warnings. Default is on.
; Show_Warning2 = 0
; Turn off null-range warnings. Default is on.
; Show_Warning3 = 0
; Turn off no-space-in-time-literal warnings. Default is on.
; Show_Warning4 = 0
; Turn off multiple-drivers-on-unresolved-signal warnings. Default is on.
; Show_Warning5 = 0
; Turn off optimization for IEEE std_logic_1164 package. Default is on.
; Optimize_1164 = 0
; Turn on resolving of ambiguous function overloading in favor of the
; "explicit" function declaration (not the one automatically created by
; the compiler for each type declaration). Default is off.
; The .ini file has Explicit enabled so that std_logic_signed/unsigned
; will match the behavior of synthesis tools.
Explicit = 1
; Turn off acceleration of the VITAL packages. Default is to accelerate.
; NoVital = 1
; Turn off VITAL compliance checking. Default is checking on.
; NoVitalCheck = 1
; Ignore VITAL compliance checking errors. Default is to not ignore.
; IgnoreVitalErrors = 1
; Turn off VITAL compliance checking warnings. Default is to show warnings.
; Show_VitalChecksWarnings = 0
; Keep silent about case statement static warnings.
; Default is to give a warning.
; NoCaseStaticError = 1
; Keep silent about warnings caused by aggregates that are not locally static.
; Default is to give a warning.
; NoOthersStaticError = 1
; Turn off inclusion of debugging info within design units.
; Default is to include debugging info.
; NoDebug = 1
; Turn off "Loading..." messages. Default is messages on.
; Quiet = 1
; Turn on some limited synthesis rule compliance checking. Checks only:
; -- signals used (read) by a process must be in the sensitivity list
; CheckSynthesis = 1
; Activate optimizations on expressions that do not involve signals,
; waits, or function/procedure/task invocations. Default is off.
; ScalarOpts = 1
; Require the user to specify a configuration for all bindings,
; and do not generate a compile time default binding for the
; component. This will result in an elaboration error of
; 'component not bound' if the user fails to do so. Avoids the rare
; issue of a false dependency upon the unused default binding.
; RequireConfigForAllDefaultBinding = 1
; Inhibit range checking on subscripts of arrays. Range checking on
; scalars defined with subtypes is inhibited by default.
; NoIndexCheck = 1
; Inhibit range checks on all (implicit and explicit) assignments to
; scalar objects defined with subtypes.
NoRangeCheck = 1
[vlog]
; Turn off inclusion of debugging info within design units.
; Default is to include debugging info.
; NoDebug = 1
; Turn off "loading..." messages. Default is messages on.
; Quiet = 1
; Turn on Verilog hazard checking (order-dependent accessing of global vars).
; Default is off.
; Hazard = 1
; Turn on converting regular Verilog identifiers to uppercase. Allows case
; insensitivity for module names. Default is no conversion.
; UpCase = 1
; Turn on incremental compilation of modules. Default is off.
; Incremental = 1
; Turns on lint-style checking.
; Show_Lint = 1
[vsim]
; Simulator resolution
; Set to fs, ps, ns, us, ms, or sec with optional prefix of 1, 10, or 100.
Resolution = ns
; User time unit for run commands
; Set to default, fs, ps, ns, us, ms, or sec. The default is to use the
; unit specified for Resolution. For example, if Resolution is 100ps,
; then UserTimeUnit defaults to ps.
; Should generally be set to default.
UserTimeUnit = default
; Default run length
RunLength = 100
; Maximum iterations that can be run without advancing simulation time
IterationLimit = 5000
; Directive to license manager:
; vhdl Immediately reserve a VHDL license
; vlog Immediately reserve a Verilog license
; plus Immediately reserve a VHDL and Verilog license
; nomgc Do not look for Mentor Graphics Licenses
; nomti Do not look for Model Technology Licenses
; noqueue Do not wait in the license queue when a license isn't available
; viewsim Try for viewer license but accept simulator license(s) instead
; of queuing for viewer license
; License = plus
; Stop the simulator after a VHDL/Verilog assertion message
; 0 = Note 1 = Warning 2 = Error 3 = Failure 4 = Fatal
BreakOnAssertion = 3
; Assertion Message Format
; %S - Severity Level
; %R - Report Message
; %T - Time of assertion
; %D - Delta
; %I - Instance or Region pathname (if available)
; %% - print '%' character
; AssertionFormat = "** %S: %R\n Time: %T Iteration: %D%I\n"
; Assertion File - alternate file for storing VHDL/Verilog assertion messages
; AssertFile = assert.log
; Default radix for all windows and commands...
; Set to symbolic, ascii, binary, octal, decimal, hex, unsigned
DefaultRadix = symbolic
; VSIM Startup command
; Startup = do startup.do
; File for saving command transcript
TranscriptFile = transcript
; File for saving command history
; CommandHistory = cmdhist.log
; Specify whether paths in simulator commands should be described
; in VHDL or Verilog format.
; For VHDL, PathSeparator = /
; For Verilog, PathSeparator = .
; Must not be the same character as DatasetSeparator.
PathSeparator = /
; Specify the dataset separator for fully rooted contexts.
; The default is ':'. For example, sim:/top
; Must not be the same character as PathSeparator.
DatasetSeparator = :
; Disable VHDL assertion messages
; IgnoreNote = 1
; IgnoreWarning = 1
; IgnoreError = 1
; IgnoreFailure = 1
; Default force kind. May be freeze, drive, deposit, or default
; or in other terms, fixed, wired, or charged.
; A value of "default" will use the signal kind to determine the
; force kind, drive for resolved signals, freeze for unresolved signals
; DefaultForceKind = freeze
; If zero, open files when elaborated; otherwise, open files on
; first read or write. Default is 0.
; DelayFileOpen = 1
; Control VHDL files opened for write.
; 0 = Buffered, 1 = Unbuffered
UnbufferedOutput = 0
; Control the number of VHDL files open concurrently.
; This number should always be less than the current ulimit
; setting for max file descriptors.
; 0 = unlimited
ConcurrentFileLimit = 40
; Control the number of hierarchical regions displayed as
; part of a signal name shown in the Wave window.
; A value of zero tells VSIM to display the full name.
; The default is 0.
; WaveSignalNameWidth = 0
; Turn off warnings from the std_logic_arith, std_logic_unsigned
; and std_logic_signed packages.
; StdArithNoWarnings = 1
; Turn off warnings from the IEEE numeric_std and numeric_bit packages.
; NumericStdNoWarnings = 1
; Control the format of the (VHDL) FOR generate statement label
; for each iteration. Do not quote it.
; The format string here must contain the conversion codes %s and %d,
; in that order, and no other conversion codes. The %s represents
; the generate_label; the %d represents the generate parameter value
; at a particular generate iteration (this is the position number if
; the generate parameter is of an enumeration type). Embedded whitespace
; is allowed (but discouraged); leading and trailing whitespace is ignored.
; Application of the format must result in a unique scope name over all
; such names in the design so that name lookup can function properly.
; GenerateFormat = %s__%d
; Specify whether checkpoint files should be compressed.
; The default is 1 (compressed).
; CheckpointCompressMode = 0
; List of dynamically loaded objects for Verilog PLI applications
; Veriuser = veriuser.sl
; Specify default options for the restart command. Options can be one
; or more of: -force -nobreakpoint -nolist -nolog -nowave
; DefaultRestartOptions = -force
; HP-UX 10.20 ONLY - Enable memory locking to speed up large designs
; (> 500 megabyte memory footprint). Default is disabled.
; Specify number of megabytes to lock.
; LockedMemory = 1000
; Turn on (1) or off (0) WLF file compression.
; The default is 1 (compress WLF file).
; WLFCompress = 0
; Specify whether to save all design hierarchy (1) in the WLF file
; or only regions containing logged signals (0).
; The default is 0 (save only regions with logged signals).
; WLFSaveAllRegions = 1
; WLF file time limit. Limit WLF file by time, as closely as possible,
; to the specified amount of simulation time. When the limit is exceeded
; the earliest times get truncated from the file.
; If both time and size limits are specified the most restrictive is used.
; UserTimeUnits are used if time units are not specified.
; The default is 0 (no limit). Example: WLFTimeLimit = {100 ms}
; WLFTimeLimit = 0
; WLF file size limit. Limit WLF file size, as closely as possible,
; to the specified number of megabytes. If both time and size limits
; are specified then the most restrictive is used.
; The default is 0 (no limit).
; WLFSizeLimit = 1000
; Specify whether or not a WLF file should be deleted when the
; simulation ends. A value of 1 will cause the WLF file to be deleted.
; The default is 0 (do not delete WLF file when simulation ends).
; WLFDeleteOnQuit = 1
; Automatic SDF compilation
; Disables automatic compilation of SDF files in flows that support it.
; Default is on, uncomment to turn off.
; NoAutoSDFCompile = 1
[lmc]
[msg_system]
; Change a message severity or suppress a message.
; The format is: <msg directive> = <msg number>[,<msg number>...]
; Examples:
; note = 3009
; warning = 3033
; error = 3010,3016
; fatal = 3016,3033
; suppress = 3009,3016,3043
; The command verror <msg number> can be used to get the complete
; description of a message.
; Control transcripting of elaboration/runtime messages.
; The default is to have messages appear in the transcript and
; recorded in the wlf file (messages that are recorded in the
; wlf file can be viewed in the MsgViewer). The other settings
; are to send messages only to the transcript or only to the
; wlf file. The valid values are
; both {default}
; tran {transcript only}
; wlf {wlf file only}
; msgmode = both

View File

@ -0,0 +1,72 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -divider SYSTEM
add wave -noupdate /rtps_builtin_endpoint_test2/uut/clk
add wave -noupdate /rtps_builtin_endpoint_test2/uut/reset
add wave -noupdate -divider INPUT
add wave -noupdate /rtps_builtin_endpoint_test2/uut/empty
add wave -noupdate /rtps_builtin_endpoint_test2/uut/rd
add wave -noupdate -radix hexadecimal /rtps_builtin_endpoint_test2/uut/data_in
add wave -noupdate /rtps_builtin_endpoint_test2/uut/last_word_in
add wave -noupdate /rtps_builtin_endpoint_test2/uut/last_word_in_latch
add wave -noupdate -divider OUTPUT
add wave -noupdate -radix hexadecimal /rtps_builtin_endpoint_test2/uut/data_out
add wave -noupdate /rtps_builtin_endpoint_test2/uut/endpoint_wr
add wave -noupdate /rtps_builtin_endpoint_test2/uut/last_word_out
add wave -noupdate -divider TESTBENCH
add wave -noupdate /rtps_builtin_endpoint_test2/start
add wave -noupdate /rtps_builtin_endpoint_test2/stim_stage
add wave -noupdate /rtps_builtin_endpoint_test2/stimulus.length
add wave -noupdate /rtps_builtin_endpoint_test2/cnt_stim
add wave -noupdate /rtps_builtin_endpoint_test2/packet_sent
add wave -noupdate /rtps_builtin_endpoint_test2/SB.ItemNumberVar
add wave -noupdate -divider {MAIN FSM}
add wave -noupdate /rtps_builtin_endpoint_test2/uut/stage
add wave -noupdate /rtps_builtin_endpoint_test2/uut/stage_next
add wave -noupdate /rtps_builtin_endpoint_test2/uut/cnt
add wave -noupdate /rtps_builtin_endpoint_test2/uut/endpoint_mask
add wave -noupdate /rtps_builtin_endpoint_test2/uut/participant_match
add wave -noupdate -divider {MEM FSM}
add wave -noupdate -group MEM_FSM /rtps_builtin_endpoint_test2/uut/mem_opcode
add wave -noupdate -group MEM_FSM /rtps_builtin_endpoint_test2/uut/mem_op_start
add wave -noupdate -group MEM_FSM /rtps_builtin_endpoint_test2/uut/mem_op_done
add wave -noupdate -group MEM_FSM /rtps_builtin_endpoint_test2/uut/mem_stage
add wave -noupdate -group MEM_FSM /rtps_builtin_endpoint_test2/uut/mem_stage_next
add wave -noupdate -group MEM_FSM /rtps_builtin_endpoint_test2/uut/mem_cnt
add wave -noupdate -group MEM_FSM -radix unsigned /rtps_builtin_endpoint_test2/uut/mem_addr_base
add wave -noupdate -group MEM_FSM -radix unsigned /rtps_builtin_endpoint_test2/uut/addr_res
add wave -noupdate -group MEM_FSM -radix unsigned /rtps_builtin_endpoint_test2/uut/last_addr
add wave -noupdate -group MEM_FSM -radix unsigned /rtps_builtin_endpoint_test2/uut/max_participant_addr
add wave -noupdate -group MEM_FSM -radix unsigned /rtps_builtin_endpoint_test2/uut/max_endpoint_addr
add wave -noupdate -divider GUARD
add wave -noupdate -radix unsigned /rtps_builtin_endpoint_test2/uut/read_cnt
add wave -noupdate -radix unsigned /rtps_builtin_endpoint_test2/uut/parameter_end
add wave -noupdate /rtps_builtin_endpoint_test2/uut/parse_prc/rd_guard
add wave -noupdate -divider MEMORY
add wave -noupdate -group MEMORY -radix unsigned /rtps_builtin_endpoint_test2/uut/ram_inst/addr
add wave -noupdate -group MEMORY /rtps_builtin_endpoint_test2/uut/ram_inst/wen
add wave -noupdate -group MEMORY /rtps_builtin_endpoint_test2/uut/ram_inst/ren
add wave -noupdate -group MEMORY -radix hexadecimal /rtps_builtin_endpoint_test2/uut/ram_inst/wr_data
add wave -noupdate -group MEMORY -radix hexadecimal /rtps_builtin_endpoint_test2/uut/ram_inst/rd_data
add wave -noupdate -divider MISC
add wave -noupdate /rtps_builtin_endpoint_test2/uut/update_participant_flags
add wave -noupdate -radix unsigned /rtps_builtin_endpoint_test2/uut/mem_seq_nr
add wave -noupdate -radix unsigned /rtps_builtin_endpoint_test2/uut/seq_nr
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {Begin {32125000 ps} 1} {Error {35025000 ps} 1} {Cursor {33675000 ps} 0}
quietly wave cursor active 3
configure wave -namecolwidth 149
configure wave -valuecolwidth 144
configure wave -justifyvalue left
configure wave -signalnamewidth 1
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {33245026 ps} {34393368 ps}

View File

@ -227,15 +227,15 @@ ENDPOINT DATA
31............24..............16..............8...............0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------------------------------------------------------+
01| ENTITYID |
00| ENTITYID |
+-------------------------------------------------------------+
02| |
01| |
+ +
03| GUIDPREFIX |
02| GUIDPREFIX |
+ +
03| |
+-------------------------------------------------------------+
04| |
+-------------------------------------------------------------+
05| |
~ ENDPOINT_BITMASK ~
**| |
+-------------------------------------------------------------+
@ -245,19 +245,19 @@ ENDPOINT MATCH FRAME
31............24..............16..............8...............0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------------------------------------------------------+
01| OPCODE |
00| OPCODE |
+-------------------------------------------------------------+
02| |
01| |
+ +
03| GUIDPREFIX |
02| GUIDPREFIX |
+ +
04| |
03| |
+-------------------------------------------------------------+
05| ENTITYID |
04| ENTITYID |
+-------------------------------------------------------------+
06| IPv4_ADDRESS |
05| IPv4_ADDRESS |
+-------------------------------------------------------------+
07| UDP_PORT | UNUSED |Q|
06| UDP_PORT | UNUSED |Q|
+-------------------------------------------------------------+
ENDPOINT UNMATCH FRAME
@ -265,15 +265,15 @@ ENDPOINT UNMATCH FRAME
31............24..............16..............8...............0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------------------------------------------------------+
01| OPCODE |
00| OPCODE |
+-------------------------------------------------------------+
02| |
01| |
+ +
03| GUIDPREFIX |
02| GUIDPREFIX |
+ +
04| |
03| |
+-------------------------------------------------------------+
05| ENTITYID |
04| ENTITYID |
+-------------------------------------------------------------+
ENDPOINT LIVELINESS UPDATE
@ -281,13 +281,13 @@ ENDPOINT LIVELINESS UPDATE
31............24..............16..............8...............0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------------------------------------------------------+
01| OPCODE |
00| OPCODE |
+-------------------------------------------------------------+
02| |
01| |
+ +
03| GUIDPREFIX |
02| GUIDPREFIX |
+ +
04| |
03| |
+-------------------------------------------------------------+
LOCAL ENDPOINT BUFFER
@ -368,7 +368,9 @@ information is not present, the implementation can assume the default values, as
In order to implement the DDS_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS policy,
implementations must include an InfoTimestamp Submessage with every update from a Writer.
9.4.2.11
The ParameterList may contain multiple Parameters with the same value for the parameterId.
This is used to provide a collection of values for that kind of Parameter.
DDS_Advanced_Tutorial_2006_00-T1-2_Pardo.pdf (P.16)

View File

@ -54,7 +54,6 @@
* Can we make an array of records of uncontrained strings? That we we could make an array of variable sized strings...
* Should I also check for Minor_Version >= 4?
* Fast-RTPS doen not follow DDSI-RTPS Specification
- Open Github Issue
https://github.com/eProsima/Fast-RTPS/issues/1221
@ -75,7 +74,6 @@
'This Submessage is invalid when the following is true:
submessageLength in the Submessage header is too small'
But if InvalidateFlag is set, Length can be Zero. Since the length is unsigned, there cannot be an invalid length.
- 9.4.5.1.2 Flags
Clarify from where the endianness begins.
One might think it would begin after the Submessage Header, but the length is also endian dependent.
@ -84,7 +82,11 @@
Does this invalidate the Submessage? Does 8.3.4.1 apply (Invalidate rest of Message)?
- 9.4.5.1.3 octetsToNextHeader
Similarly to "9.4.2.11" state that this is always a multiple of four.
* DDS 1.4 ISSUES
- 2.2.3 Supported QoS
Partition is marked as RxO=No, but should be RxO=Yes? Or not?
* Source Port of SPDP is irrelevant, since it is BEST EFFORT and we do not reply (only Destination Port is of significance)

View File

@ -494,7 +494,6 @@ begin
AlertIf(GetAffirmCount < check_cnt, "Incomplete test run");
ReportAlerts;
wait; --TODO: Remove
std.env.stop;
wait;
end process;
@ -507,10 +506,10 @@ begin
wait for 25 ns;
end process;
fifo_ctl_prc : process
in_empty_prc : process
begin
in_empty <= '0';
wait; --TODO: Remove
wait until rd_sig = '1';
wait until rising_edge(clk);
in_empty <= '1';
wait until rising_edge(clk);

View File

@ -0,0 +1,905 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library osvvm; -- Utility Library
context osvvm.OsvvmContext;
use work.rtps_package.all;
use work.user_config.all;
use work.rtps_config_package.all;
use work.rtps_test_package.all;
-- WRITER 0
-- * DEFAULT
-- WRITER 1
-- * TYPE_2
-- WRITER 2
-- * TOPIC_2
-- * TYPE_2
-- WRITER 3
-- * RELIABILITY BEST_EFFORT
-- WRITER 4
-- * DURABILITY TRANSIENT_LOCAL
-- * PRESENTATION TOPIC
-- * COHERENT_ACCESS TRUE
-- * DEADLINE 15s
-- * LATENCY_BUDGET 1s
-- * LIVELINESS MANUAL_BY_PARTICIPANT
-- * LEASE_DURATION 15s
-- * DESTINATION_ORDER BY_SOURCE_TIMESTAMP
-- WRITER 5
-- * PRESENTATION TOPIC
-- * COHERENT_ACCESS TRUE
-- * ORDERED_ACCESS TRUE
-- WRITER 6
-- * LATENCY_BUDGET 1s
-- WRITER 7
-- * DURABILITY_SERVICE_CLEANUP_DELAY 86400s
-- * DURABILITY_SERVICE_HISTORY KEEP_ALL_HISTORY_QOS
-- * DURABILITY_SERVICE_HISTORY_DEPTH 10
-- * DURABILITY_SERVICE_MAX_SAMPLES 10
-- * DURABILITY_SERVICE_MAX_INSTANCES 5
-- * DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE 5
-- * OWNERSHIP_STRENGTH 2
-- * MAX_BLOCKING_TIME 2s
-- * TRANSPORT_PRIORITY 3
-- * LIFESPAN 30s
-- * USER_DATA "USER_DATA"
-- * TOPIC_DATA "TOPIC_DATA"
-- * GROUP_DATA "GROUP_DATA"
-- READER 0
-- * DEFAULT
-- READER 1
-- * TYPE_2
-- READER 2
-- * TOPIC_2
-- * TYPE_2
-- READER 3
-- * DURABILITY TRANSIENT_LOCAL
-- READER 4
-- * PRESENTATION TOPIC
-- READER 5
-- * COHERENT_ACCESS TRUE
-- READER 6
-- * COHERENT_ACCESS TRUE
-- * ORDERED_ACCESS TRUE
-- READER 7
-- * DEADLINE 10s
-- * TIME_BASED_FILTER 5s
-- READER 8
-- * DEADLINE 20s
-- * TIME_BASED_FILTER 5s
-- READER 9
-- * LATENCY_BUDGET 500ms
-- READER 10
-- * LATENCY_BUDGET 2s
-- READER 11
-- * LIVELINESS MANUAL_BY_PARTICIPANT
-- * LEASE_DURATION 20s
-- READER 12
-- * LIVELINESS MANUAL_BY_TOPIC
-- * LEASE_DURATION 20s
-- READER 13
-- * LEASE_DURATION 10s
-- READER 14
-- * LEASE_DURATION 20s
-- READER 15
-- * RELIABILITY BEST_EFFORT
-- READER 16
-- * DESTINATION_ORDER BY_SOURCE_TIMESTAMP
entity rtps_builtin_endpoint_test2 is
end entity;
architecture testbench of rtps_builtin_endpoint_test2 is
-- *COMPONENT DECLARATION*
component rtps_builtin_endpoint is
port (
clk : in std_logic;
reset : in std_logic;
empty : in std_logic;
rd : out std_logic;
data_in : in std_logic_vector(WORD_WIDTH-1 downto 0);
data_out : out std_logic_vector(WORD_WIDTH-1 downto 0);
last_word_in : in std_logic;
time : in TIME_TYPE;
endpoint_full : in std_logic_vector(0 to NUM_ENDPOINTS-1);
endpoint_wr : out std_logic_vector(0 to NUM_ENDPOINTS-1);
rtps_wr : out std_logic;
rtps_full : in std_logic;
last_word_out : out std_logic;
alive : in std_logic_vector(0 to NUM_ENDPOINTS-1)
);
end component;
-- *TYPE DECLARATION*
type TEST_STAGE_TYPE is (IDLE, BUSY);
type MATCH_MATRIX_TYPE is array (0 to NUM_WRITERS-1) of std_logic_vector(0 to NUM_READERS-1);
-- *SIGNAL DECLARATION*
signal clk, in_empty, rd_sig, last_word_in, last_word_out: std_logic := '0';
signal reset : std_logic := '1';
signal endpoint_wr, endpoint_full : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
signal data_in, data_out : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal stim_stage : TEST_STAGE_TYPE := IDLE;
shared variable stimulus, reference : TEST_PACKET_TYPE := EMPTY_TEST_PACKET;
signal packet_sent : std_logic := '0';
signal cnt_stim : natural := 0;
signal start : std_logic := '0';
shared variable SB : work.ScoreBoardPkg_builtin_endpoint.ScoreBoardPType;
signal MATCH_MATRIX : MATCH_MATRIX_TYPE := (others => (others => '0'));
signal stim_done, check_done : std_logic := '0';
-- *FUNCTION DECLARATION*
procedure wait_on_complete is
begin
wait until rising_edge(packet_sent);
end procedure;
impure function gen_wr(index : natural; reader : boolean) return std_logic_vector is
variable ret : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
begin
if (reader) then
for i in 0 to NUM_WRITERS-1 loop
ret(NUM_READERS+i) := MATCH_MATRIX(i)(index);
end loop;
else
for i in 0 to NUM_READERS-1 loop
ret(i) := MATCH_MATRIX(index)(i);
end loop;
end if;
return ret;
end function;
begin
-- Unit Under Test
uut : rtps_builtin_endpoint
port map (
clk => clk,
reset => reset,
empty => in_empty or packet_sent,
rd => rd_sig,
data_in => data_in,
data_out => data_out,
last_word_in => last_word_in,
time => TIME_ZERO,
endpoint_full => endpoint_full,
endpoint_wr => endpoint_wr,
rtps_wr => open,
rtps_full => '0',
last_word_out => last_word_out,
alive => (others => '0')
);
stimulus_prc : process
variable sub, sub_p, sub_s : RTPS_SUBMESSAGE_TYPE := DEFAULT_RTPS_SUBMESSAGE;
variable check_cnt : natural := 0;
variable RV : RandomPType;
variable p0, p1, p2 : PARTICIPANT_DATA_TYPE := DEFAULT_PARTICIPANT_DATA;
variable fixed_readers : ENDPOINT_DATA_ARRAY_TYPE(0 to NUM_READERS-1) := gen_endpoint_array(TRUE);
variable fixed_writers : ENDPOINT_DATA_ARRAY_TYPE(0 to NUM_WRITERS-1) := gen_endpoint_array(FALSE);
variable endpoint, e1, e2 : ENDPOINT_DATA_TYPE := DEFAULT_ENDPOINT_DATA;
variable p0_sn, p0_snp, p0_sns : SEQUENCENUMBER_TYPE := FIRST_SEQUENCENUMBER;
variable p1_sn, p1_snp, p1_sns : SEQUENCENUMBER_TYPE := FIRST_SEQUENCENUMBER;
variable p2_sn, p2_snp, p2_sns : SEQUENCENUMBER_TYPE := FIRST_SEQUENCENUMBER;
variable wr_sig : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
variable user_data, topic_data, group_data : STRING_WORD_ARRAY_TYPE := EMPTY_STRING;
-- Wrapper to use procedure as function
impure function gen_rand_loc_2 return LOCATOR_TYPE is
variable ret : LOCATOR_TYPE := EMPTY_LOCATOR;
begin
gen_rand_loc(RV, ret);
return ret;
end function;
impure function gen_rand_entityid_2(reader : boolean) return std_logic_vector is
variable ret : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0');
begin
gen_rand_entityid(RV, reader, ret);
return ret;
end function;
procedure push_reference is
begin
for i in 0 to reference.length-1 loop
SB.Push(wr_sig & reference.last(i) & reference.data(i));
end loop;
end procedure;
impure function gen_rand_guid_prefix return GUIDPREFIX_TYPE is
variable ret : GUIDPREFIX_TYPE;
begin
ret := (0 => RV.RandSlv(WORD_WIDTH), 1 => RV.RandSlv(WORD_WIDTH), 2 => RV.RandSlv(WORD_WIDTH));
return ret;
end function;
procedure start_test is
begin
start <= '1';
wait until rising_edge(clk);
start <= '0';
wait until rising_edge(clk);
end procedure;
begin
assert (TEST_STRING = "TEST_CONFIG_1") report "user_config incompatible with testbench." severity FAILURE;
SetAlertLogName("L0-rtps_builtin_endpoint-endpoint_matching");
SetAlertEnable(FAILURE, TRUE);
SetAlertEnable(ERROR, TRUE);
SetAlertEnable(WARNING, TRUE);
SetLogEnable(DEBUG, FALSE);
SetLogEnable(PASSED, FALSE);
SetLogEnable(INFO, TRUE);
RV.InitSeed(RV'instance_name);
-- Populate MATCH Matrix
MATCH_MATRIX <= (
0 => (0 => '1', 9 => '1', 10 => '1', 15 => '1', others => '0'),
1 => (1 => '1', others => '0'),
2 => (2 => '1', others => '0'),
3 => (15 => '1', others => '0'),
4 => (0 => '1', 3 => '1', 4 => '1', 5 => '1', 8 => '1', 9 => '1', 10 => '1', 11 => '1', 14 => '1', 15 => '1', 16 => '1', others => '0'),
5 => (0 => '1', 4 => '1', 5 => '1', 6 => '1', 9 => '1', 10 => '1', 15 => '1', others => '0'),
6 => (10 => '1', others => '0'),
7 => (0 => '1', 9 => '1', 10 => '1', 15 => '1', others => '0')
);
-- Participant RTPS Submessage
sub := DEFAULT_RTPS_SUBMESSAGE;
sub.submessageID := SID_DATA;
sub.writerId := ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER;
sub.readerId := ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR;
sub.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
-- Publisher Endpoint RTPS Submessage
sub_p := DEFAULT_RTPS_SUBMESSAGE;
sub_p.submessageID := SID_DATA;
sub_p.writerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
sub_p.readerId := ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR;
sub_p.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
-- Subscriber Endpoint RTPS Submessage
sub_s := DEFAULT_RTPS_SUBMESSAGE;
sub_s.submessageID := SID_DATA;
sub_s.writerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER;
sub_s.readerId := ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
sub_s.flags(SUBMESSAGE_DATA_FLAG_POS) := '1';
-- Participant 0 (Contains the fixed Endpoints)
p0.guidPrefix := gen_rand_guid_prefix;
p0.nr := 0;
p0.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR));
p0.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1';
p0.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1';
p0.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1';
p0.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1';
-- Participant 1 (Contains the fixed Endpoints in Little Endian)
p1.guidPrefix := gen_rand_guid_prefix;
p1.nr := 1;
p1.littleEndian := '1';
p1.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR));
p1.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1';
p1.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1';
p1.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1';
p1.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1';
-- Participant 2 (Used for dyncamic Endpoints)
p2.guidPrefix := gen_rand_guid_prefix;
p2.nr := 2;
p2.defaultUnicastLocatorList := (numLocators => int(1,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, others => EMPTY_LOCATOR));
p2.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) := '1';
p2.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER):= '1';
p2.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) := '1';
p2.availableBuiltinEndpoints(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) := '1';
for i in 0 to fixed_writers'length-1 loop
fixed_writers(i).entityId := gen_rand_entityid_2(FALSE);
end loop;
for i in 0 to fixed_readers'length-1 loop
fixed_readers(i).entityId := gen_rand_entityid_2(TRUE);
end loop;
e1.participant := p2;
e1.entityId := gen_rand_entityid_2(FALSE);
e1.topic_name := ENDPOINT_TOPIC(0);
e1.type_name := ENDPOINT_TYPE(0);
e2.participant := p2;
e2.entityId := gen_rand_entityid_2(TRUE);
e2.topic_name := ENDPOINT_TOPIC(0);
e2.type_name := ENDPOINT_TYPE(0);
user_data := convert_string("USER_DATA" & (10 to 256 => NUL));
group_data := convert_string("GROUP_DATA" & (11 to 256 => NUL));
topic_data := convert_string("TOPIC_DATA" & (11 to 256 => NUL));
Log("Initiating Test", INFO);
stim_done <= '0';
start <= '0';
reset <= '1';
wait until rising_edge(clk);
wait until rising_edge(clk);
reset <= '0';
-- *Insert Participant 0*
-- Contains the same Endpoints as our Participant, as defined above
Log("Match Participant 0 [Compatible]", INFO);
sub.writerSN := p0_sn;
gen_participant_data(p0, sub.data);
gen_sentinel(sub.data);
gen_rtps_handler_out(sub, gen_rand_loc_2, TRUE, TIME_INVALID, p0.guidPrefix, stimulus);
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub.data := EMPTY_TEST_PACKET;
p0_sn := p0_sn + 1;
-- *Insert Participant 1*
-- Contains the same Endpoints as Participant 0, but in little Endian
Log("Match Participant 1 [Compatible, Little Endian]", INFO);
sub.writerSN := p1_sn;
gen_participant_data(p1, sub.data);
gen_sentinel(sub.data);
gen_rtps_handler_out(sub, gen_rand_loc_2, TRUE, TIME_INVALID, p1.guidPrefix, stimulus);
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub.data := EMPTY_TEST_PACKET;
p1_sn := p1_sn + 1;
-- *Insert Participant 2*
-- Used for extra Endpoint testing (e.g. unsupported QoS)
Log("Match Participant 2 [Compatible]", INFO);
sub.writerSN := p2_sn;
gen_participant_data(p2, sub.data);
gen_sentinel(sub.data);
gen_rtps_handler_out(sub, gen_rand_loc_2, TRUE, TIME_INVALID, p2.guidPrefix, stimulus);
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub.data := EMPTY_TEST_PACKET;
p2_sn := p2_sn + 1;
-- *Fixed Writers (Participant 0)*
for i in 0 to NUM_WRITERS-1 loop
Log("Fixed Writer " & to_string(i) & ", Participant 0", INFO);
sub_p.writerSN := p0_snp;
endpoint := fixed_writers(i);
endpoint.participant := p0;
gen_endpoint_data(endpoint, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
gen_match_frame(endpoint, reference);
wr_sig := gen_wr(i, FALSE);
if (or wr_sig = '1') then
push_reference;
end if;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p0_snp := p0_snp + 1;
end loop;
-- *Fixed Writers (Participant 1)[Little Endian]*
for i in 0 to NUM_WRITERS-1 loop
Log("Fixed Writer " & to_string(i) & ", Participant 1 [Little Endian]", INFO);
sub_p.writerSN := p1_snp;
endpoint := fixed_writers(i);
endpoint.participant := p1;
endpoint.littleEndian:= '1';
gen_endpoint_data(endpoint, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
gen_match_frame(endpoint, reference);
wr_sig := gen_wr(i, FALSE);
if (or wr_sig = '1') then
push_reference;
end if;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p1_snp := p1_snp + 1;
end loop;
-- *Fixed Readers (Participant 0)*
for i in 0 to NUM_READERS-1 loop
Log("Fixed Reader " & to_string(i) & ", Participant 0", INFO);
sub_s.writerSN := p0_sns;
endpoint := fixed_readers(i);
endpoint.participant := p0;
gen_endpoint_data(endpoint, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
gen_match_frame(endpoint, reference);
wr_sig := gen_wr(i, TRUE);
if (or wr_sig = '1') then
push_reference;
end if;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET;
p0_sns := p0_sns + 1;
end loop;
-- *Fixed Readers (Participant 1)[Little Endian]*
for i in 0 to NUM_READERS-1 loop
Log("Fixed Reader " & to_string(i) & ", Participant 1", INFO);
sub_s.writerSN := p1_sns;
endpoint := fixed_readers(i);
endpoint.participant := p1;
endpoint.littleEndian:= '1';
gen_endpoint_data(endpoint, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
gen_match_frame(endpoint, reference);
wr_sig := gen_wr(i, TRUE);
if (or wr_sig = '1') then
push_reference;
end if;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET;
p1_sns := p1_sns + 1;
end loop;
-- *Remove Participant 1*
Log("Unmatch Participant 1", INFO);
sub.writerSN := p1_sn;
p1.domainId := int(2, DOMAIN_ID_WIDTH);
p1.match := UNMATCH;
gen_participant_data(p1, sub.data);
gen_sentinel(sub.data);
gen_rtps_handler_out(sub, gen_rand_loc_2, TRUE, TIME_INVALID, p1.guidPrefix, stimulus);
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub.data := EMPTY_TEST_PACKET;
p1_sn := p1_sn + 1;
-- Unmatch Participant 1 Endpoints
for i in 0 to NUM_WRITERS-1 loop
endpoint := fixed_writers(i);
endpoint.participant := p1;
endpoint.littleEndian := '1';
endpoint.match := UNMATCH;
gen_match_frame(endpoint, reference);
wr_sig := gen_wr(i, FALSE);
if (or wr_sig = '1') then
push_reference;
end if;
reference := EMPTY_TEST_PACKET;
end loop;
for i in 0 to NUM_READERS-1 loop
endpoint := fixed_readers(i);
endpoint.participant := p1;
endpoint.littleEndian := '1';
endpoint.match := UNMATCH;
gen_match_frame(endpoint, reference);
wr_sig := gen_wr(i, TRUE);
if (or wr_sig = '1') then
push_reference;
end if;
reference := EMPTY_TEST_PACKET;
end loop;
-- *Participant 2 Endpoints*
-- Writers
Log("Match Participant 2 Writer [Durability Persistent]", INFO);
sub_p.writerSN := p2_snp;
endpoint := DEFAULT_ENDPOINT_DATA;
endpoint.entityId := gen_rand_entityid_2(FALSE);
endpoint.participant := p2;
endpoint.topic_name := ENDPOINT_TOPIC(0);
endpoint.type_name := ENDPOINT_TYPE(0);
endpoint.durability := PERSISTENT_DURABILITY_QOS;
gen_endpoint_data(endpoint, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
gen_match_frame(endpoint, reference);
wr_sig := (0 => '1', 3 => '1', 9 => '1', 10 => '1', 15 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p2_snp := p2_snp + 1;
Log("Match Participant 2 Writer [Presentation Group]", INFO);
sub_p.writerSN := p2_snp;
endpoint := DEFAULT_ENDPOINT_DATA;
endpoint.entityId := gen_rand_entityid_2(FALSE);
endpoint.participant := p2;
endpoint.topic_name := ENDPOINT_TOPIC(0);
endpoint.type_name := ENDPOINT_TYPE(0);
endpoint.presentation := GROUP_PRESENTATION_QOS;
gen_endpoint_data(endpoint, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
gen_match_frame(endpoint, reference);
wr_sig := (0 => '1', 4 => '1', 9 => '1', 10 => '1', 15 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p2_snp := p2_snp + 1;
Log("Ignore Participant 2 Writer [Ownership Exclusive]", INFO);
sub_p.writerSN := p2_snp;
endpoint := DEFAULT_ENDPOINT_DATA;
endpoint.entityId := gen_rand_entityid_2(FALSE);
endpoint.participant := p2;
endpoint.topic_name := ENDPOINT_TOPIC(0);
endpoint.type_name := ENDPOINT_TYPE(0);
endpoint.ownership := EXCLUSIVE_OWNERSHIP_QOS;
gen_endpoint_data(endpoint, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p2_snp := p2_snp + 1;
Log("Match Participant 2 Writer [USER_DATA, TOPIC_DATA, GROUP_DATA, MAX_SERIALIZED_PAYLOAD]", INFO);
sub_p.writerSN := p2_snp;
endpoint := DEFAULT_ENDPOINT_DATA;
endpoint.entityId := gen_rand_entityid_2(FALSE);
endpoint.participant := p2;
endpoint.topic_name := ENDPOINT_TOPIC(0);
endpoint.type_name := ENDPOINT_TYPE(0);
endpoint.user_data := user_data;
endpoint.topic_data := topic_data;
endpoint.group_data := group_data;
endpoint.max_size_serialized:= std_logic_vector(to_unsigned(65000, CDR_LONG_WIDTH));
gen_endpoint_data(endpoint, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
gen_match_frame(endpoint, reference);
wr_sig := (0 => '1', 9 => '1', 10 => '1', 15 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p2_snp := p2_snp + 1;
Log("ignore Participant 2 Writer [incompatible MAX_SERIALIZED_PAYLOAD]", INFO);
sub_p.writerSN := p2_snp;
endpoint := DEFAULT_ENDPOINT_DATA;
endpoint.entityId := gen_rand_entityid_2(FALSE);
endpoint.participant := p2;
endpoint.topic_name := ENDPOINT_TOPIC(0);
endpoint.type_name := ENDPOINT_TYPE(0);
endpoint.user_data := user_data;
endpoint.topic_data := topic_data;
endpoint.group_data := group_data;
endpoint.max_size_serialized:= std_logic_vector(to_unsigned(66000, CDR_LONG_WIDTH));
gen_endpoint_data(endpoint, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p2_snp := p2_snp + 1;
-- Readers
Log("Ignore Participant 2 Reader [Durability Persistent]", INFO);
sub_s.writerSN := p2_sns;
endpoint := DEFAULT_ENDPOINT_DATA;
endpoint.entityId := gen_rand_entityid_2(TRUE);
endpoint.participant := p2;
endpoint.topic_name := ENDPOINT_TOPIC(0);
endpoint.type_name := ENDPOINT_TYPE(0);
endpoint.durability := PERSISTENT_DURABILITY_QOS;
gen_endpoint_data(endpoint, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET;
p2_sns := p2_sns + 1;
Log("Ignore Participant 2 Reader [Presentation Group]", INFO);
sub_s.writerSN := p2_sns;
endpoint := DEFAULT_ENDPOINT_DATA;
endpoint.entityId := gen_rand_entityid_2(TRUE);
endpoint.participant := p2;
endpoint.topic_name := ENDPOINT_TOPIC(0);
endpoint.type_name := ENDPOINT_TYPE(0);
endpoint.presentation := GROUP_PRESENTATION_QOS;
gen_endpoint_data(endpoint, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET;
p2_sns := p2_sns + 1;
Log("Ignore Participant 2 Reader [Ownership Exclusive]", INFO);
sub_s.writerSN := p2_sns;
endpoint := DEFAULT_ENDPOINT_DATA;
endpoint.entityId := gen_rand_entityid_2(TRUE);
endpoint.participant := p2;
endpoint.topic_name := ENDPOINT_TOPIC(0);
endpoint.type_name := ENDPOINT_TYPE(0);
endpoint.ownership := EXCLUSIVE_OWNERSHIP_QOS;
gen_endpoint_data(endpoint, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET;
p2_sns := p2_sns + 1;
Log("Match Participant 2 Reader [USER_DATA, TOPIC_DATA, GROUP_DATA, EXPECTS_INLINE_QOS]", INFO);
sub_s.writerSN := p2_sns;
endpoint := DEFAULT_ENDPOINT_DATA;
endpoint.entityId := gen_rand_entityid_2(TRUE);
endpoint.participant := p2;
endpoint.topic_name := ENDPOINT_TOPIC(0);
endpoint.type_name := ENDPOINT_TYPE(0);
endpoint.user_data := user_data;
endpoint.topic_data := topic_data;
endpoint.group_data := group_data;
endpoint.expectsInlineQoS(0):= '1';
gen_endpoint_data(endpoint, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, gen_rand_loc_2, TRUE, TIME_INVALID, endpoint.participant.guidPrefix, stimulus);
gen_match_frame(endpoint, reference);
wr_sig := (NUM_READERS => '1', NUM_READERS+4 => '1', NUM_READERS+5 => '1', NUM_READERS+7 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET;
p2_sns := p2_sns + 1;
-- Reader/Writer Match/Unmatch
Log("Match Participant 2 Writer [Default]", INFO);
sub_p.writerSN := p2_snp;
gen_endpoint_data(e1, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, e1.participant.guidPrefix, stimulus);
gen_match_frame(e1, reference);
wr_sig := (0 => '1', 9 => '1', 10 => '1', 15 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p2_snp := p2_snp + 1;
Log("Match Participant 2 Reader [Default]", INFO);
sub_s.writerSN := p2_sns;
gen_endpoint_data(e2, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, gen_rand_loc_2, TRUE, TIME_INVALID, e2.participant.guidPrefix, stimulus);
gen_match_frame(e2, reference);
wr_sig := (NUM_READERS => '1', NUM_READERS+4 => '1', NUM_READERS+5 => '1', NUM_READERS+7 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET;
p2_sns := p2_sns + 1;
Log("Update Participant 2 Writer [Unicast Locators (1 valid, 2 invalid)]", INFO);
sub_p.writerSN := p2_snp;
e1.unicastLocatorList := (numLocators => int(4,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, 1 => gen_rand_loc_2, 2 => gen_rand_loc_2, 3 => gen_rand_loc_2, others => EMPTY_LOCATOR));
e1.unicastLocatorList.locator(1).kind := LOCATOR_KIND_UDPv6;
e1.unicastLocatorList.locator(2).addr := (others => '0');
e1.unicastLocatorList.locator(3).portn := (others => '0');
gen_endpoint_data(e1, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, e1.participant.guidPrefix, stimulus);
gen_match_frame(e1, reference);
wr_sig := (0 => '1', 9 => '1', 10 => '1', 15 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p2_snp := p2_snp + 1;
Log("Update Participant 2 Reader [Multicast Locator (1 valid, 2 invalid)]", INFO);
sub_s.writerSN := p2_sns;
e2.multicastLocatorList := (numLocators => int(4,CDR_LONG_WIDTH), locator => (0 => gen_rand_loc_2, 1 => gen_rand_loc_2, 2 => gen_rand_loc_2, 3 => gen_rand_loc_2, others => EMPTY_LOCATOR));
e2.multicastLocatorList.locator(1).kind := LOCATOR_KIND_UDPv6;
e2.multicastLocatorList.locator(2).addr := (others => '0');
e2.multicastLocatorList.locator(3).portn := (others => '0');
gen_endpoint_data(e2, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, gen_rand_loc_2, TRUE, TIME_INVALID, e2.participant.guidPrefix, stimulus);
gen_match_frame(e2, reference);
wr_sig := (NUM_READERS => '1', NUM_READERS+4 => '1', NUM_READERS+5 => '1', NUM_READERS+7 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET;
p2_sns := p2_sns + 1;
Log("Change Match Participant 2 Writer [Reliability Best Effort]", INFO);
sub_p.writerSN := p2_snp;
e1.reliability := BEST_EFFORT_RELIABILITY_QOS;
gen_endpoint_data(e1, sub_p.data);
gen_sentinel(sub_p.data);
gen_rtps_handler_out(sub_p, gen_rand_loc_2, TRUE, TIME_INVALID, e1.participant.guidPrefix, stimulus);
-- MATCH
gen_match_frame(e1, reference);
wr_sig := (15 => '1', others => '0');
push_reference;
reference := EMPTY_TEST_PACKET;
-- UNMATCH
e1.match := UNMATCH;
gen_match_frame(e1, reference);
wr_sig := (0 => '1', 9 => '1', 10 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_p.data := EMPTY_TEST_PACKET;
p2_snp := p2_snp + 1;
Log("Change Match Participant 2 Reader [Topic & Type Change]", INFO);
sub_s.writerSN := p2_sns;
e2.topic_name := ENDPOINT_TOPIC(2);
e2.type_name := ENDPOINT_TYPE(2);
gen_endpoint_data(e2, sub_s.data);
gen_sentinel(sub_s.data);
gen_rtps_handler_out(sub_s, gen_rand_loc_2, TRUE, TIME_INVALID, e2.participant.guidPrefix, stimulus);
-- MATCH
gen_match_frame(e2, reference);
wr_sig := (NUM_READERS+2 => '1', others => '0');
push_reference;
reference := EMPTY_TEST_PACKET;
-- UNMATCH
e2.match := UNMATCH;
gen_match_frame(e2, reference);
wr_sig := (NUM_READERS => '1', NUM_READERS+4 => '1', NUM_READERS+5 => '1', NUM_READERS+7 => '1', others => '0');
push_reference;
start_test;
wait_on_complete;
stimulus := EMPTY_TEST_PACKET;
reference := EMPTY_TEST_PACKET;
sub_s.data := EMPTY_TEST_PACKET;
p2_sns := p2_sns + 1;
stim_done <= '1';
wait until check_done = '1';
ReportAlerts;
std.env.stop;
wait;
end process;
clock_prc : process
begin
clk <= '0';
wait for 25 ns;
clk <= '1';
wait for 25 ns;
end process;
in_empty_prc : process
begin
in_empty <= '0';
wait until rd_sig = '1';
wait until rising_edge(clk);
in_empty <= '1';
wait until rising_edge(clk);
end process;
endpoint_full_prc : process
begin
endpoint_full <= (others => '0');
wait until (or endpoint_wr) = '1';
wait until rising_edge(clk);
endpoint_full <= (others => '1');
wait until rising_edge(clk);
end process;
alert_prc : process(all)
begin
if rising_edge(clk) then
alertif(in_empty = '1' and rd_sig = '1', "Input FIFO read signal high while empty signal high", ERROR);
alertif(endpoint_full /= (0 to NUM_ENDPOINTS-1 => '0') and (endpoint_wr /= (0 to NUM_ENDPOINTS-1 => '0')), "Endpoint FIFO write signal high while full signal high", ERROR);
end if;
end process;
input_prc : process(all)
begin
data_in <= stimulus.data(cnt_stim);
last_word_in <= stimulus.last(cnt_stim);
case (stim_stage) is
when IDLE =>
packet_sent <= '1';
when BUSY =>
packet_sent <= '0';
end case;
if rising_edge(clk) then
if (reset = '1') then
cnt_stim <= 0;
stim_stage <= IDLE;
else
case (stim_stage) is
when IDLE =>
if (start = '1') then
stim_stage <= BUSY;
cnt_stim <= 0;
end if;
when BUSY =>
if (cnt_stim = stimulus.length) then
stim_stage <= IDLE;
elsif (rd_sig = '1') then
cnt_stim <= cnt_stim + 1;
end if;
end case;
end if;
end if;
end process;
output_prc : process(all)
begin
check_done <= '0';
if rising_edge(clk) then
if (endpoint_wr /= (0 to NUM_ENDPOINTS-1 => '0')) then
SB.Check(endpoint_wr & last_word_out & data_out);
end if;
if (stim_done = '1' and SB.empty) then
check_done <= '1';
end if;
end if;
end process;
watchdog : process
begin
wait for 1 ms;
Alert("Test timeout", FAILURE);
std.env.stop;
end process;
end architecture;

View File

@ -0,0 +1,17 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library osvvm; -- Utility Library
context osvvm.OsvvmContext;
use work.rtps_test_package.all;
package ScoreBoardPkg_builtin_endpoint is new osvvm.ScoreboardGenericPkg
generic map (
ExpectedType => std_logic_vector,
ActualType => std_logic_vector,
Match => std_match,
expected_to_string => to_string1,
actual_to_string => to_string1
);

View File

@ -13,9 +13,9 @@ package user_config is
-- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.80]
constant DEFAULT_IPv4_ADDRESS : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := x"C0A80080";
-- Number of RTPS Writer Endpoints
constant NUM_WRITERS : natural := 2;
constant NUM_WRITERS : natural := 8;
-- Number of RTPS Reader Endpoints
constant NUM_READERS : natural := 2;
constant NUM_READERS : natural := 17;
-- Number of RTPS Endpoints (Do not modify)
constant NUM_ENDPOINTS : natural := NUM_READERS+NUM_WRITERS;
-- PB Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1)
@ -43,9 +43,19 @@ package user_config is
-- Array denoting if Endpoints use Keyed Topics
constant ENDPOINT_WITH_KEY : USER_BOOLEAN_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => FALSE);
-- Array mapping Topic Names to Endpoints
constant ENDPOINT_TOPIC_STRING : USER_STRING_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => "Placeholder" & (12 to 256 => NUL));
constant ENDPOINT_TOPIC_STRING : USER_STRING_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
2 => "TOPIC_2" & (8 to 256 => NUL),
NUM_READERS+2 => "TOPIC_2" & (8 to 256 => NUL),
others => "TOPIC_1" & (8 to 256 => NUL)
);
-- Array mapping Type Names to Endpoints
constant ENDPOINT_TYPE_STRING : USER_STRING_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => "Placeholder" & (12 to 256 => NUL));
constant ENDPOINT_TYPE_STRING : USER_STRING_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
1 => "TYPE_2" & (7 to 256 => NUL),
2 => "TYPE_2" & (7 to 256 => NUL),
NUM_READERS+1 => "TYPE_2" & (7 to 256 => NUL),
NUM_READERS+2 => "TYPE_2" & (7 to 256 => NUL),
others => "TYPE_1" & (7 to 256 => NUL)
);
-- *TIMING CHARACTERISTICS*
-- Timing Characteristics for Participant
constant PARTICIPANT_ANNOUNCEMENT_PERIOD : DURATION_TYPE := gen_duration(30,0); -- 30 s
@ -68,41 +78,126 @@ package user_config is
--***ENDPOINT DDS QOS***
-- Array mapping DURABILITY QoS to Endpoints
constant ENDPOINT_DURABILITY_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_QOS);
constant ENDPOINT_DURABILITY_SERVICE_CLEANUP_DELAY : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY);
constant ENDPOINT_DURABILITY_SERVICE_HISTORY : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_HISTORY);
constant ENDPOINT_DURABILITY_SERVICE_HISTORY_DEPTH : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_HISTORY_DEPTH);
constant ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES);
constant ENDPOINT_DURABILITY_SERVICE_MAX_INSTANCES : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES);
constant ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE);
constant ENDPOINT_DURABILITY_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
3 => TRANSIENT_LOCAL_DURABILITY_QOS,
NUM_READERS+4 => TRANSIENT_LOCAL_DURABILITY_QOS,
others => DEFAULT_DURABILITY_QOS
);
constant ENDPOINT_DURABILITY_SERVICE_CLEANUP_DELAY : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => gen_duration(86400,0),
others => DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY
);
constant ENDPOINT_DURABILITY_SERVICE_HISTORY : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => KEEP_ALL_HISTORY_QOS,
others => DEFAULT_DURABILITY_SERVICE_HISTORY
);
constant ENDPOINT_DURABILITY_SERVICE_HISTORY_DEPTH : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => std_logic_vector(to_unsigned(10, CDR_LONG_WIDTH)),
others => DEFAULT_DURABILITY_SERVICE_HISTORY_DEPTH
);
constant ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => std_logic_vector(to_unsigned(10, CDR_LONG_WIDTH)),
others => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES
);
constant ENDPOINT_DURABILITY_SERVICE_MAX_INSTANCES : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => std_logic_vector(to_unsigned(5, CDR_LONG_WIDTH)),
others => DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES
);
constant ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => std_logic_vector(to_unsigned(5, CDR_LONG_WIDTH)),
others => DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE
);
-- Array mapping PRESENTATION QoS to Endpoints
constant ENDPOINT_PRESENTATION_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_PRESENTATION_QOS);
constant ENDPOINT_COHERENT_ACCESS : USER_BOOLEAN_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_COHERENT_ACCESS);
constant ENDPOINT_ORDERED_ACCESS : USER_BOOLEAN_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_ORDERED_ACCESS);
constant ENDPOINT_PRESENTATION_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
4 => TOPIC_PRESENTATION_QOS,
NUM_READERS+4 => TOPIC_PRESENTATION_QOS,
NUM_READERS+5 => TOPIC_PRESENTATION_QOS,
others => DEFAULT_PRESENTATION_QOS
);
constant ENDPOINT_COHERENT_ACCESS : USER_BOOLEAN_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
5 => TRUE,
6 => TRUE,
NUM_READERS+4 => TRUE,
NUM_READERS+5 => TRUE,
others => DEFAULT_COHERENT_ACCESS
);
constant ENDPOINT_ORDERED_ACCESS : USER_BOOLEAN_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
6 => TRUE,
NUM_READERS+5 => TRUE,
others => DEFAULT_ORDERED_ACCESS
);
-- Array mapping DEADLINE QoS to Endpoints
constant ENDPOINT_DEADLINE_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DEADLINE_QOS);
constant ENDPOINT_DEADLINE_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
7 => gen_duration(10,0),
8 => gen_duration(20,0),
NUM_READERS+4 => gen_duration(15,0),
others => DEFAULT_DEADLINE_QOS
);
-- Array mapping LATENCY_BUDGET QoS to Endpoints
constant ENDPOINT_LATENCY_BUDGET_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_LATENCY_BUDGET_QOS);
constant ENDPOINT_LATENCY_BUDGET_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
9 => gen_duration(0,500000000),
10 => gen_duration(2,0),
NUM_READERS+6 => gen_duration(1,0),
others => DEFAULT_LATENCY_BUDGET_QOS
);
-- Array mapping OWNERSHIP QoS to Endpoints
constant ENDPOINT_OWNERSHIP_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_OWNERSHIP_QOS);
constant ENDPOINT_OWNERSHIP_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
others => DEFAULT_OWNERSHIP_QOS
);
-- Array mapping OWNERSHIP_STRENGTH QoS to Endpoints (Only relevant to Writers)
constant ENDPOINT_OWNERSHIP_STRENGTH_QOS : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_OWNERSHIP_STRENGTH_QOS);
constant ENDPOINT_OWNERSHIP_STRENGTH_QOS : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => std_logic_vector(to_unsigned(2, CDR_LONG_WIDTH)),
others => DEFAULT_OWNERSHIP_STRENGTH_QOS
);
-- Array mapping LIVELINESS QoS to Endpoints
constant ENDPOINT_LIVELINESS_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_LIVELINESS_QOS);
constant ENDPOINT_LEASE_DURATION : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_LEASE_DURATION);
constant ENDPOINT_LIVELINESS_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
11 => MANUAL_BY_PARTICIPANT_LIVELINESS_QOS,
12 => MANUAL_BY_TOPIC_LIVELINESS_QOS,
NUM_READERS+4 => MANUAL_BY_PARTICIPANT_LIVELINESS_QOS,
others => DEFAULT_LIVELINESS_QOS
);
constant ENDPOINT_LEASE_DURATION : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
11 => gen_duration(20,0),
12 => gen_duration(20,0),
13 => gen_duration(10,0),
14 => gen_duration(20,0),
NUM_READERS+4 => gen_duration(15,0),
others => DEFAULT_LEASE_DURATION
);
-- Array mapping TIME_BASED_FILTER QoS to Endpoints (Only relevant to Readers)
constant ENDPOINT_TIME_BASED_FILTER_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_TIME_BASED_FILTER_QOS);
constant ENDPOINT_TIME_BASED_FILTER_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
7 => gen_duration(5,0),
8 => gen_duration(5,0),
others => DEFAULT_TIME_BASED_FILTER_QOS
);
-- XXX: PARTITION QoS Ignored
-- Array mapping RELIABILITY QoS to Endpoints
constant ENDPOINT_RELIABILITY_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_RELIABILTY_QOS);
constant ENDPOINT_RELIABILITY_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
15 => BEST_EFFORT_RELIABILITY_QOS,
NUM_READERS+3 => BEST_EFFORT_RELIABILITY_QOS,
others => DEFAULT_RELIABILTY_QOS
);
-- (Only relevant to Writers)
constant ENDPOINT_MAX_BLOCKING_TIME : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_MAX_BLOCKING_TIME);
constant ENDPOINT_MAX_BLOCKING_TIME : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => gen_duration(2,0),
others => DEFAULT_MAX_BLOCKING_TIME
);
-- Array mapping TRANSPORT_PRIORITY QoS to Endpoints (Only relevant to Writers)
constant ENDPOINT_TRANSPORT_PRIORITY_QOS : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_TRANSPORT_PRIORITY_QOS);
constant ENDPOINT_TRANSPORT_PRIORITY_QOS : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => std_logic_vector(to_unsigned(3, CDR_LONG_WIDTH)),
others => DEFAULT_TRANSPORT_PRIORITY_QOS
);
-- Array mapping LIFESPAN QoS to Endpoints (Only relevant to Writers)
constant ENDPOINT_LIFESPAN_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_LIFESPAN_QOS);
constant ENDPOINT_LIFESPAN_QOS : USER_DURATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
NUM_READERS+7 => gen_duration(30,0),
others => DEFAULT_LIFESPAN_QOS
);
-- Array mapping DESTINATION_ORDER QoS to Endpoints
constant ENDPOINT_DESTINATION_ORDER_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_DESTINATION_ORDER_QOS);
constant ENDPOINT_DESTINATION_ORDER_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (
16 => BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS,
NUM_READERS+4 => BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS,
others => DEFAULT_DESTINATION_ORDER_QOS
);
-- Array mapping HISTORY QoS to Endpoints
constant ENDPOINT_HISTORY_QOS : USER_ENUMERATION_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_HISTORY_QOS);
constant ENDPOINT_HISTORY_DEPTH : USER_LONG_ARRAY_TYPE(0 to NUM_ENDPOINTS-1) := (others => DEFAULT_HISTORY_DEPTH);
@ -120,4 +215,6 @@ package user_config is
-- NOTE: The buffer will not only store participants, but also endpoint data
-- Used to determine the size of the builtin endpoint buffer
constant MAX_REMOTE_PARTICIPANTS : natural := 50;
constant TEST_STRING : string := "TEST_CONFIG_1";
end package;

View File

@ -10,12 +10,15 @@ analyze ../rtps_config_package.vhd
analyze ../rtps_test_package.vhd
analyze ../rtps_handler.vhd
analyze ../rtps_builtin_endpoint.vhd
analyze test_ram.vhd
analyze ScoreBoard_test_memory.vhd
analyze Level_0/rtps_handler_test1.vhd
analyze Level_0/rtps_handler_test2.vhd
analyze test_ram.vhd
analyze ScoreBoard_test_memory.vhd
analyze Level_0/rtps_builtin_endpoint_test1.vhd
analyze ScoreBoard_builtin_endpoint.vhd
analyze Level_0/rtps_builtin_endpoint_test2.vhd
#simulate rtps_handler_test1
#simulate rtps_handler_test2
simulate rtps_builtin_endpoint_test1
#simulate rtps_builtin_endpoint_test1
simulate rtps_builtin_endpoint_test2

View File

@ -10,6 +10,7 @@ use work.rtps_config_package.all;
-- TODO: Initialise RAM to zeroes
-- TODO: Skip Packet while we are waiting for memory operation to complete
-- TODO: add_res is still valid after removal. So we could continue searching the next orphan endpoint from that address on
-- TODO: is it really necessary to process Sequence Numbers in sequence? Could we not just accept any higher Sequence Number?
entity rtps_builtin_endpoint is
port (
@ -60,9 +61,9 @@ architecture arch of rtps_builtin_endpoint is
--*****TYPE DECLARATION*****
-- FSM states. Explained below in detail
type STAGE_TYPE is (IDLE, PACKET_HEADER, PACKET_SRC_ADDR, PACKET_SRC_ENTITYID, PACKET_SRC_GUIDPREFIX, PACKET_DEST_ENTITYID,
CHECK_SRC_ENTITYID, LATCH_SEQ_NR, PROCESS_DATA, PROCESS_MESSAGE, PROCESS_GAP, PROCESS_GAP_SEQUENCE_NUMBERS, PROCESS_PL,
CHECK_SRC_ENTITYID, LATCH_SEQ_NR, PROCESS_DATA, PROCESS_MESSAGE, PROCESS_GAP, PROCESS_GAP_SEQUENCE_NUMBERS, PROCESS_PL, CHECK_DEFAULT,
LATCH_STRING_LENGTH, COMPARE_STRING, RXO_DURABILITY, RXO_DEADLINE, RXO_LIVELINESS, RXO_LEASE_DURATION, LATCH_LEASE_DURATION,
RXO_RELIABILITY, RXO_DESTINATION_ORDER, RXO_OWNERSHIP, RXO_PRESENTATION, RXO_PARTITION, MATCH_DOMAIN_ID, MATCH_PROTOCOL_VERSION,
RXO_RELIABILITY, RXO_DESTINATION_ORDER, RXO_OWNERSHIP, RXO_PRESENTATION, RXO_PARTITION, RXO_LATENCY_BUDGET, CHECK_MAX_SIZE_SERIALIZED, MATCH_DOMAIN_ID, MATCH_PROTOCOL_VERSION,
LATCH_LOCATOR, LATCH_EXPECTS_INLINE_QOS, MATCH_GUID, CHECK_REMOTE_BUILTIN_ENDPOINTS, PARTICIPANT_MATCH_STAGE,
INITIATE_ENDPOINT_SEARCH, ENDPOINT_MATCH_STAGE, FIND_ORPHAN_ENDPOINT, PURGE_ORPHAN_ENDPOINT, INFORM_ENDPOINTS_MATCH,
INFORM_ENDPOINTS_UNMATCH, PARTICIPANT_STALE_CHECK, LATCH_REMOVED_GUIDPREFIX, PROCESS_HEARTBEAT, PROCESS_HEARTBEAT_SEQUENCE_NUMBERS,
@ -122,6 +123,8 @@ architecture arch of rtps_builtin_endpoint is
end record;
--*****CONSTANT DECLARATION*****
-- Max Serialized Payload Size in a UDP Stream (Bytes) [MAX_PAYLAOD(65536) - IPv4_HEADER(20) - UDP_HEADER(8) - RTPS_HEADER(20) - DATA_HEADER(24)]
constant UDP_MAX_SIZE_SERIALIZED : natural := 65464;
-- Memory Size in 4-Byte Words
constant BUILTIN_BUFFER_SIZE : natural := MAX_REMOTE_PARTICIPANTS*PARTICIPANT_FRAME_SIZE;
-- Memory Address Width
@ -155,11 +158,34 @@ architecture arch of rtps_builtin_endpoint is
-- Signifies if the Reader Endpoint expects in-line QoS
constant EXPECTS_INLINE_QOS_FLAG : natural := 0;
-- Highest Sequence Number of Publisher Data
constant PUB_SEQUENCENUMBER : SEQUENCENUMBER_TYPE := convert_to_double_word(to_unsigned(NUM_WRITERS, 64));
constant PUB_SEQUENCENUMBER : SEQUENCENUMBER_TYPE := convert_to_double_word(to_unsigned(NUM_WRITERS, 64));
-- Highest Sequence Number of Subscriber Data
constant SUB_SEQUENCENUMBER : SEQUENCENUMBER_TYPE := convert_to_double_word(to_unsigned(NUM_READERS, 64));
constant SUB_SEQUENCENUMBER : SEQUENCENUMBER_TYPE := convert_to_double_word(to_unsigned(NUM_READERS, 64));
-- Heartbeat/Liveliness Assertion Period
constant HEARTBEAT_PERIOD : DURATION_TYPE := work.rtps_package.min(MIN_ENDPOINT_LEASE_DURATION, PARTICIPANT_HEARTBEAT_PERIOD) - DURATION_DELTA;
-- *RECV FLAGS*
-- Width of the received array
constant RCVD_WIDTH : natural := 9;
-- Signifies that the DOMAIN_TAG was received
constant DOMAIN_TAG_RCVD : natural := 0;
-- Signifies that the DURABILITY QoS was received
constant DURABILITY_QOS_RCVD_FLAG : natural := 1;
-- Signifies that the PRESENTATION QoS was received
constant PRESENTATION_QOS_RCVD_FLAG : natural := 2;
-- Signifies that the DEADLINE QoS was received
constant DEADLINE_QOS_RCVD_FLAG : natural := 3;
-- Signifies that the LATENCY_BUDGET QoS was received
constant LATENCY_BUDGET_QOS_RCVD_FLAG : natural := 4;
-- Signifies that the OWNERSHIP QoS was received
constant OWNERSHIP_QOS_RCVD_FLAG : natural := 5;
-- Signifies that the LIVELINESS QoS was received
constant LIVELINESS_QOS_RCVD_FLAG : natural := 6;
-- Signifies that the RELIABILITY QoS was received
constant RELIABILITY_QOS_RCVD_FLAG : natural := 7;
-- Signifies that the DESTINATION_ORDER QoS was received
constant DESTINATION_ORDER_QOS_RCVD_FLAG : natural := 8;
-- Constant for zero Participant Data
constant ZERO_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE := (
meta_addr => (others => '0'),
@ -282,8 +308,8 @@ architecture arch of rtps_builtin_endpoint is
signal reset_max_pointer, reset_max_pointer_next : std_logic := '0';
-- Signifies if we currently are doing a Participant Stale Entry Check (Used to start Stale Checks between packet handling)
signal stale_check, stale_check_next : std_logic := '0';
-- Latch containing the GUID Prefix of the removed Participant from the memory
signal mem_guidprefix, mem_guidprefix_next : GUIDPREFIX_TYPE := (others => (others => '0'));
-- Latch containing the GUID Prefix of the removed Participant from the memory, and the Enity ID of the last Orphan Endpoint found
signal mem_guid, mem_guid_next : GUID_TYPE := (others => (others => '0'));
-- Toggle latching the "last_word_in" signal until reset
signal last_word_in_latch, last_word_in_latch_next : std_logic := '0';
-- Flags signifying which parts of the participant Data stored in memory to update
@ -333,9 +359,9 @@ architecture arch of rtps_builtin_endpoint is
signal extra_flags, extra_flags_next : std_logic_vector(EXTRA_FLAGS_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Long latch
signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
-- Signifies if the Participant Domain Tag was checked/matched
-- NOTE: Because the Domain Tag has a default value, we have to note if we received a PID_DOMAIN_TAG (since the default value is implied on its absence)
signal domain_tag_rcv, domain_tag_rcv_next : std_logic := '0';
-- Contains flags that signify which PIDs where received. This is done in order to use the default value for
-- not received elements.
signal rcvd, rcvd_next : std_logic_vector(RCVD_WIDTH-1 downto 0) := (others => '0');
@ -526,6 +552,7 @@ begin
-- FIND_ORPHAN_ENDPOINT Search for Orphan (whose parent Participant was removed) Endpoints in memory
-- PURGE_ORPHAN_ENDPOINT Remove Orphan Endpoint from memory
-- PROCESS_PL Parse RTPS Parameter List
-- CHECK_DEFAULT Match local endpoints against non-received QoS (default values) of remote
-- LATCH_STRING_LENGTH Store String Length
-- COMPARE_STRING Compare string to constants depending on string contents.
-- MATCH_GUID Compare GUID Prefix to source GUID Prefix of Packet
@ -544,6 +571,8 @@ begin
-- RXO_OWNERSHIP Check Compatibility of Ownership QoS
-- RXO_PRESENTATION Check Compatibility of Presentation QoS
-- RXO_PARTITION Check Compatibility of Partition QoS
-- RXO_LATENCY_BUDGET Check Compatibility of Latency Budget QoS
-- CHECK_MAX_SIZE_SERIALIZED Check if Publishers Max sent Payload Size is Compatible
-- PARTICIPANT_MATCH_STAGE Add compatible remote and remove incompatible remote Participants to and from memory. Update stored Sequence Numbers respectively
-- INITIATE_ENDPOINT_SEARCH Search for remote Endpoint in memory
-- ENDPOINT_MATCH_STAGE Add compatible remote and remove incompatible remote Participants to and from memory. Mark compatibility changes to local Endpoints.
@ -561,8 +590,9 @@ begin
-- SKIP_PARAMETER Skip rest of Parameter
-- SKIP_PACKET Skip rest of Packet
parse_prc: process(all)
variable tmp_endpoint_mask : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
variable rd_guard : std_logic := '0';
variable tmp_endpoint_mask : std_logic_vector(0 to NUM_ENDPOINTS-1) := (others => '0');
variable rd_guard : std_logic := '0';
variable tmp_default_qos_match : DEFAULT_QOS_MATCH_TYPE := READER_DEFAULT_QOS_MATCH;
begin
--DEFAULT Registered
stage_next <= stage;
@ -613,7 +643,7 @@ begin
last_word_in_latch_next <= last_word_in_latch;
count_next <= count;
long_latch_next <= long_latch;
domain_tag_rcv_next <= domain_tag_rcv;
rcvd_next <= rcvd;
-- DEFAULT Unregistered
rd_sig <= '0';
rd_guard := '0';
@ -695,8 +725,9 @@ begin
expects_inline_qos_rcv_next <= '0';
extra_flags_next <= (others => '0');
extra_flags_next(EXPECTS_INLINE_QOS_FLAG) <= DEFAULT_EXPECTS_INLINE_QOS;
domain_tag_rcv_next <= '0';
-- NOTE: We work with a "mark by default, and unmark on first missmatch" System
rcvd_next <= (others => '0');
-- NOTE: We work with a "mark by default, and unmark on first missmatch" System.
-- This assumes that each RxO QoS parameter occur only once in the list, else the behavior is undefined.
participant_match_next <= '1';
endpoint_mask_next <= (others => '1');
end if;
@ -1502,9 +1533,9 @@ begin
when LATCH_REMOVED_GUIDPREFIX =>
if (mem_op_done = '1') then
-- Help Stage needed to latch the GUID Prefix of the removed staled participant (Needed for the orphan search)
guid_next(0) <= mem_guidprefix(0);
guid_next(1) <= mem_guidprefix(1);
guid_next(2) <= mem_guidprefix(2);
guid_next(0) <= mem_guid(0);
guid_next(1) <= mem_guid(1);
guid_next(2) <= mem_guid(2);
stage_next <= FIND_ORPHAN_ENDPOINT;
end if;
when FIND_ORPHAN_ENDPOINT =>
@ -1524,6 +1555,8 @@ begin
-- Remove Orphaned Endpoint from Buffer
mem_opcode <= REMOVE_ENDPOINT;
mem_op_start <= '1';
-- Latch Orphan Entity ID
guid_next(3) <= mem_guid(3);
-- Mark UNMATCHES
endpoint_match_next <= (others => '0');
endpoint_unmatch_next <= convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS);
@ -1532,6 +1565,8 @@ begin
cnt_next <= 0;
-- Buffer has no more Orphans
else
-- Reset Orphan Search Flag
is_orphan_search_next <= '0';
-- DONE
stage_next <= SKIP_PACKET;
end if;
@ -1573,7 +1608,7 @@ begin
-- Mark String contents (Needed for string comparison)
string_content_next <= DOMAIN_TAG_TYPE;
-- Mark reception of DOMAIN_TAG
domain_tag_rcv_next <= '1';
rcvd_next(DOMAIN_TAG_RCVD) <= '1';
end if;
when PID_PROTOCOL_VERSION =>
-- Ignore in-line QoS
@ -1653,6 +1688,7 @@ begin
-- Only relevant for Endpoint Discovery Protocol
if(qos_flag = '0' and message_type = EDP) then
stage_next <= RXO_DURABILITY;
rcvd_next(DURABILITY_QOS_RCVD_FLAG) <= '1';
end if;
when PID_DEADLINE =>
-- Ignore in-line QoS
@ -1660,30 +1696,35 @@ begin
if(qos_flag = '0' and message_type = EDP) then
stage_next <= RXO_DEADLINE;
cnt_next <= 0;
rcvd_next(DEADLINE_QOS_RCVD_FLAG) <= '1';
end if;
when PID_LIVELINESS =>
-- Ignore in-line QoS
-- Only relevant for Endpoint Discovery Protocol
if(qos_flag = '0' and message_type = EDP) then
stage_next <= RXO_LIVELINESS;
rcvd_next(LIVELINESS_QOS_RCVD_FLAG) <= '1';
end if;
when PID_RELIABILITY =>
-- Ignore in-line QoS
-- Only relevant for Endpoint Discovery Protocol
if(qos_flag = '0' and message_type = EDP) then
stage_next <= RXO_RELIABILITY;
rcvd_next(RELIABILITY_QOS_RCVD_FLAG) <= '1';
end if;
when PID_DESTINATION_ORDER =>
-- Ignore in-line QoS
-- Only relevant for Endpoint Discovery Protocol
if(qos_flag = '0' and message_type = EDP) then
stage_next <= RXO_DESTINATION_ORDER;
rcvd_next(DESTINATION_ORDER_QOS_RCVD_FLAG) <= '1';
end if;
when PID_OWNERSHIP =>
-- Ignore in-line QoS
-- Only relevant for Endpoint Discovery Protocol
if(qos_flag = '0' and message_type = EDP) then
stage_next <= RXO_OWNERSHIP;
stage_next <= RXO_OWNERSHIP;
rcvd_next(OWNERSHIP_QOS_RCVD_FLAG) <= '1';
end if;
when PID_PRESENTATION =>
-- Ignore in-line QoS
@ -1691,6 +1732,7 @@ begin
if(qos_flag = '0' and message_type = EDP) then
stage_next <= RXO_PRESENTATION;
cnt_next <= 0;
rcvd_next(PRESENTATION_QOS_RCVD_FLAG) <= '1';
end if;
when PID_PARTITION =>
-- Ignore in-line QoS
@ -1698,6 +1740,14 @@ begin
if(qos_flag = '0' and message_type = EDP) then
stage_next <= RXO_PARTITION;
end if;
when PID_LATENCY_BUDGET =>
-- Ignore in-line QoS
-- Only relevant for Endpoint Discovery Protocol
if(qos_flag = '0' and message_type = EDP) then
stage_next <= RXO_LATENCY_BUDGET;
cnt_next <= 0;
rcvd_next(LATENCY_BUDGET_QOS_RCVD_FLAG) <= '1';
end if;
when PID_UNICAST_LOCATOR =>
-- Ignore in-line QoS
-- Only relevant for Endpoint Discovery Protocol
@ -1723,6 +1773,12 @@ begin
stage_next <= MATCH_GUID;
cnt_next <= 0;
end if;
when PID_DATA_MAX_SIZE_SERIALIZED =>
-- Ignore in-line QoS
-- Only relevant for Endpoint Discovery Protocol
if(qos_flag = '0' and message_type = EDP) then
stage_next <= CHECK_MAX_SIZE_SERIALIZED;
end if;
when PID_EXPECTS_INLINE_QOS =>
stage_next <= LATCH_EXPECTS_INLINE_QOS;
when PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT =>
@ -1737,9 +1793,6 @@ begin
when PID_PROPERTY_LIST =>
-- Ignore
null;
when PID_DATA_MAX_SIZE_SERIALIZED =>
-- Ignore
null;
when PID_ENTITY_NAME =>
-- Ignore
null;
@ -1765,9 +1818,6 @@ begin
-- Ignore
-- NOTE: Lifespan is requested via in-line QoS and handled directly by the endpoint
null;
when PID_LATENCY_BUDGET =>
-- Ignore
null;
when PID_DURABILITY_SERVICE =>
-- Ignore
null;
@ -1820,19 +1870,16 @@ begin
-- Ignore
null;
when PID_SENTINEL =>
-- SANITY CHECK: Default DOMAIN TAG Match
if (domain_tag_rcv = '0' and DOMAIN_TAG /= DEFAULT_DOMAIN_TAG) then
participant_match_next <= '0';
end if;
-- If Processing in-line QoS until now, start processing data
if(qos_flag = '1') then
-- Override QoS Flag
qos_flag_next <= '0';
stage_next <= PROCESS_DATA;
-- Else check Participant/Endpoint Matching
-- Else check Defaults
else
stage_next <= PARTICIPANT_MATCH_STAGE;
stage_next <= CHECK_DEFAULT;
end if;
when PID_LIST_END =>
-- TODO
null;
@ -1846,6 +1893,54 @@ begin
end if;
end case;
end if;
when CHECK_DEFAULT =>
-- DEFAULT
stage_next <= PARTICIPANT_MATCH_STAGE;
case (message_type) is
when PDP =>
-- Check Domain Tag against Default if necessary
if (rcvd(DOMAIN_TAG_RCVD) = '0' and DOMAIN_TAG /= DEFAULT_DOMAIN_TAG) then
participant_match_next <= '0';
end if;
when EDP =>
-- Defaults
tmp_endpoint_mask := (others => '1');
if (is_subscriber = '1') then
tmp_default_qos_match := READER_DEFAULT_QOS_MATCH;
else
tmp_default_qos_match := WRITER_DEFAULT_QOS_MATCH;
end if;
if (rcvd(DURABILITY_QOS_RCVD_FLAG) = '0') then
tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.DURABILITY_QOS;
end if;
if (rcvd(PRESENTATION_QOS_RCVD_FLAG) = '0') then
tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.PRESENTATION_QOS;
end if;
if (rcvd(DEADLINE_QOS_RCVD_FLAG) = '0') then
tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.DEADLINE_QOS;
end if;
if (rcvd(LATENCY_BUDGET_QOS_RCVD_FLAG) = '0') then
tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.LATENCY_BUDGET_QOS;
end if;
if (rcvd(OWNERSHIP_QOS_RCVD_FLAG) = '0') then
tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.OWNERSHIP_QOS;
end if;
if (rcvd(LIVELINESS_QOS_RCVD_FLAG) = '0') then
tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.LIVELINESS_QOS;
end if;
if (rcvd(RELIABILITY_QOS_RCVD_FLAG) = '0') then
tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.RELIABILITY_QOS;
end if;
if (rcvd(DESTINATION_ORDER_QOS_RCVD_FLAG) = '0') then
tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.DESTINATION_ORDER_QOS;
end if;
endpoint_mask_next <= endpoint_mask and tmp_endpoint_mask;
when others =>
null;
end case;
when LATCH_STRING_LENGTH =>
-- Input FIFO Guard
if (empty = '0') then
@ -2062,16 +2157,8 @@ begin
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered >= requested, with VOLATILE < TRANSIENT_LOCAL < TRANSIENT < PERSISTENT
for i in 0 to NUM_ENDPOINTS-1 loop
-- data-in is Subscriber-Requested
if (is_subscriber = '1') then
if (unsigned(data_in_swapped) > unsigned(ENDPOINT_DURABILITY_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (unsigned(data_in_swapped) < unsigned(ENDPOINT_DURABILITY_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_DURABILITY_QOS(i)))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
-- DONE
@ -2088,32 +2175,16 @@ begin
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered <= requested
for i in 0 to NUM_ENDPOINTS-1 loop
-- data-in is Subscriber-Requested
if (is_subscriber = '1') then
if (unsigned(data_in_swapped) < ENDPOINT_DEADLINE_QOS(i)(0)) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (unsigned(data_in_swapped) > ENDPOINT_DEADLINE_QOS(i)(0)) then
endpoint_mask_next(i) <= '0';
end if;
if (not check_qos_compatibility(is_subscriber, '0', unsigned(data_in_swapped), ENDPOINT_DEADLINE_QOS(i)(0))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
when 1 =>
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered <= requested
for i in 0 to NUM_ENDPOINTS-1 loop
-- data-in is Subscriber-Requested
if (is_subscriber = '1') then
if (unsigned(data_in_swapped) < ENDPOINT_DEADLINE_QOS(i)(1)) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (unsigned(data_in_swapped) > ENDPOINT_DEADLINE_QOS(i)(1)) then
endpoint_mask_next(i) <= '0';
end if;
if (not check_qos_compatibility(is_subscriber, '0', unsigned(data_in_swapped), ENDPOINT_DEADLINE_QOS(i)(1))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
-- DONE
@ -2130,16 +2201,8 @@ begin
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered >= requested, with AUTOMATIC < MANUAL_BY_PARTICIPANT < MANUAL_BY_TOPIC
for i in 0 to NUM_ENDPOINTS-1 loop
-- data-in is Subscriber-Requested
if (is_subscriber = '1') then
if (unsigned(data_in_swapped) > unsigned(ENDPOINT_LIVELINESS_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (unsigned(data_in_swapped) < unsigned(ENDPOINT_LIVELINESS_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_LIVELINESS_QOS(i)))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
@ -2157,32 +2220,16 @@ begin
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered <= requested
for i in 0 to NUM_ENDPOINTS-1 loop
-- data-in is Subscriber-Requested
if (is_subscriber = '1') then
if (unsigned(data_in_swapped) > ENDPOINT_LEASE_DURATION(i)(0)) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (unsigned(data_in_swapped) < ENDPOINT_LEASE_DURATION(i)(0)) then
endpoint_mask_next(i) <= '0';
end if;
if (not check_qos_compatibility(is_subscriber, '0', unsigned(data_in_swapped), ENDPOINT_LEASE_DURATION(i)(0))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
when 1 =>
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered <= requested
for i in 0 to NUM_ENDPOINTS-1 loop
-- data-in is Subscriber-Requested
if (is_subscriber = '1') then
if (unsigned(data_in_swapped) > ENDPOINT_LEASE_DURATION(i)(1)) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (unsigned(data_in_swapped) < ENDPOINT_LEASE_DURATION(i)(1)) then
endpoint_mask_next(i) <= '0';
end if;
if (not check_qos_compatibility(is_subscriber, '0', unsigned(data_in_swapped), ENDPOINT_LEASE_DURATION(i)(1))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
-- DONE
@ -2199,16 +2246,8 @@ begin
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered >= requested, with BEST_EFFORT < RELIABLE
for i in 0 to NUM_ENDPOINTS-1 loop
-- data-in is Subscriber-Requested
if (is_subscriber = '1') then
if (unsigned(data_in_swapped) > unsigned(ENDPOINT_RELIABILITY_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (unsigned(data_in_swapped) < unsigned(ENDPOINT_RELIABILITY_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_RELIABILITY_QOS(i)))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
@ -2224,16 +2263,8 @@ begin
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered >= requested, with BY_RECEPTION_TIMESTAMP < BY_SOURCE_TIMESTAMP
for i in 0 to NUM_ENDPOINTS-1 loop
-- data-in is Subscriber-Requested
if (is_subscriber = '1') then
if (unsigned(data_in_swapped) > unsigned(ENDPOINT_DESTINATION_ORDER_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (unsigned(data_in_swapped) < unsigned(ENDPOINT_DESTINATION_ORDER_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_DESTINATION_ORDER_QOS(i)))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
-- DONE
@ -2244,12 +2275,13 @@ begin
if (empty = '0') then
rd_guard := '1';
-- NOTE: Currently we only support Shared Ownership
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered = requested
if (data_in_swapped /= SHARED_OWNERSHIP_QOS) then
endpoint_mask_next <= (others => '0');
end if;
for i in 0 to NUM_ENDPOINTS-1 loop
if (data_in_swapped /= ENDPOINT_OWNERSHIP_QOS(i)) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
-- DONE
stage_next <= SKIP_PARAMETER;
end if;
@ -2264,16 +2296,8 @@ begin
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered >= requested, with INSTANCE < TOPIC < GROUP
for i in 0 to NUM_ENDPOINTS-1 loop
-- data-in is Subscriber-Requested
if (is_subscriber = '1') then
if (unsigned(data_in_swapped) > unsigned(ENDPOINT_PRESENTATION_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (unsigned(data_in_swapped) < unsigned(ENDPOINT_PRESENTATION_QOS(i))) then
endpoint_mask_next(i) <= '0';
end if;
if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_PRESENTATION_QOS(i)))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
when 1 =>
@ -2282,10 +2306,18 @@ begin
-- data-in is Subscriber-Requested
-- COMPATIBLE (DDS v1.4): requested=FALSE or requested=offered=TRUE
if (is_subscriber = '1') then
if (data_in(23) = '1' and ENDPOINT_COHERENT_ACCESS(i) = FALSE) then
if (data_in(24) = '1' and not ENDPOINT_COHERENT_ACCESS(i)) then
endpoint_mask_next(i) <= '0';
end if;
if (data_in(15) = '1' and ENDPOINT_ORDERED_ACCESS(i) = FALSE) then
if (data_in(16) = '1' and not ENDPOINT_ORDERED_ACCESS(i)) then
endpoint_mask_next(i) <= '0';
end if;
-- data-in is Publisher-Offered
else
if (data_in(24) = '0' and ENDPOINT_COHERENT_ACCESS(i)) then
endpoint_mask_next(i) <= '0';
end if;
if (data_in(16) = '0' and ENDPOINT_ORDERED_ACCESS(i)) then
endpoint_mask_next(i) <= '0';
end if;
end if;
@ -2309,6 +2341,47 @@ begin
-- DONE
stage_next <= SKIP_PARAMETER;
end if;
when RXO_LATENCY_BUDGET =>
-- Input FIFO Guard
if (empty = '0') then
rd_guard := '1';
cnt_next <= cnt + 1;
case (cnt) is
when 0 =>
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered <= requested
for i in 0 to NUM_ENDPOINTS-1 loop
if (not check_qos_compatibility(is_subscriber, '0', unsigned(data_in_swapped), ENDPOINT_LATENCY_BUDGET_QOS(i)(0))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
when 1 =>
-- Check QoS Compatibility (Unmark match on incompatibility)
-- COMPATIBLE (DDS v1.4): offered <= requested
for i in 0 to NUM_ENDPOINTS-1 loop
if (not check_qos_compatibility(is_subscriber, '0', unsigned(data_in_swapped), ENDPOINT_LATENCY_BUDGET_QOS(i)(1))) then
endpoint_mask_next(i) <= '0';
end if;
end loop;
-- DONE
stage_next <= SKIP_PARAMETER;
when others =>
null;
end case;
end if;
when CHECK_MAX_SIZE_SERIALIZED =>
-- Input FIFO Guard
if (empty = '0') then
rd_guard := '1';
-- Ignore Publishers that may need Fragmentation
if (is_subscriber = '0' and unsigned(data_in_swapped) > to_unsigned(UDP_MAX_SIZE_SERIALIZED, CDR_LONG_WIDTH)) then
endpoint_mask_next <= (others => '0');
end if;
-- DONE
stage_next <= SKIP_PARAMETER;
end if;
when PARTICIPANT_MATCH_STAGE =>
-- Wait for Participant Search to finish and Next Sequence Number to be set
if (mem_op_done = '1' and seq_prc_done = '1') then
@ -2402,18 +2475,24 @@ begin
-- Propagate Matches to local Endpoints
stage_next <= INFORM_ENDPOINTS_MATCH;
cnt_next <= 0;
-- No local Endpoint matches
else
-- Ignore
stage_next <= SKIP_PACKET;
end if;
-- Match in buffer (Existing Endpoint)
else
-- At least one local Endpoint match
if (endpoint_mask /= (endpoint_mask'range => '0')) then
-- Mark Endpoint match changes
tmp_endpoint_mask := convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS);
tmp_endpoint_mask := tmp_endpoint_mask xor endpoint_mask;
tmp_endpoint_mask := convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS) xor endpoint_mask;
-- Mark UNMATCHES
endpoint_unmatch_next <= tmp_endpoint_mask xor endpoint_mask;
endpoint_unmatch_next <= tmp_endpoint_mask and convert_from_bitmask_array(endpoint_mask_array, NUM_ENDPOINTS);
-- Mark NEW MATCHES
endpoint_match_next <= tmp_endpoint_mask and endpoint_mask;
-- NOTE: Mark all matches and resent the Endpoint Match Frame also to already Matched Endpoints,
-- in order to propagate possible data updates (e.g. new Locator)
--endpoint_match_next <= tmp_endpoint_mask and endpoint_mask;
endpoint_match_next <= endpoint_mask;
-- Update endpoint in buffer
mem_opcode <= UPDATE_ENDPOINT;
mem_op_start <= '1';
@ -2467,7 +2546,8 @@ begin
-- UDPv4 Port and ExpectsInlineQoSFlag
when 6 =>
-- Default
data_out <= (others => '0');
data_out <= (others => '0');
last_word_out <= '1';
-- If Endpoint did not set Port, use Participant Default
if (def_port /= (def_port'reverse_range => '0')) then
@ -2518,8 +2598,8 @@ begin
data_out <= guid(2);
-- Entity ID
when 4 =>
data_out <= guid(3);
data_out <= guid(3);
last_word_out <= '1';
-- If we are in the middle of an Orphan Purge Process, return to the search stage
if (is_orphan_search = '1') then
stage_next <= FIND_ORPHAN_ENDPOINT;
@ -3089,7 +3169,7 @@ begin
max_participant_addr_next <= max_participant_addr;
max_endpoint_addr_next <= max_endpoint_addr;
reset_max_pointer_next <= reset_max_pointer;
mem_guidprefix_next <= mem_guidprefix;
mem_guid_next <= mem_guid;
-- DEFAULT Unregistered
mem_write_data <= (others => '0');
mem_op_done <= '0';
@ -3196,7 +3276,7 @@ begin
case (mem_cnt) is
when 0 =>
-- Preload
-- Reached MAX Addr, No Match Found
-- Reached End of Participant Memory Area, No Match Found
if (mem_addr_base = max_participant_addr) then
addr_res_next <= MAX_ADDRESS; --No match
-- DONE
@ -3247,8 +3327,8 @@ begin
case (mem_cnt) is
-- Preload
when 0 =>
-- Reached MAX Addr, No Match Found
if (mem_addr_base = max_endpoint_addr) then
-- Reache End of Endpoint Memory Area, No Match Found
if (mem_addr_base < max_endpoint_addr) then
addr_res_next <= MAX_ADDRESS; -- No match
-- DONE
mem_stage_next <= IDLE;
@ -3257,12 +3337,15 @@ begin
-- Entity ID
when 1 =>
-- No Match
-- Ignore Entity ID if Orphan Search
if (is_orphan_search = '0' and mem_read_data /= guid(3)) then
-- Ignore Entity ID Match if Orphan Search (But make sure to ignore empty Slots)
if ((is_orphan_search = '0' and mem_read_data /= guid(3)) or mem_read_data = ENTITYID_UNKNOWN) then
-- Continue Search
mem_addr_next <= tmp;
mem_addr_base_next <= tmp;
mem_cnt_next <= 0;
-- Latch Entity ID if Orphan Search
elsif (is_orphan_search = '1') then
mem_guid_next(3) <= mem_read_data;
end if;
-- GUID Prefix 1/3
when 2 =>
@ -3676,15 +3759,15 @@ begin
-- GUID Prefix 1/3
when 1 =>
mem_rd <= '1';
mem_guidprefix_next(0) <= mem_read_data;
mem_guid_next(0) <= mem_read_data;
-- GUID Prefix 2/3
when 2 =>
mem_rd <= '1';
mem_guidprefix_next(1) <= mem_read_data;
mem_guid_next(1) <= mem_read_data;
-- GUID Prefix 3/3
when 3 =>
mem_rd <= '1';
mem_guidprefix_next(2) <= mem_read_data;
mem_guid_next(2) <= mem_read_data;
mem_addr_next <= addr_res;
-- GUID Prefix 1/3
when 4 =>
@ -3744,6 +3827,7 @@ begin
-- MEMORY COLLISION
-- XXX: Posible worst case path (addition and comparison on same clock)
elsif (tmp > max_endpoint_addr) then
report "Memory Full, Ignoring Participant Data" severity NOTE;
-- Ignore Insertion
mem_stage_next <= IDLE;
else
@ -3821,8 +3905,8 @@ begin
-- Preload
when 0 =>
-- Exceeded MAX Addr
if (mem_addr_base > max_endpoint_addr) then
-- We are in the middle of resetting the MAX Participant Pointer
if (mem_addr_base < max_endpoint_addr) then
-- If we are in the middle of resetting the MAX Participant Pointer
if (reset_max_pointer = '1') then
-- Reset MAX Endpoint Pointer to last occupied slot
if (last_addr /= MAX_ADDRESS) then
@ -3832,6 +3916,7 @@ begin
mem_stage_next <= IDLE;
-- MEMORY COLLISION
elsif (mem_addr_base < max_participant_addr) then
report "Memory Full, Ignoring Endpoint Data" severity NOTE;
-- Ignore Insertion
mem_stage_next <= IDLE;
else
@ -3953,7 +4038,7 @@ begin
when 1 =>
-- Slot Occupied
if (mem_read_data /= GUIDPREFIX_UNKNOWN(0)) then
-- Jumpt to Stale Check
-- Jump to Stale Check
mem_addr_next <= tmp2;
mem_cnt_next <= 4;
end if;
@ -3961,7 +4046,7 @@ begin
when 2 =>
-- Slot Occupied
if (mem_read_data /= GUIDPREFIX_UNKNOWN(1)) then
-- Jumpt to Stale Check
-- Jump to Stale Check
mem_addr_next <= tmp2;
mem_cnt_next <= 4;
end if;
@ -3969,7 +4054,7 @@ begin
when 3 =>
-- Slot Occupied
if (mem_read_data /= GUIDPREFIX_UNKNOWN(2)) then
-- Jumpt to Stale Check
-- Jump to Stale Check
mem_addr_next <= tmp2;
mem_cnt_next <= 4;
-- Slot Empty
@ -4115,10 +4200,11 @@ begin
addr_res <= (others => '0');
last_addr <= (others => '0');
long_latch <= (others => '0');
rcvd <= (others => '0');
max_participant_addr <= FIRST_PARTICIPANT_ADDRESS;
max_endpoint_addr <= FIRST_ENDPOINT_ADDRESS;
guid <= (others => (others => '0'));
mem_guidprefix <= (others => (others => '0'));
mem_guid <= (others => (others => '0'));
endpoint_mask_array <= (others => (others => '0'));
lease_duration <= (others => (others => '0'));
deadline <= (others => (others => '0'));
@ -4150,7 +4236,6 @@ begin
is_heartbeat_res <= '0';
reset_max_pointer <= '0';
last_word_in_latch <= '0';
domain_tag_rcv <= '0';
else
stage <= stage_next;
return_stage <= return_stage_next;
@ -4181,10 +4266,11 @@ begin
addr_res <= addr_res_next;
last_addr <= last_addr_next;
long_latch <= long_latch_next;
rcvd <= rcvd_next;
max_participant_addr <= max_participant_addr_next;
max_endpoint_addr <= max_endpoint_addr_next;
guid <= guid_next;
mem_guidprefix <= mem_guidprefix_next;
mem_guid <= mem_guid_next;
endpoint_mask_array <= endpoint_mask_array_next;
lease_duration <= lease_duration_next;
deadline <= deadline_next;
@ -4216,7 +4302,6 @@ begin
is_heartbeat_res <= is_heartbeat_res_next;
reset_max_pointer <= reset_max_pointer_next;
last_word_in_latch <= last_word_in_latch_next;
domain_tag_rcv <= domain_tag_rcv_next;
end if;
end if;
end process;

View File

@ -76,6 +76,18 @@ package rtps_config_package is
-- TODO: Use everywhere
constant EMPTY_STRING : STRING_WORD_ARRAY_TYPE := (others => (others => '0'));
type DEFAULT_QOS_MATCH_TYPE is record
DURABILITY_QOS : std_logic_vector(0 to NUM_ENDPOINTS-1);
PRESENTATION_QOS : std_logic_vector(0 to NUM_ENDPOINTS-1);
DEADLINE_QOS : std_logic_vector(0 to NUM_ENDPOINTS-1);
LATENCY_BUDGET_QOS : std_logic_vector(0 to NUM_ENDPOINTS-1);
OWNERSHIP_QOS : std_logic_vector(0 to NUM_ENDPOINTS-1);
LIVELINESS_QOS : std_logic_vector(0 to NUM_ENDPOINTS-1);
RELIABILITY_QOS : std_logic_vector(0 to NUM_ENDPOINTS-1);
DESTINATION_ORDER_QOS : std_logic_vector(0 to NUM_ENDPOINTS-1);
end record;
constant READER_DEFAULT_QOS_MATCH : DEFAULT_QOS_MATCH_TYPE; -- Deferred to Package Body
constant WRITER_DEFAULT_QOS_MATCH : DEFAULT_QOS_MATCH_TYPE; -- Deferred to Package Body
-- Swap "data" to Big Endian representation.
function endian_swap(swap : std_logic; data : std_logic_vector) return std_logic_vector;
@ -87,6 +99,8 @@ package rtps_config_package is
function convert_string (str : USER_STRING_TYPE) return STRING_WORD_ARRAY_TYPE;
function round_slv(slv : std_logic_vector; width : natural) return std_logic_vector;
function check_qos_compatibility(src_is_reader : std_logic; direction : std_logic; remote : unsigned(WORD_WIDTH-1 downto 0); local : unsigned(WORD_WIDTH-1 downto 0)) return boolean;
end package;
package body rtps_config_package is
@ -748,6 +762,102 @@ package body rtps_config_package is
constant PARTICIPANT_DATA : OUTPUT_DATA_TYPE := gen_participant_data;
-- Direction 1 : Offered >= Requested
-- Direction 0 : Offered <= Requested
-- src_is_reader 1 : Remote is Subscriber-Requested
-- src_is_reader 0 : Remote is Publisher-Offered
function check_qos_compatibility(src_is_reader : std_logic; direction : std_logic; remote : unsigned(WORD_WIDTH-1 downto 0); local : unsigned(WORD_WIDTH-1 downto 0)) return boolean is
variable ret : boolean;
begin
-- Default Match
ret := TRUE;
if ((src_is_reader xor direction) = '1') then
if (remote < local) then
ret := FALSE;
end if;
else
if (remote > local) then
ret := FALSE;
end if;
end if;
return ret;
end function;
function gen_default_qos_match(is_reader : boolean) return DEFAULT_QOS_MATCH_TYPE is
variable ret : DEFAULT_QOS_MATCH_TYPE;
begin
-- Default Match
ret := (others => (others => '1'));
for i in 0 to NUM_ENDPOINTS-1 loop
-- DURABILITY
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '1', unsigned(DEFAULT_DURABILITY_QOS), unsigned(ENDPOINT_DURABILITY_QOS(i)))) then
ret.DURABILITY_QOS(i) := '0';
end if;
-- PRESENTATION
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '1', unsigned(DEFAULT_PRESENTATION_QOS), unsigned(ENDPOINT_PRESENTATION_QOS(i)))) then
ret.PRESENTATION_QOS(i) := '0';
end if;
if (is_reader) then
if (DEFAULT_COHERENT_ACCESS and not ENDPOINT_COHERENT_ACCESS(i)) then
ret.PRESENTATION_QOS(i) := '0';
end if;
if (DEFAULT_ORDERED_ACCESS and not ENDPOINT_ORDERED_ACCESS(i)) then
ret.PRESENTATION_QOS(i) := '0';
end if;
else
if (not DEFAULT_COHERENT_ACCESS and ENDPOINT_COHERENT_ACCESS(i)) then
ret.PRESENTATION_QOS(i) := '0';
end if;
if (not DEFAULT_ORDERED_ACCESS and ENDPOINT_ORDERED_ACCESS(i)) then
ret.PRESENTATION_QOS(i) := '0';
end if;
end if;
-- DEADLINE
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '0', DEFAULT_DEADLINE_QOS(0), ENDPOINT_DEADLINE_QOS(i)(0))) then
ret.DEADLINE_QOS(i) := '0';
end if;
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '0', DEFAULT_DEADLINE_QOS(1), ENDPOINT_DEADLINE_QOS(i)(1))) then
ret.DEADLINE_QOS(i) := '0';
end if;
-- LATENCY_BUDGET
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '0', DEFAULT_LATENCY_BUDGET_QOS(0), ENDPOINT_LATENCY_BUDGET_QOS(i)(0))) then
ret.LATENCY_BUDGET_QOS(i) := '0';
end if;
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '0', DEFAULT_LATENCY_BUDGET_QOS(1), ENDPOINT_LATENCY_BUDGET_QOS(i)(1))) then
ret.LATENCY_BUDGET_QOS(i) := '0';
end if;
-- OWNERSHIP
if (DEFAULT_OWNERSHIP_QOS /= ENDPOINT_OWNERSHIP_QOS(i)) then
ret.OWNERSHIP_QOS(i) := '0';
end if;
-- LIVELINESS
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '1', unsigned(DEFAULT_LIVELINESS_QOS), unsigned(ENDPOINT_LIVELINESS_QOS(i)))) then
ret.LIVELINESS_QOS(i) := '0';
end if;
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '0', DEFAULT_LEASE_DURATION(0), ENDPOINT_LEASE_DURATION(i)(0))) then
ret.LIVELINESS_QOS(i) := '0';
end if;
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '0', DEFAULT_LEASE_DURATION(1), ENDPOINT_LEASE_DURATION(i)(1))) then
ret.LIVELINESS_QOS(i) := '0';
end if;
-- RELIABILITY
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '1', unsigned(DEFAULT_RELIABILTY_QOS), unsigned(ENDPOINT_RELIABILITY_QOS(i)))) then
ret.RELIABILITY_QOS(i) := '0';
end if;
-- DESTINATION_ORDER
if (not check_qos_compatibility(boolean_to_std_logic(is_reader), '1', unsigned(DEFAULT_DESTINATION_ORDER_QOS), unsigned(ENDPOINT_DESTINATION_ORDER_QOS(i)))) then
ret.DESTINATION_ORDER_QOS(i) := '0';
end if;
end loop;
return ret;
end function;
constant READER_DEFAULT_QOS_MATCH : DEFAULT_QOS_MATCH_TYPE := gen_default_qos_match(TRUE);
constant WRITER_DEFAULT_QOS_MATCH : DEFAULT_QOS_MATCH_TYPE := gen_default_qos_match(FALSE);
-- Returns the 'data' argument either as is, or with reversed Byte order, depending on the
-- 'swap' argument.
function endian_swap(swap : std_logic; data : std_logic_vector) return std_logic_vector is

View File

@ -239,7 +239,7 @@ package rtps_package is
-- DEADLINE
constant DEFAULT_DEADLINE_QOS : DURATION_TYPE := DURATION_INFINITE;
-- LATENCY BUDGET
constant DEFAULT_LATENCY_BUDGET_QOS : DURATION_TYPE := (others => (others => '0'));
constant DEFAULT_LATENCY_BUDGET_QOS : DURATION_TYPE := DURATION_ZERO;
-- OWNERSHIP
constant SHARED_OWNERSHIP_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(0,CDR_ENUMERATION_WIDTH));
constant EXCLUSIVE_OWNERSHIP_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_WIDTH));
@ -254,7 +254,7 @@ package rtps_package is
-- LEASE DURATION (LIVELINESS)
constant DEFAULT_LEASE_DURATION : DURATION_TYPE := DURATION_INFINITE;
-- TIME_BASED_FILTER
constant DEFAULT_TIME_BASED_FILTER_QOS : DURATION_TYPE := (others => (others => '0'));
constant DEFAULT_TIME_BASED_FILTER_QOS : DURATION_TYPE := DURATION_ZERO;
-- RELIABILITY
constant BEST_EFFORT_RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_WIDTH));
constant RELIABLE_RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(2,CDR_ENUMERATION_WIDTH));
@ -288,7 +288,7 @@ package rtps_package is
constant DISALLOW_TYPE_COERCION : std_logic_vector(CDR_ENUMERATION_SHORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(0,CDR_ENUMERATION_SHORT_WIDTH));
constant ALLOW_TYPE_COERCION : std_logic_vector(CDR_ENUMERATION_SHORT_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_ENUMERATION_SHORT_WIDTH));
-- DURABILITY SERVICE (DURABILITY)
constant DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY : DURATION_TYPE := (others => (others => '0'));
constant DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY : DURATION_TYPE := DURATION_ZERO;
constant DEFAULT_DURABILITY_SERVICE_HISTORY : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := KEEP_LAST_HISTORY_QOS;
constant DEFAULT_DURABILITY_SERVICE_HISTORY_DEPTH : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_LONG_WIDTH));
constant DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED
@ -372,15 +372,15 @@ package body rtps_package is
constant half_sec : natural := sec/2;
begin
assert (ns < 10**9) report "ns argument has to be less than a second" severity failure;
ret(0) := to_unsigned(s, 32);
ret(0) := to_unsigned(s, WORD_WIDTH);
-- If Fraction Bit is >= 500 ms it cannot be represented as a natural (because naturals/integers are signed).
-- So we handle that manualy
if (ns >= half_sec) then
ret(1)(31) := '1';
ret(1) := to_unsigned(natural(CEIL(real(ns/2)*unit)),32);
ret(1) := to_unsigned(natural(CEIL(real(ns/2)*unit)),WORD_WIDTH);
else
ret(1) := to_unsigned(natural(CEIL(real(ns)*unit)),32);
ret(1) := to_unsigned(natural(CEIL(real(ns)*unit)),WORD_WIDTH);
end if;
return ret;

View File

@ -211,16 +211,22 @@ package rtps_test_package is
unicastLocatorList : LOCATOR_LIST_TYPE;
multicastLocatorList : LOCATOR_LIST_TYPE;
max_size_serialized : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
match : MATCH_TYPE;
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;
procedure gen_endpoint_data( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE);
procedure gen_match_frame( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE);
function gen_endpoint_array(readers : boolean) return ENDPOINT_DATA_ARRAY_TYPE;
procedure gen_sentinel(output : inout TEST_PACKET_TYPE);
procedure gen_rand_loc(RV : inout RandomPType; ret : out LOCATOR_TYPE);
procedure gen_rand_entityid(RV : inout RandomPType; reader : boolean; ret : out std_logic_vector(ENTITYID_WIDTH-1 downto 0));
function int(n : integer; width : natural) return std_logic_vector;
function to_string1 (input : std_logic_vector) return string;
end package;
@ -235,6 +241,17 @@ package body rtps_test_package is
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));
@ -416,7 +433,8 @@ package body rtps_test_package is
expectsInlineQoS => (others => '0'),
unicastLocatorList => EMPTY_LOCATOR_LIST,
multicastLocatorList => EMPTY_LOCATOR_LIST,
max_size_serialized => (others => '0')
max_size_serialized => (others => '0'),
match => MATCH
);
-- *PACKAGE INTERNAL HELPER FUNCTIONS*
@ -881,7 +899,6 @@ package body rtps_test_package is
-- DOMAIN TAG
if (ref.domainTag /= DEFAULT_DOMAIN_TAG) then
tmp := string_len(ref.domainTag);
report "Strlen domain_tag = " & to_string(tmp);
output.data(output.length) := PID_DOMAIN_TAG & 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, CDR_LONG_WIDTH));
@ -1124,6 +1141,13 @@ package body rtps_test_package is
procedure gen_endpoint_data( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE) 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
output.data(output.length) := PID_ENDPOINT_GUID & endian_swap(ref.littleEndian, int(16,PARAMETER_LENGTH_WIDTH));
output.length := output.length + 1;
@ -1155,7 +1179,7 @@ package body rtps_test_package is
end loop;
-- TYPE NAME
tmp := string_len(ref.type_name);
output.data(output.length) := PID_TOPIC_NAME & endian_swap(ref.littleEndian, int((round_div(tmp,4)+1)*4,PARAMETER_LENGTH_WIDTH));
output.data(output.length) := PID_TYPE_NAME & 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,CDR_LONG_WIDTH));
output.length := output.length + 1;
@ -1198,7 +1222,7 @@ package body rtps_test_package is
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);
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;
end if;
-- DEADLINE
@ -1214,9 +1238,9 @@ package body rtps_test_package is
if (ref.latency_budget /= DEFAULT_LATENCY_BUDGET_QOS) then
output.data(output.length) := PID_LATENCY_BUDGET & endian_swap(ref.littleEndian, int(8,PARAMETER_LENGTH_WIDTH));
output.length := output.length + 1;
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.deadline(0)));
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.deadline(1)));
output.data(output.length) := endian_swap(ref.littleEndian, std_logic_vector(ref.latency_budget(1)));
output.length := output.length + 1;
end if;
-- OWNERSHIP
@ -1372,6 +1396,59 @@ package body rtps_test_package is
end if;
end procedure;
procedure gen_match_frame( ref : in ENDPOINT_DATA_TYPE; output : inout TEST_PACKET_TYPE) is
variable loc : LOCATOR_TYPE;
begin
-- Fetch relevant Locator
if (is_valid_loc(get_loc(ref.unicastLocatorList))) then
loc := get_loc(ref.unicastLocatorList);
elsif (is_valid_loc(get_loc(ref.multicastLocatorList))) then
loc := get_loc(ref.multicastLocatorList);
elsif (is_valid_loc(get_loc(ref.participant.defaultUnicastLocatorList))) then
loc := get_loc(ref.participant.defaultUnicastLocatorList);
elsif (is_valid_loc(get_loc(ref.participant.defaultMulticastLocatorList))) then
loc := get_loc(ref.participant.defaultMulticastLocatorList);
else
assert(FALSE) report "Endpoint has no valid Locators" severity FAILURE;
loc := EMPTY_LOCATOR;
end if;
-- OPCODE
case (ref.match) is
when MATCH =>
output.data(output.length) := OPCODE_MATCH;
output.length := output.length + 1;
when UNMATCH =>
output.data(output.length) := OPCODE_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);
output.data(output.length)(0) := ref.expectsInlineQoS(0);
output.length := output.length + 1;
end if;
-- Mark Last Word
output.last(output.length-1) := '1';
end procedure;
procedure gen_sentinel(output : inout TEST_PACKET_TYPE) is
begin
output.data(output.length) := PID_SENTINEL & (PARAMETER_LENGTH_WIDTH-1 downto 0 => '0');
@ -1392,9 +1469,77 @@ package body rtps_test_package is
return TRUE;
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).topic_name := ENDPOINT_TOPIC(i);
ret_readers(i).type_name := ENDPOINT_TYPE(i);
ret_readers(i).durability := ENDPOINT_DURABILITY_QOS(i);
ret_readers(i).durability_service_cleanup_delay := ENDPOINT_DURABILITY_SERVICE_CLEANUP_DELAY(i);
ret_readers(i).durability_service_history := ENDPOINT_DURABILITY_SERVICE_HISTORY(i);
ret_readers(i).durability_service_history_depth := ENDPOINT_DURABILITY_SERVICE_HISTORY_DEPTH(i);
ret_readers(i).durability_service_max_samples := ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES(i);
ret_readers(i).durability_service_max_instances := ENDPOINT_DURABILITY_SERVICE_MAX_INSTANCES(i);
ret_readers(i).durability_service_max_samples_per_instances := ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE(i);
ret_readers(i).presentation := ENDPOINT_PRESENTATION_QOS(i);
ret_readers(i).coherent_access(0) := boolean_to_std_logic(ENDPOINT_COHERENT_ACCESS(i));
ret_readers(i).ordered_access(0) := boolean_to_std_logic(ENDPOINT_ORDERED_ACCESS(i));
ret_readers(i).deadline := ENDPOINT_DEADLINE_QOS(i);
ret_readers(i).latency_budget := ENDPOINT_LATENCY_BUDGET_QOS(i);
ret_readers(i).ownership := ENDPOINT_OWNERSHIP_QOS(i);
ret_readers(i).ownership_strength := ENDPOINT_OWNERSHIP_STRENGTH_QOS(i);
ret_readers(i).liveliness := ENDPOINT_LIVELINESS_QOS(i);
ret_readers(i).leaseDuration := ENDPOINT_LEASE_DURATION(i);
ret_readers(i).time_based_filter := ENDPOINT_TIME_BASED_FILTER_QOS(i);
ret_readers(i).reliability := ENDPOINT_RELIABILITY_QOS(i);
ret_readers(i).max_blocking_time := ENDPOINT_MAX_BLOCKING_TIME(i);
ret_readers(i).transportnpriority := ENDPOINT_TRANSPORT_PRIORITY_QOS(i);
ret_readers(i).lifespan := ENDPOINT_LIFESPAN_QOS(i);
ret_readers(i).destination_order := ENDPOINT_DESTINATION_ORDER_QOS(i);
end loop;
return ret_readers;
else
for i in NUM_READERS to NUM_ENDPOINTS-1 loop
ret_writers(i-NUM_READERS).topic_name := ENDPOINT_TOPIC(i);
ret_writers(i-NUM_READERS).type_name := ENDPOINT_TYPE(i);
ret_writers(i-NUM_READERS).durability := ENDPOINT_DURABILITY_QOS(i);
ret_writers(i-NUM_READERS).durability_service_cleanup_delay := ENDPOINT_DURABILITY_SERVICE_CLEANUP_DELAY(i);
ret_writers(i-NUM_READERS).durability_service_history := ENDPOINT_DURABILITY_SERVICE_HISTORY(i);
ret_writers(i-NUM_READERS).durability_service_history_depth := ENDPOINT_DURABILITY_SERVICE_HISTORY_DEPTH(i);
ret_writers(i-NUM_READERS).durability_service_max_samples := ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES(i);
ret_writers(i-NUM_READERS).durability_service_max_instances := ENDPOINT_DURABILITY_SERVICE_MAX_INSTANCES(i);
ret_writers(i-NUM_READERS).durability_service_max_samples_per_instances := ENDPOINT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE(i);
ret_writers(i-NUM_READERS).presentation := ENDPOINT_PRESENTATION_QOS(i);
ret_writers(i-NUM_READERS).coherent_access(0) := boolean_to_std_logic(ENDPOINT_COHERENT_ACCESS(i));
ret_writers(i-NUM_READERS).ordered_access(0) := boolean_to_std_logic(ENDPOINT_ORDERED_ACCESS(i));
ret_writers(i-NUM_READERS).deadline := ENDPOINT_DEADLINE_QOS(i);
ret_writers(i-NUM_READERS).latency_budget := ENDPOINT_LATENCY_BUDGET_QOS(i);
ret_writers(i-NUM_READERS).ownership := ENDPOINT_OWNERSHIP_QOS(i);
ret_writers(i-NUM_READERS).ownership_strength := ENDPOINT_OWNERSHIP_STRENGTH_QOS(i);
ret_writers(i-NUM_READERS).liveliness := ENDPOINT_LIVELINESS_QOS(i);
ret_writers(i-NUM_READERS).leaseDuration := ENDPOINT_LEASE_DURATION(i);
ret_writers(i-NUM_READERS).time_based_filter := ENDPOINT_TIME_BASED_FILTER_QOS(i);
ret_writers(i-NUM_READERS).reliability := ENDPOINT_RELIABILITY_QOS(i);
ret_writers(i-NUM_READERS).max_blocking_time := ENDPOINT_MAX_BLOCKING_TIME(i);
ret_writers(i-NUM_READERS).transportnpriority := ENDPOINT_TRANSPORT_PRIORITY_QOS(i);
ret_writers(i-NUM_READERS).lifespan := ENDPOINT_LIFESPAN_QOS(i);
ret_writers(i-NUM_READERS).destination_order := ENDPOINT_DESTINATION_ORDER_QOS(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;
end package body;