Redo Blind Implementation of READER side (RTPS Endpoint & History Cache)

Redefined Sample Memory Format. The design decision was made to handle
most (if not all) of the DDS QOS inside the History Cache, which allows
storing needed information in a more efiicient way.
A (dual port) Instance Memory was added into the HC, to support the QOS
operations.
This commit only implements the A side processes for the READER case.
RESOURCE_LIMITS_QOS, TIME_BASED_FILTER_QOS, and HISTORY_QOS are handled.
The inter-entity communication was changed to allow the HC to mark
parsed changes as rejected, and allow future re-transmission (in the
case of Reliable communication).
This commit is contained in:
Greek 2021-01-16 18:22:36 +01:00
parent d2f466d588
commit 7e84a15d54
6 changed files with 1591 additions and 508 deletions

View File

@ -340,41 +340,33 @@ READER
31............24..............16..............8...............0 31............24..............16..............8...............0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------------------------------------------------------+ +-------------------------------------------------------------+
00| STATUS_INFO | 00| STATUS_INFO | {A/B}
+-------------------------------------------------------------+ +-------------------------------------------------------------+
01| | 01| |
+ + + +
02| | 02| |
+ KEY_HASH + + KEY_HASH + {A}
03| | 03| |
+ + + +
04| | 04| |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
05| ENTITYID | 05| |
+-------------------------------------------------------------+ + TIMESTAMP + {A}
06| | 06| |
+ + +-------------------------------------------------------------+
07| GUIDPREFIX | 07| |
+ + + LIFESPAN_DEADLINE + {A}
08| | 08| |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
09| | 09| PAYLOAD_ADDRESS | {A}
+ SEQUENCE_NUMBER +
10| |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
11| | 10| DISPOSED_GENERATION_COUNT | {A} [only GENERATION_COUNTERS]
+ TIMESTAMP +
12| |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
13| | 11| NO_WRITERS_GENERATION_COUNT | {A} [only GENERATION_COUNTERS]
+ LIFESPAN_DEADLINE +
14| |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
15| PAYLOAD_ADDRESS | 12| PREV_ADDRESS | {A}
+-------------------------------------------------------------+ +-------------------------------------------------------------+
16| PREV_ADDRESS | 13| NEXT_ADDRESS | {A/B}
+-------------------------------------------------------------+
17| NEXT_ADDRESS |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
@ -383,12 +375,12 @@ STATUS INFO
31............24..............16..............8...............0 31............24..............16..............8...............0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-------------------------------------------------+-+-+-+ +-+-+-+-------------------------------------------------+-+-+-+
|R|K|P| UNUSED |F|U|D| |R|P|K| UNUSED |F|U|D|
+-+-+-+-------------------------------------------------+-+-+-+ +-+-+-+-------------------------------------------------+-+-+-+
R...Sample has been Read R...Sample has been Read
K...Key Hash available
P...Sample has associated Payload P...Sample has associated Payload
K...Key Hash available
F...FilteredFlag F...FilteredFlag
U...UnregisteredFlag U...UnregisteredFlag
@ -398,9 +390,9 @@ PAYLOAD MEMORY
============== ==============
31............24..............16..............8...............0 31............24..............16..............8...............0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-----------------------------------------------------------+-+ +-------------------------------------------------------------+
00| NEXT_ADDRESS |O| 00| NEXT_ADDRESS |
+-----------------------------------------------------------+-+ +-------------------------------------------------------------+
01| | 01| |
~ PAYLOAD ~ ~ PAYLOAD ~
**| | **| |
@ -421,31 +413,67 @@ HISTORY CACHE INPUT
+ + + +
04| | 04| |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
05| ENTITYID | 05| |
+-------------------------------------------------------------+ + TIMESTAMP +
06| | 06| |
+ + +-------------------------------------------------------------+
07| GUIDPREFIX | 07| |
+ + + LIFESPAN_DEADLINE +
08| | 08| |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
09| | 09| ENDPOINT_POSITION |
+ SEQUENCE_NUMBER + +-------------------------------------------------------------+
10| | 10| |
+-------------------------------------------------------------+
11| |
+ TIMESTAMP +
12| |
+-------------------------------------------------------------+
13| |
+ LIFESPAN_DEADLINE +
14| |
+-------------------------------------------------------------+
15| |
~ PAYLOAD ~ ~ PAYLOAD ~
**| | **| |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
INSTANCE MEMORY
===============
31............24..............16..............8...............0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------------------------------------------------------+
00| NEXT_ADDRESS | {A/B}
+-------------------------------------------------------------+
01| |
+ +
02| |
+ KEY_HASH + {A}
03| |
+ +
04| |
+-------------------------------------------------------------+
05| STATUS_INFO | {A/B}
+-------------------------------------------------------------+
06| SAMPLE_COUNT | {A/B} [only MAX_SAMPLES_PER_INSTANCE/HISTORY]
+-------------------------------------------------------------+
07| DISPOSED_GENERATION_COUNT | {A} [only GENERATION_COUNTERS]
+-------------------------------------------------------------+
08| NO_WRITERS_GENERATION_COUNT | {A} [only GENERATION_COUNTERS]
+-------------------------------------------------------------+
09| |
+ IGNORE_DEADLINE + {A} [only TIME_BASED_FILTER]
10| |
+-------------------------------------------------------------+
11| |
~ WRITER_BITMAP ~ {A}
**| |
+-------------------------------------------------------------+
STATUS INFO
-----------
31............24..............16..............8...............0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-----------------------------------------------------+-+-+-+-+
| UNUSED |V|L|W|D|
+-----------------------------------------------------+-+-+-+-+
D...NOT_ALIVE_DISPOSED
W...NOT_ALIVE_NO_WRITERS
L...LIVELINESS FLAG
V...VIEW STATE
OUTPUT DATA OUTPUT DATA
=========== ===========

View File

@ -95,6 +95,8 @@
'This Submessage is invalid when the following is true: 'This Submessage is invalid when the following is true:
submessageLength in the Submessage header is too small' 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. But if InvalidateFlag is set, Length can be Zero. Since the length is unsigned, there cannot be an invalid length.
- 8.7.3.2 Indicating to a Reader that a Sample has been filtered
Text refs 8.3.7.2.2 for DataFlag, but shoudl also ref 8.7.4 for FilteredFlag
- 9.4.5.1.2 Flags - 9.4.5.1.2 Flags
Clarify from where the endianness begins. Clarify from where the endianness begins.
One might think it would begin after the Submessage Header, but the length is also endian dependent. One might think it would begin after the Submessage Header, but the length is also endian dependent.

File diff suppressed because it is too large Load Diff

View File

