diff --git a/.gitignore b/.gitignore index 7dd60c9..5ce30df 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ #***MODELSIM*** #Do files !*.do +#Modelsim INI File +!*modelsim.ini #***QUARTUS*** #Project File !*.qpf diff --git a/sim/modelsim.ini b/sim/modelsim.ini new file mode 100644 index 0000000..7660e38 --- /dev/null +++ b/sim/modelsim.ini @@ -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: = [,...] +; Examples: +; note = 3009 +; warning = 3033 +; error = 3010,3016 +; fatal = 3016,3033 +; suppress = 3009,3016,3043 +; The command verror 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 diff --git a/sim/rtps_builtin_endpoint_test2.do b/sim/rtps_builtin_endpoint_test2.do new file mode 100644 index 0000000..8c1a515 --- /dev/null +++ b/sim/rtps_builtin_endpoint_test2.do @@ -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} diff --git a/src/REF.txt b/src/REF.txt index 8fc6276..49af26b 100644 --- a/src/REF.txt +++ b/src/REF.txt @@ -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) diff --git a/src/TODO.txt b/src/TODO.txt index 3c5c65b..5215764 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -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) diff --git a/src/Tests/Level_0/rtps_builtin_endpoint_test1.vhd b/src/Tests/Level_0/rtps_builtin_endpoint_test1.vhd index 3e583e0..3c95297 100644 --- a/src/Tests/Level_0/rtps_builtin_endpoint_test1.vhd +++ b/src/Tests/Level_0/rtps_builtin_endpoint_test1.vhd @@ -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); diff --git a/src/Tests/Level_0/rtps_builtin_endpoint_test2.vhd b/src/Tests/Level_0/rtps_builtin_endpoint_test2.vhd new file mode 100644 index 0000000..d35b7c7 --- /dev/null +++ b/src/Tests/Level_0/rtps_builtin_endpoint_test2.vhd @@ -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; \ No newline at end of file diff --git a/src/Tests/ScoreBoard_builtin_endpoint.vhd b/src/Tests/ScoreBoard_builtin_endpoint.vhd new file mode 100644 index 0000000..c0f0304 --- /dev/null +++ b/src/Tests/ScoreBoard_builtin_endpoint.vhd @@ -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 + ); \ No newline at end of file diff --git a/src/Tests/test_config.vhd b/src/Tests/test_config.vhd index a9b9422..696385a 100644 --- a/src/Tests/test_config.vhd +++ b/src/Tests/test_config.vhd @@ -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; \ No newline at end of file diff --git a/src/Tests/testbench.pro b/src/Tests/testbench.pro index 6b408c4..dced516 100644 --- a/src/Tests/testbench.pro +++ b/src/Tests/testbench.pro @@ -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 \ No newline at end of file +#simulate rtps_builtin_endpoint_test1 +simulate rtps_builtin_endpoint_test2 \ No newline at end of file diff --git a/src/rtps_builtin_endpoint.vhd b/src/rtps_builtin_endpoint.vhd index 0c2dcb8..62beac1 100644 --- a/src/rtps_builtin_endpoint.vhd +++ b/src/rtps_builtin_endpoint.vhd @@ -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; diff --git a/src/rtps_config_package.vhd b/src/rtps_config_package.vhd index 8719f1a..1b2d14f 100644 --- a/src/rtps_config_package.vhd +++ b/src/rtps_config_package.vhd @@ -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 diff --git a/src/rtps_package.vhd b/src/rtps_package.vhd index 8bedaeb..906d4a2 100644 --- a/src/rtps_package.vhd +++ b/src/rtps_package.vhd @@ -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; diff --git a/src/rtps_test_package.vhd b/src/rtps_test_package.vhd index 54fda0f..368813f 100644 --- a/src/rtps_test_package.vhd +++ b/src/rtps_test_package.vhd @@ -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; \ No newline at end of file