@ -51,15 +51,22 @@ package rtps_config_package is
type HISTORY_CACHE_OPCODE_TYPE is (NOP, ADD_CACHE_CHANGE); type HISTORY_CACHE_OPCODE_TYPE is (NOP, ADD_CACHE_CHANGE);
type KEY_GENERATOR_OPCODE_TYPE is (NOP, WRITE_PAYLOAD, READ_KEY, READ_SIZE); type KEY_GENERATOR_OPCODE_TYPE is (NOP, WRITE_PAYLOAD, READ_KEY, READ_SIZE);
type HISTORY_CACHE_RESPOSNE_TYPE is (UNDEFINED, ACK, ACCEPTED, REJECTED);
type INSTANCE_STATE_TYPE is (ALIVE, NOT_ALIVE_DISPOSED, NOT_ALIVE_NO_WRITERS);
-- Status Info Flags -- Sample Status Info Flags
constant DISPOSED_FLAG : natural := 0; constant DISPOSED_FLAG : natural := 0;
constant UNREGISTERED_FLAG : natural := 1; constant UNREGISTERED_FLAG : natural := 1;
constant FILTERED_FLAG : natural := 2; constant FILTERED_FLAG : natural := 2;
constant PAYLOAD_FLAG : natural := 29; constant KEY_HASH_FLAG : natural := 29;
constant KEY_HASH_FLAG : natural := 30; constant PAYLOAD_FLAG : natural := 30;
constant READ_FLAG : natural := 31; constant READ_FLAG : natural := 31;
constant NOT_ALIVE_DISPOSED_FLAG : natural := 0;
constant NOT_ALIVE_NO_WRITERS_FLAG : natural := 1;
constant LIVELINESS_FLAG : natural := 2;
constant VIEW_FLAG : natural := 3;
-- Marks the Reader Endpoint in the Endpoint Array -- Marks the Reader Endpoint in the Endpoint Array
constant ENDPOINT_READERS : std_logic_vector(0 to NUM_ENDPOINTS-1) := (0 to NUM_READERS-1 => '1', others => '0'); constant ENDPOINT_READERS : std_logic_vector(0 to NUM_ENDPOINTS-1) := (0 to NUM_READERS-1 => '1', others => '0');
@ -106,6 +113,12 @@ package rtps_config_package is
type RTPS_OUT_DATA_TYPE is array (0 to NUM_ENDPOINTS) of std_logic_vector(WORD_WIDTH-1 downto 0); type RTPS_OUT_DATA_TYPE is array (0 to NUM_ENDPOINTS) of std_logic_vector(WORD_WIDTH-1 downto 0);
constant ENDPOINT_BITMAP_WIDTH : natural := 1; -- TODO
type ENDPOINT_BITMAP_ARRAY_TYPE is array (0 to round_div(ENDPOINT_BITMAP_WIDTH, WORD_WIDTH)-1) of std_logic_vector(0 to WORD_WIDTH-1);
function to_endpoint_bitmap (input : ENDPOINT_BITMAP_ARRAY_TYPE) return std_logic_vector;
function from_endpoint_bitmap (input : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1)) return ENDPOINT_BITMAP_ARRAY_TYPE;
-- Swap "data" to Big Endian representation. -- Swap "data" to Big Endian representation.
function endian_swap(swap : std_logic; data : std_logic_vector) return std_logic_vector; function endian_swap(swap : std_logic; data : std_logic_vector) return std_logic_vector;
function endian_swap(swap : std_logic; data : unsigned) return unsigned; function endian_swap(swap : std_logic; data : unsigned) return unsigned;
@ -1053,4 +1066,22 @@ package body rtps_config_package is
return ret; return ret;
end function; end function;
function to_endpoint_bitmap (input : ENDPOINT_BITMAP_ARRAY_TYPE) return std_logic_vector is
variable ret : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1) := (others => '0');
begin
for i in 0 to input'length-1 loop
ret(i*WORD_WIDTH to ((i+1)*WORD_WIDTH)-1) := input(i);
end loop;
return ret;
end function;
function from_endpoint_bitmap (input : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1)) return ENDPOINT_BITMAP_ARRAY_TYPE is
variable ret : ENDPOINT_BITMAP_ARRAY_TYPE := (others => (others => '0'));
begin
for i in 0 to ret'length-1 loop
ret(i) := input(i*WORD_WIDTH to ((i+1)*WORD_WIDTH)-1);
end loop;
return ret;
end function;
end package body; end package body;

View File

@ -10,7 +10,9 @@ use work.rtps_config_package.all;
-- TODO: Check for special values of time/duration? -- TODO: Check for special values of time/duration?
-- TODO: Remove last_word flag from metattraffic operations -- TODO: Remove last_word flag from metattraffic operations
-- TODO: Replace all ('range => 0) checks with defined constants, where possible -- TODO: Replace all ('range => 0) checks with defined constants, where possible
-- TODO: Remove highest_seq_nr in stand alone git commit -- TODO: Adding LIFESPAN Duration in the stored Endpoint Metatraffic Data would allow us to not expect in-line QoS (Which could be a significant overhead)
-- TODO: Is mem_addr_base needed? Isn't it a direct mirror of addr_mem_base? mem_addr_base is only used in the same clock cycle as mem_op_done is pulled high.
entity rtps_endpoint is entity rtps_endpoint is
generic ( generic (
@ -38,11 +40,13 @@ entity rtps_endpoint is
hc_start : out std_logic; hc_start : out std_logic;
hc_opcode : out HISTORY_CACHE_OPCODE_TYPE; hc_opcode : out HISTORY_CACHE_OPCODE_TYPE;
hc_ack : in std_logic; hc_res : in HISTORY_CACHE_RESPOSNE_TYPE;
hc_data_out : in std_logic_vector(WORD_WIDTH-1 downto 0); hc_data_out : in std_logic_vector(WORD_WIDTH-1 downto 0);
hc_valid_out : in std_logic; hc_valid_out : in std_logic;
hc_ready_out : out std_logic; hc_ready_out : out std_logic;
hc_last_word_out: in std_logic; hc_last_word_out: in std_logic;
hc_data_in : out std_logic_vector(WORD_WIDTH-1 downto 0); hc_data_in : out std_logic_vector(WORD_WIDTH-1 downto 0);
hc_valid_in : out std_logic; hc_valid_in : out std_logic;
hc_ready_in : in std_logic; hc_ready_in : in std_logic;
@ -54,27 +58,26 @@ architecture arch of rtps_endpoint is
--*****CONSTANT DECLARATION***** --*****CONSTANT DECLARATION*****
-- Endpoint Memory Size in 4-Byte Words -- Endpoint Memory Size in 4-Byte Words
constant ENDPOINT_MEMORY_SIZE : natural := TODO; constant ENDPOINT_MEMORY_SIZE : natural := TODO;
-- Endpoint Memory Address Width -- Endpoint Memory Address Width
constant ENDPOINT_MEMORY_WIDTH : natural := log2c(ENDPOINT_MEMORY_SIZE); constant ENDPOINT_MEMORY_ADDR_WIDTH : natural := log2c(ENDPOINT_MEMORY_SIZE);
-- Highest Memory Address -- Highest Memory Address
constant MAX_ADDRESS : unsigned(ENDPOINT_MEMORY_WIDTH-1 downto 0) := to_unsigned(ENDPOINT_MEMORY_SIZE-1, ENDPOINT_MEMORY_WIDTH); constant MAX_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(ENDPOINT_MEMORY_SIZE-1, ENDPOINT_MEMORY_ADDR_WIDTH);
-- Highest Endpoint Frame Address -- Highest Endpoint Frame Address
constant MAX_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_WIDTH-1 downto 0) := MAX_ADDRESS - ENDPOINT_FRAME_SIZE + 1; constant MAX_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := MAX_ADDRESS - ENDPOINT_FRAME_SIZE + 1;
-- Address pointing to the beginning of the first Endpoint Data Frame -- Address pointing to the beginning of the first Endpoint Data Frame
constant FIRST_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_WIDTH-1 downto 0) := (others => '0'); constant FIRST_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- *UPDATE PARTICIPANT FLAG POSITIONS* -- *UPDATE PARTICIPANT FLAG POSITIONS*
constant UPDATE_ENDPOINT_FLAG_WIDTH : natural := 4; constant UPDATE_ENDPOINT_FLAG_WIDTH : natural := 4;
-- Signifies that the main Endpoint Data are updated -- Signifies that the main Endpoint Data are updated
constant ENDPOINT_DATA_FLAG : std_logic_vector(UPDATE_ENDPOINT_FLAG_WIDTH-1 downto 0) := (0 => 1, others => '0'); constant ENDPOINT_DATA_FLAG : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (0 => 1, others => '0');
-- Signifies that the Lease Deadline of the Endpoint Data is updated -- Signifies that the Lease Deadline of the Endpoint Data is updated
constant LEASE_DEADLINE_FLAG : std_logic_vector(UPDATE_ENDPOINT_FLAG_WIDTH-1 downto 0) := (1 => 1, others => '0'); constant LEASE_DEADLINE_FLAG : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (1 => 1, others => '0');
-- Signifies that the last Sequence Number of the Endpoint Data is updated -- Signifies that the last Sequence Number of the Endpoint Data is updated
constant NEXT_SEQ_NR_FLAG : std_logic_vector(UPDATE_ENDPOINT_FLAG_WIDTH-1 downto 0) := (2 => 1, others => '0'); constant NEXT_SEQ_NR_FLAG : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (2 => 1, others => '0');
-- Signifies that the HEARTBEAT/ACKNACK Timeout Time of the Endpoint Data is updated -- Signifies that the HEARTBEAT/ACKNACK Timeout Time of the Endpoint Data is updated
constant RES_TIME_FLAG : std_logic_vector(UPDATE_ENDPOINT_FLAG_WIDTH-1 downto 0) := (3 => 1, others => '0'); constant RES_TIME_FLAG : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (3 => 1, others => '0');
constant BITMAP_BLOCK_SIZE : natural := 16;
--*****TYPE DECLARATION***** --*****TYPE DECLARATION*****
-- FSM states. Explained below in detail -- FSM states. Explained below in detail
@ -106,8 +109,7 @@ architecture arch of rtps_endpoint is
expects_inline_qos : std_logic; expects_inline_qos : std_logic;
deadline : TIME_TYPE; deadline : TIME_TYPE;
next_seq_nr : SEQUENCENUMBER_TYPE; next_seq_nr : SEQUENCENUMBER_TYPE;
update_flags : std_logic_vector(UPDATE_ENDPOINT_FLAG_WIDTH-1 downto 0); update_flags : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1);
mem_opcode : MEM_OPCODE_TYPE;
end record; end record;
constant ZERO_MEM_CTRL_DATA : MEM_CTRL_DATA_TYPE := ( constant ZERO_MEM_CTRL_DATA : MEM_CTRL_DATA_TYPE := (
guid => (others => (others => '0')), guid => (others => (others => '0')),
@ -117,7 +119,6 @@ architecture arch of rtps_endpoint is
deadline => TIME_INVALID, deadline => TIME_INVALID,
next_seq_nr => SEQUENCENUMBER_UNKNOWN, next_seq_nr => SEQUENCENUMBER_UNKNOWN,
update_flags => (others => '0'), update_flags => (others => '0'),
mem_opcode => IDLE
); );
@ -134,7 +135,7 @@ architecture arch of rtps_endpoint is
signal portn, portn_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); signal portn, portn_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0');
signal expects_inline_qos, expects_inline_qos_next : std_logic := '0'; signal expects_inline_qos, expects_inline_qos_next : std_logic := '0';
signal is_meta, is_meta_next : std_logic := '0'; signal is_meta, is_meta_next : std_logic := '0';
signal update_endpoint_flags : std_logic_vector(UPDATE_ENDPOINT_FLAG_WIDTH-1 downto 0) := (others => '0'); signal update_endpoint_flags : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (others => '0');
signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := (others => '0'); signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := (others => '0');
signal flags, flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0) := (others => '0'); signal flags, flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0) := (others => '0');
signal seq_nr, seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; signal seq_nr, seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
@ -165,16 +166,18 @@ architecture arch of rtps_endpoint is
signal mem_stage, mem_stage_next : MEM_STAGE_TYPE := IDLE; signal mem_stage, mem_stage_next : MEM_STAGE_TYPE := IDLE;
signal mem_wr, mem_rd : std_logic := '0'; signal mem_wr, mem_rd : std_logic := '0';
signal mem_wr_data, mem_rd_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal mem_wr_data, mem_rd_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal mem_addr, mem_addr_next : unsigned(ENDPOINT_MEMORY_WIDTH-1 downto 0) := (others => '0'); signal mem_addr, mem_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal mem_addr_base, mem_addr_base_next : unsigned(ENDPOINT_MEMORY_WIDTH-1 downto 0) := (others => '0'); signal mem_addr_base, mem_addr_base_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal addr_res, addr_res_next : unsigned(ENDPOINT_MEMORY_WIDTH-1 downto 0) := (others => '0'); signal mem_addr_base, mem_addr_base_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal last_addr, last_addr_next : unsigned(ENDPOINT_MEMORY_WIDTH-1 downto 0) := (others => '0'); signal last_addr, last_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal max_endpoint_addr, max_endpoint_addr_next : unsigned(ENDPOINT_MEMORY_WIDTH-1 downto 0) := (others => '0'); signal max_endpoint_addr, max_endpoint_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal mem_cnt, mem_cnt_next : natural range TODO := 0; signal mem_cnt, mem_cnt_next : natural range TODO := 0;
signal mem_endpoint_data, mem_endpoint_data_next : ENDPOINT_DATA_TYPE := ZERO_ENDPOINT_DATA; signal mem_endpoint_data, mem_endpoint_data_next : ENDPOINT_DATA_TYPE := ZERO_ENDPOINT_DATA;
signal reset_max_pointer, reset_max_pointer_next : std_logic := '0'; signal reset_max_pointer, reset_max_pointer_next : std_logic := '0';
signal mem_long_latch, mem_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); signal mem_long_latch, mem_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
signal mem_ctrl_data, mem_ctrl_data_next : MEM_CTRL_DATA_TYPE := ZERO_MEM_CTRL_DATA; signal mem_ctrl_data, mem_ctrl_data_next : MEM_CTRL_DATA_TYPE := ZERO_MEM_CTRL_DATA;
signal mem_pos, mem_pos_next : natural range TODO := 0;
signal is_psearch, is_psearch_next : std_logic := '0';
signal stale_check, stale_check_next : std_logic := '0'; signal stale_check, stale_check_next : std_logic := '0';
signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0) := (others => '0'); signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0) := (others => '0');
@ -227,7 +230,7 @@ begin
--*****COMPONENT INSTANTIATION***** --*****COMPONENT INSTANTIATION*****
ram_inst : single_port_ram ram_inst : single_port_ram
generic map ( generic map (
ADDR_WIDTH => ENDPOINT_MEMORY_WIDTH, ADDR_WIDTH => ENDPOINT_MEMORY_ADDR_WIDTH,
DATA_WIDTH => WORD_WIDTH, DATA_WIDTH => WORD_WIDTH,
MEMORY_DEPTH => ENDPOINT_MEMORY_SIZE MEMORY_DEPTH => ENDPOINT_MEMORY_SIZE
) )
@ -386,7 +389,7 @@ begin
if (is_meta = '1' and (meta_opcode = OPCODE_PARTICIPANT_UNMATCH or meta_opcode = OPCODE_LIVELINESS_UPDATE)) then if (is_meta = '1' and (meta_opcode = OPCODE_PARTICIPANT_UNMATCH or meta_opcode = OPCODE_LIVELINESS_UPDATE)) then
-- DONE Parsing -- DONE Parsing
stage_next <= METATRAFFIC_OPERATION; stage_next <= INITIATE_ENDPOINT_SEARCH;
else else
stage_next <= LATCH_ENTITYID; stage_next <= LATCH_ENTITYID;
end if; end if;
@ -398,19 +401,57 @@ begin
if (is_meta = '1') then if (is_meta = '1') then
meta_rd <= '1'; meta_rd <= '1';
guid_next(3) <= meta_data_in; guid_next(3) <= meta_data_in;
if (mem_opcode = OPCODE_ENDPOINT_MATCH) then
stage_next <= LATCH_ENDPOINT_DATA;
cnt_next <= 0;
else
stage_next <= METATRAFFIC_OPERATION;
end if;
-- Memory Operation Guard -- Memory Operation Guard
else else
rd_guard := '1'; rd_guard := '1';
guid_next(3) <= data_in; guid_next(3) <= data_in;
end if;
stage_next <= INITIATE_ENDPOINT_SEARCH;
end if;
when INITIATE_ENDPOINT_SEARCH =>
-- Memory Operation Guard
if (mem_op_done = '1') then
stage_next <= INITIATE_ENDPOINT_SEARCH; if (is_meta = '1') then
case (meta_opcode) is
when OPCODE_ENDPOINT_MATCH =>
mem_op_start <= '1';
mem_opcode <= SEARCH_ENDPOINT;
stage_next <= LATCH_ENDPOINT_DATA;
when OPCODE_ENDPOINT_UNMATCH =>
mem_op_start <= '1';
mem_opcode <= SEARCH_ENDPOINT;
stage_next <= METATRAFFIC_OPERATION;
when OPCODE_PARTICIPANT_UNMATCH =>
mem_op_start <= '1';
mem_opcode <= FIND_FIRST_PARTICIPANT_ENDPOINT;
stage_next <= METATRAFFIC_OPERATION;
when OPCODE_LIVELINESS_UPDATE =>
mem_op_start <= '1';
mem_opcode <= FIND_FIRST_PARTICIPANT_ENDPOINT;
stage_next <= METATRAFFIC_OPERATION;
when others =>
assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE;
null;
end case;
else
mem_op_start <= '1';
mem_opcode <= SEARCH_ENDPOINT;
case (opcode) is
when SID_DATA =>
stage_next <= LATCH_EXTRA_DATA;
cnt_next <= 0;
when SID_HEARTBEAT =>
stage_next <= LATCH_HEARTBEAT;
cnt_next <= 0;
when SID_GAP =>
stage_next <= LATCH_GAP;
cnt_next <= 0;
when others =>
stage_next <= SKIP_PACKET;
end case;
end if; end if;
end if; end if;
when LATCH_ENDPOINT_DATA => when LATCH_ENDPOINT_DATA =>
@ -441,28 +482,76 @@ begin
case (meta_opcode) is case (meta_opcode) is
when OPCODE_ENDPOINT_MATCH => when OPCODE_ENDPOINT_MATCH =>
-- Insert Matched Remote Endpoint -- Endpoint already in Memory
-- NOTE: The Lease Duration is NOT updated in case of an update. That is the responsibility of the Liveliness Update if (mem_addr_base /= MAX_ADDRESS) then
update_endpoint_flags <= ENDPOINT_DATA_FLAG; -- In case the Endpoint is already in the memory, we update the data -- Update the Endpoint Data
mem_opcode <= INSERT_ENDPOINT; -- NOTE: The Lease Duration is NOT updated in case of an update. That is the responsibility of the Liveliness Update
mem_op_start <= '1'; update_endpoint_flags <= ENDPOINT_DATA_FLAG;
stage_next <= IDLE; mem_opcode <= UDPATE_ENDPOINT;
mem_op_start <= '1';
stage_next <= IDLE;
else
-- Insert Matched Remote Endpoint
mem_opcode <= INSERT_ENDPOINT;
mem_op_start <= '1';
stage_next <= IDLE;
end if;
when OPCODE_ENDPOINT_UNMATCH => when OPCODE_ENDPOINT_UNMATCH =>
-- Remove Unmatched Remote Endpoint -- Endpoint not in Memory
mem_opcode <= REMOVE_ENDPOINT; if (mem_addr_base = MAX_ADDRESS) then
mem_op_start <= '1'; -- Ignore
stage_next <= IDLE; stage_next <= IDLE;
else
-- Output Guard
if (hc_ready_in = '1') then
-- Propagate Removal
hc_start <= '1';
hc_opcode <= REMOVE_WRITER;
hc_valid_in <= '1';
hc_data_in <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH));
-- Wait until HC Acknowledgement
if (hc_res = ACK) then
-- Remove Unmatched Remote Endpoint
mem_opcode <= REMOVE_ENDPOINT;
mem_op_start <= '1';
stage_next <= IDLE;
end if;
end if;
end if;
when OPCODE_PARTICIPANT_UNMATCH => when OPCODE_PARTICIPANT_UNMATCH =>
-- Remove All Endpoint of Remote Participant -- No matches in memory
mem_opcode <= REMOVE_PARTICIPANT; if (mem_addr_base = MAX_ADDRESS) then
mem_op_start <= '1'; -- DONE
stage_next <= IDLE; stage_next <= IDLE;
else
-- Output Guard
if (hc_ready_in = '1') then
-- Propagate Removal
hc_start <= '1';
hc_opcode <= REMOVE_WRITER;
hc_valid_in <= '1';
hc_data_in <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH));
-- Wait until HC Acknowledgement
if (hc_res = ACK) then
-- Remove Unmatched Remote Endpoint
mem_opcode <= REMOVE_ENDPOINT;
mem_op_start <= '1';
stage_next <= INITIATE_NEXT_ENDPOINT_SEARCH;
end if;
end if;
end if;
when OPCODE_LIVELINESS_UPDATE => when OPCODE_LIVELINESS_UPDATE =>
-- Renew Lease of Remote Endpoint -- No matches in memory
update_endpoint_flags <= LEASE_DEADLINE_FLAG; if (mem_addr_base = MAX_ADDRESS) then
mem_opcode <= UDPATE_ENDPOINT; -- DONE
mem_op_start <= '1'; stage_next <= IDLE;
stage_next <= IDLE; else
-- Renew Lease of Remote Endpoint
update_endpoint_flags <= LEASE_DEADLINE_FLAG;
mem_opcode <= UDPATE_ENDPOINT;
mem_op_start <= '1';
stage_next <= INITIATE_NEXT_ENDPOINT_SEARCH;
end if;
when others => when others =>
assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE; assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE;
null; null;
@ -470,6 +559,13 @@ begin
-- DONE -- DONE
stage_next <= SKIP_PACKET; stage_next <= SKIP_PACKET;
end if; end if;
when INITIATE_NEXT_ENDPOINT_SEARCH =>
-- Memory Operation Guard
if (mem_op_done = '1') then
mem_opcode <= FIND_NEXT_PARTICIPANT_ENDPOINT;
mem_op_start <= '1';
stage_next <= METATRAFFIC_OPERATION;
end if;
when LATCH_SRC_ADDR => when LATCH_SRC_ADDR =>
-- Input FIFO Guard -- Input FIFO Guard
if (empty = '0') then if (empty = '0') then
@ -481,26 +577,6 @@ begin
stage_next <= LATCH_GUIDPREFIX; stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0; cnt_next <= 0;
end if; end if;
when INITIATE_ENDPOINT_SEARCH =>
-- Memory Operation Guard
if (mem_op_done = '1') then
mem_op_start <= '1';
mem_opcode <= SEARCH_ENDPOINT;
case (opcode) is
when SID_DATA =>
stage_next <= LATCH_EXTRA_DATA;
cnt_next <= 0;
when SID_HEARTBEAT =>
stage_next <= LATCH_HEARTBEAT;
cnt_next <= 0;
when SID_GAP =>
stage_next <= LATCH_GAP;
cnt_next <= 0;
when others =>
stage_next <= SKIP_PACKET;
end case;
end if;
when LATCH_EXTRA_DATA => when LATCH_EXTRA_DATA =>
-- Input FIFO Guard -- Input FIFO Guard
if (empty = '0') then if (empty = '0') then
@ -515,7 +591,7 @@ begin
when 1 => when 1 =>
seq_nr_next(1) <= unsigned(data_in); seq_nr_next(1) <= unsigned(data_in);
-- Store Next Sequence Number -- Store Next Sequence Number
tmp_dw := (0 => seq_nr(0), 1 => unsigned(data_in_swapped)); tmp_dw := (0 => seq_nr(0), 1 => unsigned(data_in));
next_seq_nr_next <= tmp_dw + 1; next_seq_nr_next <= tmp_dw + 1;
-- Timestamp 1/2 -- Timestamp 1/2
when 2 => when 2 =>
@ -565,7 +641,7 @@ begin
stage_next <= SKIP_PACKET; stage_next <= SKIP_PACKET;
-- Endpoint in Buffer -- Endpoint in Buffer
if (addr_res /= MAX_ADDRESS) then if (mem_addr_base /= MAX_ADDRESS) then
-- No scheduled Heartbeat Response -- No scheduled Heartbeat Response
if (mem_endpoint_data.res_time = 0) then if (mem_endpoint_data.res_time = 0) then
-- If current Sequence Number obsolete (removed from source history cache) -- If current Sequence Number obsolete (removed from source history cache)
@ -651,7 +727,7 @@ begin
stage_next <= SKIP_PACKET; stage_next <= SKIP_PACKET;
-- Known Remote Endpoint -- Known Remote Endpoint
if (addr_res /= MAX_ADDRESS) then if (mem_addr_base /= MAX_ADDRESS) then
-- GAP is relevant -- GAP is relevant
if (gap_start <= mem_endpoint_data.next_seq_nr and mem_endpoint_data.next_seq_nr <= gap_list_end) then if (gap_start <= mem_endpoint_data.next_seq_nr and mem_endpoint_data.next_seq_nr <= gap_list_end) then
-- Next Expected is in GAP List -- Next Expected is in GAP List
@ -794,10 +870,15 @@ begin
case (cnt) is case (cnt) is
-- Lifespan 1/2 -- Lifespan 1/2
when 0 => when 0 =>
deadline_next(0) <= unsigned(data_in_swapped); -- NOTE: We are misusing the sn_latch_1 as temporal CDR_LONG storage
sn_latch_1_next(0) <= unsigned(data_in_swapped);
-- Lifespan 2/2 -- Lifespan 2/2
when 1 => when 1 =>
deadline_next(1) <= unsigned(data_in_swapped); tmp_dw := (0 => sn_latch_1(0), 1 => unsigned(data_in_swapped));
-- TODO: Use source timestamp if clocks with remote synchronized
-- Calculate Sample Lifespan Deadline
deadline_next <= time + tmp_dw;
-- DONE -- DONE
stage_next <= SKIP_PARAMETER; stage_next <= SKIP_PARAMETER;
@ -845,7 +926,7 @@ begin
hc_start <= '1'; hc_start <= '1';
hc_opcode <= ADD_CACHE_CHANGE; hc_opcode <= ADD_CACHE_CHANGE;
-- Wait until History Cache acknowledges request -- Wait until History Cache acknowledges request
if (hc_ack = '1') then if (hc_res = ACK) then
stage_next <= ADD_CACHE_CHANGE; stage_next <= ADD_CACHE_CHANGE;
cnt_next <= 0; cnt_next <= 0;
end if; end if;
@ -872,51 +953,38 @@ begin
-- Key hash 4/4 -- Key hash 4/4
when 4 => when 4 =>
hc_data_in <= key_hash(3); hc_data_in <= key_hash(3);
-- Entity ID
when 5 =>
hc_data_in <= guid(3);
-- GUID Prefix 1/3
when 6 =>
hc_data_in <= guid(0);
-- GUID Prefix 2/3
when 7 =>
hc_data_in <= guid(1);
-- GUID Prefix 3/3
when 8 =>
hc_data_in <= guid(2);
-- Sequence Number 1/2
when 9 =>
hc_data_in <= seq_nr(0);
-- Sequence Number 2/2
when 10 =>
hc_data_in <= seq_nr(1);
-- Timestamp 1/2 -- Timestamp 1/2
when 11 => when 5 =>
hc_data_in <= ts(0); hc_data_in <= ts(0);
-- Timestamp 2/2 -- Timestamp 2/2
when 12 => when 6 =>
hc_data_in <= ts(1); hc_data_in <= ts(1);
-- Lifespan Deadline 1/2 -- Lifespan Deadline 1/2
when 13 => when 7 =>
hc_data_in <= deadline(0); hc_data_in <= deadline(0);
-- Lifespan Deadline 2/2 -- Lifespan Deadline 2/2
when 14 => when 8 =>
hc_data_in <= deadline(1); hc_data_in <= deadline(1);
-- Endpoint Memory Position
when 9 =>
-- Wait for Endpoint Search
if (mem_op_done = '1') then
-- Payload exists -- TODO: Assert mem_pos range fits in CDR_LONG
if (data_flag = '1' or key_flag = '1') then hc_data_in <= std_logic_vector(to_unsigned(mem_pos, CDR_LONG_WIDTH));
stage_next <= PUSH_PAYLOAD;
else
-- DONE
hc_last_word_in <= '1';
-- Operation Sucessfull -- Payload exists
if (hc_ack = '1') then if (data_flag = '1' or key_flag = '1') then
stage_next <= FINALIZE_HISTORY_CACHE_REQUEST; stage_next <= PUSH_PAYLOAD;
else else
-- Operation Failed, Skip -- DONE
stage_next <= SKIP_PACKET; hc_last_word_in <= '1';
stage_next <= FINALIZE_HISTORY_CACHE_REQUEST;
end if; end if;
else
-- Keep State
hc_valid_in <= '0';
cnt_next <= cnt;
end if; end if;
when others => when others =>
null; null;
@ -933,34 +1001,33 @@ begin
-- Exit Condition -- Exit Condition
if (last_word_in = '1') then if (last_word_in = '1') then
hc_last_word_in <= '1'; hc_last_word_in <= '1';
-- XXX: Possible worst case path (The hc_ack is set from last_word signal -> round trip delay between entities) stage_next <= FINALIZE_HISTORY_CACHE_REQUEST;
-- Change Add Sucessfull
if (hc_ack = '1') then
-- Update Endpoint Data
stage_next <= FINALIZE_HISTORY_CACHE_REQUEST;
else
-- Operation Failed, Skip
stage_next <= SKIP_PACKET;
end if;
end if; end if;
end if; end if;
when FINALIZE_HISTORY_CACHE_REQUEST => when FINALIZE_HISTORY_CACHE_REQUEST =>
-- Memory Operation Guard -- NOTE: Memory is already in done state from previous state (ADD_CACHE_CHANGE)
if (mem_op_done = '1') then assert (mem_op_done = '1') report "FINALIZE_HISTORY_CACHE_REQUEST precondition not met. mem_op_done /= '1'" severity FAILURE;
-- Update next sequence number and renew Lease -- Wai for History Cache Response
mem_op_start <= '1'; if (hc_res /= UNDEFINED) then
mem_opcode <= UPDATE_ENDPOINT; -- Operation was Accepted
deadline_next <= time + ENDPOINT_LEASE_DURATION(ID); if (hc_res = ACCEPTED) then
update_endpoint_flags <= NEXT_SEQ_NR_FLAG or LEASE_DEADLINE_FLAG; -- Update next sequence number and renew Lease
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
deadline_next <= time + ENDPOINT_LEASE_DURATION(ID);
update_endpoint_flags <= NEXT_SEQ_NR_FLAG or LEASE_DEADLINE_FLAG;
end if;
-- NOTE: In case the operation was unsucessfull (e.g. reached Resource Limits), the endpoint is not updated and the
-- Sequence Number is thus not "acknowledged".
-- DONE -- DONE
stage_next <= SKIP_PACKET; stage_next <= SKIP_PACKET;
end if; end if;
when ENDPOINT_STALE_CHECK => when ENDPOINT_STALE_CHECK =>
-- Wait for Stale Search to finish -- Wait for Stale Search to finish
if (mem_op_done = '1') then if (mem_op_done = '1') then
-- Found Stale Entry -- Found Stale Entry
if (addr_res /= MAX_ADDRESS) then if (mem_addr_base /= MAX_ADDRESS) then
-- Endpoint Lease Expired -- Endpoint Lease Expired
-- NOTE: The mem_endpoint_data is zero initialized on lease expiration, so we check if the address is set -- NOTE: The mem_endpoint_data is zero initialized on lease expiration, so we check if the address is set
if (mem_endpoint_data.addr = IPv4_ADDRESS_INVALID) then if (mem_endpoint_data.addr = IPv4_ADDRESS_INVALID) then
@ -1169,7 +1236,6 @@ begin
mem_stage_next <= mem_stage; mem_stage_next <= mem_stage;
mem_addr_base_next <= mem_addr_base; mem_addr_base_next <= mem_addr_base;
mem_addr_next <= mem_addr; mem_addr_next <= mem_addr;
addr_res_next <= addr_res;
mem_cnt_next <= mem_cnt; mem_cnt_next <= mem_cnt;
last_addr_next <= last_addr; last_addr_next <= last_addr;
mem_endpoint_data_next <= mem_endpoint_data; mem_endpoint_data_next <= mem_endpoint_data;
@ -1178,6 +1244,7 @@ begin
reset_max_pointer_next <= reset_max_pointer; reset_max_pointer_next <= reset_max_pointer;
mem_long_latch_next <= mem_long_latch; mem_long_latch_next <= mem_long_latch;
mem_ctrl_data_next <= mem_ctrl_data; mem_ctrl_data_next <= mem_ctrl_data;
mem_pos_next <= mem_pos;
-- DEFAULT Unregistered -- DEFAULT Unregistered
mem_write_data <= (others => '0'); mem_write_data <= (others => '0');
mem_op_done <= '0'; mem_op_done <= '0';
@ -1189,6 +1256,7 @@ begin
when IDLE => when IDLE =>
mem_op_done <= '1'; mem_op_done <= '1';
reset_max_pointer_next <= '0'; reset_max_pointer_next <= '0';
is_psearch_next <= '0';
if (mem_op_start = '1') then if (mem_op_start = '1') then
-- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk) -- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk)
@ -1199,70 +1267,89 @@ begin
expects_inline_qos => expects_inline_qos_next, expects_inline_qos => expects_inline_qos_next,
deadline => deadline_next, deadline => deadline_next,
next_seq_nr => next_seq_nr_next, next_seq_nr => next_seq_nr_next,
update_flags => update_endpoint_flags_next, update_flags => update_endpoint_flags_next
mem_opcode => mem_opcode_next
); );
case(mem_opcode) is case(mem_opcode) is
when SEARCH_ENDPOINT => when SEARCH_ENDPOINT =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= FIRST_ENDPOINT_ADDRESS; mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
mem_pos_next <= 0;
mem_stage_next <= SEARCH_ENDPOINT; mem_stage_next <= SEARCH_ENDPOINT;
mem_cnt_next <= 0; mem_cnt_next <= 0;
when INSERT_ENDPOINT => when INSERT_ENDPOINT =>
-- NOTE: First check if Endpoint is already inserted. If yes, just update the data.
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= FIRST_ENDPOINT_ADDRESS; mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
mem_stage_next <= SEARCH_ENDPOINT; mem_pos_next <= 0;
mem_stage_next <= FIND_ENDPOINT_SLOT;
mem_cnt_next <= 0; mem_cnt_next <= 0;
when UPDATE_ENDPOINT => when UPDATE_ENDPOINT =>
if ((update_endpoint_flags and ENDPOINT_DATA_FLAG) = ENDPOINT_DATA_FLAG) then if ((update_endpoint_flags and ENDPOINT_DATA_FLAG) = ENDPOINT_DATA_FLAG) then
mem_stage_next <= UPDATE_ENDPOINT; mem_stage_next <= UPDATE_ENDPOINT;
mem_addr_next <= addr_res + 4; mem_addr_next <= mem_addr_base + 4;
mem_cnt_next <= 0; mem_cnt_next <= 0;
elsif ((update_endpoint_flags and LEASE_DEADLINE_FLAG) = LEASE_DEADLINE_FLAG) then elsif ((update_endpoint_flags and LEASE_DEADLINE_FLAG) = LEASE_DEADLINE_FLAG) then
mem_stage_next <= UPDATE_ENDPPOINT; mem_stage_next <= UPDATE_ENDPPOINT;
mem_addr_next <= addr_res + 6; mem_addr_next <= mem_addr_base + 6;
mem_cnt_next <= 2; mem_cnt_next <= 2;
elsif ((update_endpoint_flags and RES_TIME_FLAG) = RES_TIME_FLAG) then elsif ((update_endpoint_flags and RES_TIME_FLAG) = RES_TIME_FLAG) then
mem_stage_next <= UPDATE_ENDPOINT; mem_stage_next <= UPDATE_ENDPOINT;
mem_addr_next <= addr_res + 8; mem_addr_next <= mem_addr_base + 8;
mem_cnt_next <= 4; mem_cnt_next <= 4;
elsif ((update_endpoint_flags and NEXT_SEQ_NR_FLAG) = NEXT_SEQ_NR_FLAG) then elsif ((update_endpoint_flags and NEXT_SEQ_NR_FLAG) = NEXT_SEQ_NR_FLAG) then
mem_stage_next <= UPDATE_ENDPOINT; mem_stage_next <= UPDATE_ENDPOINT;
mem_addr_next <= addr_res + 10; mem_addr_next <= mem_addr_base + 10;
mem_cnt_next <= 6; mem_cnt_next <= 6;
end if; end if;
when REMOVE_ENDPOINT => when REMOVE_ENDPOINT =>
mem_addr_next <= addr_res; mem_addr_next <= mem_addr_base;
mem_stage_next <= REMOVE_ENDPOINT; mem_stage_next <= REMOVE_ENDPOINT;
mem_cnt_next <= 0; mem_cnt_next <= 0;
when REMOVE_PARTICIPANT =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
mem_stage_next <= SEARCH_ENDPOINT;
mem_cnt_next <= 0;
when FIND_STALE_ENDPOINT => when FIND_STALE_ENDPOINT =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= FIRST_ENDPOINT_ADDRESS; mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
mem_pos_next <= 0;
mem_stage_next <= FIND_STALE_ENDPOINT; mem_stage_next <= FIND_STALE_ENDPOINT;
mem_cnt_next <= 0; mem_cnt_next <= 0;
when FIND_FIRST_ENDPOINT => when GET_FIRST_ENDPOINT =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= FIRST_ENDPOINT_ADDRESS; mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
mem_stage_next <= FIND_NEXT_ENDPOINT; mem_pos_next <= 0;
mem_stage_next <= GET_NEXT_ENDPOINT;
mem_cnt_next <= 0; mem_cnt_next <= 0;
when FIND_NEXT_ENDPOINT => when GET_NEXT_ENDPOINT =>
-- Memory Bound Guard -- Memory Bound Guard
if (addr_res /= max_endpoint_addr) then if (mem_addr_base /= max_endpoint_addr) then
-- Reached End of Memory, No match -- Reached End of Memory, No match
tmp := addr_res + ENDPOINT_FRAME_SIZE; tmp := mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_addr_base_next <= tmp; mem_addr_base_next <= tmp;
mem_addr_next <= tmp; mem_addr_next <= tmp;
mem_stage_next <= FIND_NEXT_ENDPOINT; mem_pos_next <= mem_pos + 1;
mem_stage_next <= GET_NEXT_ENDPOINT;
mem_cnt_next <= 0; mem_cnt_next <= 0;
else else
addr_res_next <= MAX_ADDRESS; mem_addr_base_next <= MAX_ADDRESS;
end if;
when FIND_FIRST_PARTICIPANT_ENDPOINT =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
mem_pos_next <= 0;
mem_stage_next <= SEARCH_ENDPOINT;
mem_cnt_next <= 0;
is_psearch_next <= '1';
when FIND_NEXT_PARTICIPANT_ENDPOINT =>
-- Memory Bound Guard
if (mem_addr_base /= max_endpoint_addr) then
-- Reached End of Memory, No match
tmp := mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_addr_base_next <= tmp;
mem_addr_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_stage_next <= SEARCH_ENDPOINT;
mem_cnt_next <= 0;
is_psearch_next <= '1';
else
mem_addr_base_next <= MAX_ADDRESS;
end if; end if;
when others => when others =>
null; null;
@ -1282,84 +1369,77 @@ begin
null; null;
-- Entity ID -- Entity ID
when 1 => when 1 =>
-- No Match (Ignore Entity ID match on Participant Search, but skip empty Slot) -- No Match (Ignore Entity ID match on Participant Endpoint Search, but skip empty Slot)
if ((mem_read_data /= guid(3) and mem_ctrl_data.mem_opcode /= REMOVE_PARTICIPANT) or (mem_read_data = ENTITYID_UNKNOWN)) then if ((mem_read_data /= mem_ctrl_data.guid(3) and is_psearch = '0') or (mem_read_data = ENTITYID_UNKNOWN)) then
-- Reached End of Memory, No Match -- Reached End of Memory, No Match
if (mem_addr_base = max_endpoint_addr) then if (mem_addr_base = max_endpoint_addr) then
case (mem_ctrl_data.mem_opcode) is mem_addr_base_next <= MAX_ADDRESS; --No match
when INSERT_ENDPOINT => -- DONE
-- Insert new Endpoint mem_stage_next <= IDLE;
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
mem_stage_next <= FIND_ENDPOINT_SLOT;
mem_cnt_next <= 0;
when REMOVE_PARTICIPANT =>
-- Reset MAX Endpoint Pointer
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
reset_max_pointer_next <= '1';
last_addr_next <= (others => '0');
mem_stage_next <= FIND_ENDPOINT_SLOT;
mem_cnt_next <= 0;
when others =>
addr_res_next <= MAX_ADDRESS; --No match
-- DONE
mem_stage_next <= IDLE;
end case;
else else
-- Continue Search -- Continue Search
mem_addr_next <= tmp; mem_addr_next <= tmp;
mem_addr_base_next <= tmp; mem_addr_base_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0; mem_cnt_next <= 0;
end if; end if;
end if; end if;
-- GUID Prefix 1/3 -- GUID Prefix 1/3
when 2 => when 2 =>
-- No Match -- No Match
if (mem_read_data /= guid(0)) then if (mem_read_data /= mem_ctrl_data.guid(0)) then
-- Continue Search -- Reached End of Memory, No Match
mem_addr_next <= tmp; if (mem_addr_base = max_endpoint_addr) then
mem_addr_base_next <= tmp; mem_addr_base_next <= MAX_ADDRESS; --No match
mem_cnt_next <= 0; -- DONE
mem_stage_next <= IDLE;
else
-- Continue Search
mem_addr_next <= tmp;
mem_addr_base_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
end if; end if;
-- GUID Prefix 2/3 -- GUID Prefix 2/3
when 3 => when 3 =>
-- No Match -- No Match
if (mem_read_data /= guid(1)) then if (mem_read_data /= mem_ctrl_data.guid(1)) then
-- Continue Search -- Reached End of Memory, No Match
mem_addr_next <= tmp; if (mem_addr_base = max_endpoint_addr) then
mem_addr_base_next <= tmp; mem_addr_base_next <= MAX_ADDRESS; --No match
mem_cnt_next <= 0; -- DONE
mem_stage_next <= IDLE;
else
-- Continue Search
mem_addr_next <= tmp;
mem_addr_base_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
end if; end if;
-- GUID Prefix 3/3 -- GUID Prefix 3/3
when 4 => when 4 =>
-- No Match -- No Match
if (mem_read_data /= guid(2)) then if (mem_read_data /= mem_ctrl_data.guid(2)) then
-- Continue Search -- Reached End of Memory, No Match
mem_addr_next <= tmp; if (mem_addr_base = max_endpoint_addr) then
mem_addr_base_next <= tmp; mem_addr_base_next <= MAX_ADDRESS; --No match
mem_cnt_next <= 0; -- DONE
mem_stage_next <= IDLE;
else
-- Continue Search
mem_addr_next <= tmp;
mem_addr_base_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
-- Match -- Match
else else
case (mem_ctrl_data.mem_opcode) is mem_addr_base_next <= mem_addr_base;
when REMOVE_PARTICIPANT => -- Fetch Endpoint Data
addr_res_next <= mem_addr_base; mem_stage_next <= GET_ENDPOINT_DATA;
-- Remove Endpoint from remote Participant mem_cnt_next <= 1; -- No preload needed
mem_stage_next <= REMOVE_ENDPOINT;
mem_addr_next <= mem_addr_base;
mem_cnt_next <= 0;
when INSERT_ENDPOINT =>
addr_res_next <= mem_addr_base;
-- Update Endpoint Data
mem_stage_next <= UPDATE_ENDPOINT;
mem_addr_next <= mem_addr_base + 4;
mem_cnt_next <= 0;
when others =>
addr_res_next <= mem_addr_base;
-- Fetch Endpoint Data
mem_stage_next <= GET_ENDPOINT_DATA;
mem_cnt_next <= 1; -- No preload needed
end case;
end if; end if;
when others => when others =>
null; null;
@ -1528,21 +1608,14 @@ begin
mem_wr <= '1'; mem_wr <= '1';
mem_write_data <= ENTITYID_UNKNOWN; mem_write_data <= ENTITYID_UNKNOWN;
if (mem_ctrl_data.mem_opcode = REMOVE_PARTICIPANT) then -- Reset MAX Endpoint Pointer
-- Continue Participant Match Search mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_base_next <= addr_res; mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= addr_res; mem_pos_next <= 0;
mem_stage_next <= SEARCH_ENDPOINT; reset_max_pointer_next <= '1';
mem_cnt_next <= 0; last_addr_next <= (others => '0');
else mem_stage_next <= FIND_ENDPOINT_SLOT;
-- Reset MAX Endpoint Pointer mem_cnt_next <= 0;
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_addr_next <= FIRST_ENDPOINT_ADDRESS;
reset_max_pointer_next <= '1';
last_addr_next <= (others => '0');
mem_stage_next <= FIND_ENDPOINT_SLOT;
mem_cnt_next <= 0;
end if;
when FIND_ENDPOINT_SLOT => when FIND_ENDPOINT_SLOT =>
mem_rd <= '1'; mem_rd <= '1';
mem_addr_next <= mem_addr + 1; mem_addr_next <= mem_addr + 1;
@ -1570,16 +1643,18 @@ begin
report "Memory Full, Ignoring Endpoint Data" severity NOTE; report "Memory Full, Ignoring Endpoint Data" severity NOTE;
-- Ignore Insertion -- Ignore Insertion
mem_stage_next <= IDLE; mem_stage_next <= IDLE;
addr_res_next <= MAX_ADDRESS; mem_addr_base_next <= MAX_ADDRESS;
else else
-- Extend Endpoint Memory Area -- Extend Endpoint Memory Area
-- NOTE: "max_endpoint_addr" points to the first address of last Endpoint Frame -- NOTE: "max_endpoint_addr" points to the first address of last Endpoint Frame
max_endpoint_addr_next <= tmp; max_endpoint_addr_next <= tmp;
-- Populate Endpoint Slot -- Populate Endpoint Slot
mem_stage_next <= INSERT_ENDPOINT; mem_stage_next <= INSERT_ENDPOINT;
mem_addr_next <= tmp; mem_addr_base_next <= tmp;
addr_res_next <= tmp; mem_addr_next <= tmp;
mem_cnt_next <= 0; mem_pos_next <= mem_pos + 1;
mem_addr_base_next <= tmp;
mem_cnt_next <= 0;
end if; end if;
else else
-- Latch last occupied Endpoint Slot -- Latch last occupied Endpoint Slot
@ -1587,10 +1662,12 @@ begin
-- Continue Search -- Continue Search
mem_addr_next <= tmp; mem_addr_next <= tmp;
mem_addr_base_next <= tmp; mem_addr_base_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0; mem_cnt_next <= 0;
end if; end if;
-- Slot Empty -- Slot Empty
else else
-- We are in the middle of resetting the MAX Endpoint Pointer
if (reset_max_pointer = '1') then if (reset_max_pointer = '1') then
-- Make sure to iterate through complete Endpoint Area -- Make sure to iterate through complete Endpoint Area
if (mem_addr_base = max_endpoint_addr) then if (mem_addr_base = max_endpoint_addr) then
@ -1602,20 +1679,20 @@ begin
-- Continue Search -- Continue Search
mem_addr_next <= tmp; mem_addr_next <= tmp;
mem_addr_base_next <= tmp; mem_addr_base_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0; mem_cnt_next <= 0;
end if; end if;
else else
-- Populate Endpoint Slot -- Populate Endpoint Slot
mem_stage_next <= INSERT_ENDPOINT; mem_stage_next <= INSERT_ENDPOINT;
mem_addr_next <= mem_addr_base; mem_addr_next <= mem_addr_base;
addr_res_next <= mem_addr_base; mem_cnt_next <= 0;
mem_cnt_next <= 0;
end if; end if;
end if; end if;
when others => when others =>
null; null;
end case; end case;
when FIND_NEXT_ENDPOINT => when GET_NEXT_ENDPOINT =>
mem_rd <= '1'; mem_rd <= '1';
mem_cnt_next <= mem_cnt + 1; mem_cnt_next <= mem_cnt + 1;
mem_addr_next <= mem_addr + 1; mem_addr_next <= mem_addr + 1;
@ -1634,21 +1711,21 @@ begin
-- Slot Occupied -- Slot Occupied
if (mem_read_data /= ENTITYID_UNKNOWN) then if (mem_read_data /= ENTITYID_UNKNOWN) then
-- Get Endpoint Data -- Get Endpoint Data
mem_addr_next <= tmp2; mem_addr_next <= tmp2;
addr_res_next <= mem_addr_base; mem_stage_next <= GET_ENDPOINT_DATA;
mem_stage_next <= GET_ENDPOINT_DATA; mem_cnt_next <= 0;
mem_cnt_next <= 0;
-- Slot Empty -- Slot Empty
else else
-- Reached End of Memory, No Match -- Reached End of Memory, No Match
if (mem_addr_base = max_endpoint_addr) then if (mem_addr_base = max_endpoint_addr) then
addr_res_next <= MAX_ADDRESS; --No match mem_addr_base_next <= MAX_ADDRESS; --No match
-- DONE -- DONE
mem_stage_next <= IDLE; mem_stage_next <= IDLE;
else else
-- Continue Search -- Continue Search
mem_addr_next <= tmp; mem_addr_next <= tmp;
mem_addr_base_next <= tmp; mem_addr_base_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0; mem_cnt_next <= 0;
end if; end if;
end if; end if;
@ -1682,13 +1759,14 @@ begin
else else
-- Reached End of Memory, No Match -- Reached End of Memory, No Match
if (mem_addr_base = max_endpoint_addr) then if (mem_addr_base = max_endpoint_addr) then
addr_res_next <= MAX_ADDRESS; --No match mem_addr_base_next <= MAX_ADDRESS; --No match
-- DONE -- DONE
mem_stage_next <= IDLE; mem_stage_next <= IDLE;
else else
-- Continue Search -- Continue Search
mem_addr_next <= tmp; mem_addr_next <= tmp;
mem_addr_base_next <= tmp; mem_addr_base_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0; mem_cnt_next <= 0;
end if; end if;
end if; end if;
@ -1704,7 +1782,6 @@ begin
-- Lease Deadline passed -- Lease Deadline passed
if (tmp_dw < time) then if (tmp_dw < time) then
-- Mark Endpoint as stale -- Mark Endpoint as stale
addr_res_next <= mem_addr_base;
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA; mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
-- DONE -- DONE
mem_stage_next <= IDLE; mem_stage_next <= IDLE;
@ -1718,21 +1795,21 @@ begin
-- Response/Suppression Time passed -- Response/Suppression Time passed
if (tmp_dw /= 0 and tmp_dw < time) then if (tmp_dw /= 0 and tmp_dw < time) then
-- Mark Endpoint and get Endpoint Data -- Mark Endpoint and get Endpoint Data
addr_res_next <= mem_addr_base; mem_addr_next <= tmp2;
mem_addr_next <= tmp2; mem_stage_next <= GET_ENDPOINT_DATA;
mem_stage_next <= GET_ENDPOINT_DATA; mem_cnt_next <= 0;
mem_cnt_next <= 0;
-- Endpoint not Stale -- Endpoint not Stale
else else
-- Reached End of Memory, No Match -- Reached End of Memory, No Match
if (mem_addr_base = max_endpoint_addr) then if (mem_addr_base = max_endpoint_addr) then
addr_res_next <= MAX_ADDRESS; --No match mem_addr_base_next <= MAX_ADDRESS; --No match
-- DONE -- DONE
mem_stage_next <= IDLE; mem_stage_next <= IDLE;
else else
-- Continue Search -- Continue Search
mem_addr_next <= tmp; mem_addr_next <= tmp;
mem_addr_base_next <= tmp; mem_addr_base_next <= tmp;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0; mem_cnt_next <= 0;
end if; end if;
end if; end if;

View File

@ -85,6 +85,7 @@ package rtps_package is
constant GUIDPREFIX_UNKNOWN : GUIDPREFIX_TYPE := (others => (others => '0')); constant GUIDPREFIX_UNKNOWN : GUIDPREFIX_TYPE := (others => (others => '0'));
constant UDP_PORT_INVALID : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); constant UDP_PORT_INVALID : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0');
constant IPv4_ADDRESS_INVALID : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0'); constant IPv4_ADDRESS_INVALID : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0');
constant LENGTH_UNLIMITED : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH));
-- *SUBMESSAGE IDs* -- *SUBMESSAGE IDs*
constant SID_PAD : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"01"; constant SID_PAD : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"01";
@ -279,9 +280,9 @@ package rtps_package is
-- DEPTH (HISTORY) -- DEPTH (HISTORY)
constant DEFAULT_HISTORY_DEPTH : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_LONG_WIDTH)); constant DEFAULT_HISTORY_DEPTH : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(1,CDR_LONG_WIDTH));
-- RESOURCE_LIMITS -- RESOURCE_LIMITS
constant DEFAULT_MAX_SAMPLES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED constant DEFAULT_MAX_SAMPLES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := LENGTH_UNLIMITED;
constant DEFAULT_MAX_INSTANCES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED constant DEFAULT_MAX_INSTANCES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := LENGTH_UNLIMITED;
constant DEFAULT_MAX_SAMPLES_PER_INSTANCE : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED constant DEFAULT_MAX_SAMPLES_PER_INSTANCE : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := LENGTH_UNLIMITED;
-- WRITER_DATA_LIFECYCLE -- WRITER_DATA_LIFECYCLE
constant DEFAULT_AUTODISPOSE_UNREGISTERED_INSTANCES : boolean := TRUE; constant DEFAULT_AUTODISPOSE_UNREGISTERED_INSTANCES : boolean := TRUE;
-- READER_DATA_LIFECYCLE -- READER_DATA_LIFECYCLE
@ -294,9 +295,9 @@ package rtps_package is
constant DEFAULT_DURABILITY_SERVICE_CLEANUP_DELAY : DURATION_TYPE := DURATION_ZERO; 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 : 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_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 constant DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := LENGTH_UNLIMITED;
constant DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED constant DEFAULT_DURABILITY_SERVICE_MAX_INSTANCES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := LENGTH_UNLIMITED;
constant DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE: std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH)); -- LENGTH_UNLIMITED constant DEFAULT_DURABILITY_SERVICE_MAX_SAMPLES_PER_INSTANCE: std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := LENGTH_UNLIMITED;
constant DEFAULT_PARTICIPANT_LEASE_DURATION : DURATION_TYPE; -- Deferred to package Body (100 s) constant DEFAULT_PARTICIPANT_LEASE_DURATION : DURATION_TYPE; -- Deferred to package Body (100 s)