Documentation & Code Refactoring
This commit is contained in:
parent
5f58b0bca4
commit
ca80910494
8
READ.txt
8
READ.txt
@ -12,11 +12,11 @@ AUTOMATICALLY
|
||||
-------------
|
||||
|
||||
* Open Terminal in /sim directory
|
||||
* Run 'vsim -do test_all.do'
|
||||
* Run 'vsim -c -do test_all.do'
|
||||
|
||||
NOTE: After some time the compilation of the simulator gets sluggisly slow.
|
||||
I noticed that deleting the Libraries and re-creating them re-vitalizes the speed
|
||||
In order to do so start a simulation (so that the Library is loaded), make sure that you end the current simulation, and type 'RemoveAllLibraries'. After a vsim re-start everything shoudl run faster
|
||||
NOTE: After some time the compilation of the simulator gets sluggishly slow.
|
||||
I noticed that deleting the Libraries and re-creating them re-vitalizes the speed.
|
||||
In order to do so start a simulation (so that the Library is loaded), make sure that you end the current simulation, and type 'RemoveAllLibraries'. After a vsim re-start everything should run faster
|
||||
|
||||
RUN ON BOARD
|
||||
============
|
||||
|
||||
127
Report.txt
127
Report.txt
@ -1,127 +0,0 @@
|
||||
---------------------------------------------------------------------------------
|
||||
Start RTL Component Statistics (1 Buffer)
|
||||
---------------------------------------------------------------------------------
|
||||
Detailed RTL Component Info :
|
||||
+---Adders :
|
||||
3 Input 14 Bit Adders := 1
|
||||
2 Input 14 Bit Adders := 3
|
||||
2 Input 9 Bit Adders := 1
|
||||
+---Registers :
|
||||
400 Bit Registers := 1
|
||||
88 Bit Registers := 1
|
||||
32 Bit Registers := 1
|
||||
14 Bit Registers := 5
|
||||
9 Bit Registers := 1
|
||||
4 Bit Registers := 1
|
||||
1 Bit Registers := 3
|
||||
+---RAMs :
|
||||
512K Bit RAMs := 1
|
||||
+---Muxes :
|
||||
2 Input 400 Bit Muxes := 2
|
||||
18 Input 400 Bit Muxes := 1
|
||||
2 Input 32 Bit Muxes := 10
|
||||
18 Input 32 Bit Muxes := 2
|
||||
2 Input 14 Bit Muxes := 1
|
||||
18 Input 14 Bit Muxes := 4
|
||||
18 Input 9 Bit Muxes := 1
|
||||
17 Input 5 Bit Muxes := 1
|
||||
2 Input 5 Bit Muxes := 10
|
||||
2 Input 2 Bit Muxes := 2
|
||||
2 Input 1 Bit Muxes := 7
|
||||
18 Input 1 Bit Muxes := 16
|
||||
---------------------------------------------------------------------------------------------------
|
||||
State | New Encoding | Previous Encoding
|
||||
---------------------------------------------------------------------------------------------------
|
||||
ipv4_init | 00000 | 00000
|
||||
ipv4_header_1 | 00001 | 00001
|
||||
ipv4_header_2 | 00010 | 00010
|
||||
ipv4_header_3 | 00011 | 00011
|
||||
ipv4_header_4 | 00100 | 00100
|
||||
ipv4_header_5 | 00101 | 00101
|
||||
skip_header | 00110 | 01111
|
||||
ipv4_fragment_pre | 00111 | 01000
|
||||
ipv4_fragment | 01000 | 01001
|
||||
ipv4_fragment_post | 01001 | 01010
|
||||
ipv4_buffer_src | 01010 | 01011
|
||||
ipv4_buffer_dest | 01011 | 01100
|
||||
ipv4_buffer_length | 01100 | 01101
|
||||
ipv4_buffer_payload | 01101 | 01110
|
||||
skip_packet | 01110 | 10000
|
||||
iSTATE | 01111 | 11111
|
||||
ipv4_payload_length | 10000 | 00110
|
||||
ipv4_payload | 10001 | 00111
|
||||
---------------------------------------------------------------------------------------------------
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
Start RTL Component Statistics (0 Buffer)
|
||||
---------------------------------------------------------------------------------
|
||||
Detailed RTL Component Info :
|
||||
+---Adders :
|
||||
2 Input 14 Bit Adders := 3
|
||||
3 Input 14 Bit Adders := 1
|
||||
2 Input 9 Bit Adders := 1
|
||||
+---Registers :
|
||||
400 Bit Registers := 1
|
||||
88 Bit Registers := 1
|
||||
14 Bit Registers := 5
|
||||
9 Bit Registers := 1
|
||||
4 Bit Registers := 1
|
||||
1 Bit Registers := 2
|
||||
+---Muxes :
|
||||
2 Input 400 Bit Muxes := 2
|
||||
2 Input 32 Bit Muxes := 7
|
||||
12 Input 32 Bit Muxes := 1
|
||||
2 Input 14 Bit Muxes := 1
|
||||
11 Input 4 Bit Muxes := 1
|
||||
2 Input 4 Bit Muxes := 7
|
||||
2 Input 1 Bit Muxes := 4
|
||||
12 Input 1 Bit Muxes := 7
|
||||
---------------------------------------------------------------------------------------------------
|
||||
State | New Encoding | Previous Encoding
|
||||
---------------------------------------------------------------------------------------------------
|
||||
ipv4_init | 0000 | 00000
|
||||
ipv4_header_1 | 0001 | 00001
|
||||
ipv4_header_2 | 0010 | 00010
|
||||
ipv4_header_3 | 0011 | 00011
|
||||
ipv4_header_4 | 0100 | 00100
|
||||
ipv4_header_5 | 0101 | 00101
|
||||
skip_header | 0110 | 01111
|
||||
ipv4_fragment_pre | 0111 | 01000
|
||||
ipv4_payload_length | 1000 | 00110
|
||||
ipv4_payload | 1001 | 00111
|
||||
skip_packet | 1010 | 10000
|
||||
iSTATE | 1011 | 11111
|
||||
---------------------------------------------------------------------------------------------------
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
Start RTL Component Statistics (No Frag)
|
||||
---------------------------------------------------------------------------------
|
||||
Detailed RTL Component Info :
|
||||
+---Adders :
|
||||
2 Input 14 Bit Adders := 1
|
||||
3 Input 14 Bit Adders := 1
|
||||
+---Registers :
|
||||
14 Bit Registers := 1
|
||||
4 Bit Registers := 1
|
||||
+---Muxes :
|
||||
2 Input 32 Bit Muxes := 3
|
||||
11 Input 32 Bit Muxes := 1
|
||||
10 Input 4 Bit Muxes := 1
|
||||
2 Input 4 Bit Muxes := 5
|
||||
2 Input 1 Bit Muxes := 1
|
||||
11 Input 1 Bit Muxes := 6
|
||||
---------------------------------------------------------------------------------------------------
|
||||
State | New Encoding | Previous Encoding
|
||||
---------------------------------------------------------------------------------------------------
|
||||
ipv4_init | 0000 | 0000
|
||||
ipv4_header_1 | 0001 | 0001
|
||||
ipv4_header_2 | 0010 | 0010
|
||||
ipv4_header_3 | 0011 | 0011
|
||||
ipv4_header_4 | 0100 | 0100
|
||||
ipv4_header_5 | 0101 | 0101
|
||||
skip_header | 0110 | 1000
|
||||
ipv4_payload_length | 0111 | 0110
|
||||
ipv4_payload | 1000 | 0111
|
||||
skip_packet | 1001 | 1001
|
||||
iSTATE | 1010 | 1111
|
||||
---------------------------------------------------------------------------------------------------
|
||||
BIN
doc/DDSI-RTPS_2-0.pdf
(Stored with Git LFS)
Normal file
BIN
doc/DDSI-RTPS_2-0.pdf
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -298,7 +298,7 @@ The 'ALIGN_STREAM' stage is split into 'ALIGN_IN_STREAM' (for decode_stage) and
|
||||
|
||||
The decode procedure (decode_stage stages) follows 2 different decoding procedures.
|
||||
The first - taken on a 'PUSH_DATA' opcode - follows the reader_interface procedure of the <TOPIC> type until
|
||||
the last declared member that is also member of the KeyHolder(<NAME>)[6] Type (i.e. the last decalred
|
||||
the last declared member that is also member of the KeyHolder(<NAME>)[6] Type (i.e. the last declared
|
||||
key of the type), after which the 'SKIP_PAYLOAD' stage is taken.
|
||||
(Since the serialized key only uses the KeyHolder(<NAME>) members, the rest is ignored)
|
||||
The second - taken on a 'PUSH_SERIALIZED_KEY' opcode - follows the reader_interface procedure of the
|
||||
@ -312,7 +312,7 @@ The first - taken on a 'READ_SERIALIZED_KEY' opcode - follows the write_interfac
|
||||
KeyHolder(<NAME>) Type.
|
||||
The second - taken on a 'READ_KEY_HASH' opcode (if the key is not already calculated) - follows the
|
||||
write_interface procedure of the <NAME>KeyHolder[7] Type. Note that this encoding is in PLAIN_CDR2
|
||||
Big Endian, meaning that types wich have an ALIGN_8 in PLAIN_CDR have a ALIGN_4 in PLAIN_CDR2.
|
||||
Big Endian, meaning that types which have an ALIGN_8 in PLAIN_CDR have a ALIGN_4 in PLAIN_CDR2.
|
||||
Both encoding procedures share the same encode_stages, and the 'encode_stage_next' signal is
|
||||
set depending on the 'opcode_latch' signal. On a 'READ_SERIALIZED_KEY' opcode the
|
||||
'WRITE_PAYLOAD_HEADER' stage selects the first encode_stage, while on a 'READ_KEY_HASH' opcode the
|
||||
@ -331,4 +331,4 @@ PITFALLS
|
||||
[4] DDS_XTYPES v1.3, 7.4.1.1.4
|
||||
[5] DDS_XTYPES v1.3, 7.4.1.1.5.2
|
||||
[6] DDS_XTYPES v1.3, 7.2.2.4.7
|
||||
[7] DDS_XTYPES v1.3, 7.6.8
|
||||
[7] DDS_XTYPES v1.3, 7.6.8
|
||||
|
||||
1146
src/REF.txt
1146
src/REF.txt
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@ use ieee.numeric_std.all;
|
||||
use work.rtps_package.all;
|
||||
use work.rtps_config_package.all;
|
||||
|
||||
architecture TYPENAME of key_holder is
|
||||
architecture TEMPLATE of key_holder is
|
||||
|
||||
--*****COMPONENT DECLARATION*****
|
||||
component key_hash_generator is
|
||||
@ -539,4 +539,4 @@ begin
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
end architecture;
|
||||
|
||||
458
src/TODO.txt
458
src/TODO.txt
@ -5,7 +5,7 @@
|
||||
- TwinOaks Computing Inc (CoreDX)
|
||||
- OpenVPX
|
||||
* Implementation makes unnecessary transitions, that are ignored in later stages.
|
||||
This was a design decision to simplify complexity of each stage (and probably FMAX), but increases power consumtion.
|
||||
This was a design decision to simplify complexity of each stage (and probably FMAX), but increases power consumption.
|
||||
* Is the Timestamp used by something else except ordering by source? If not, does it have to be "sane"?
|
||||
2.2.3.16
|
||||
This QoS relies on the sender and receiving applications having their clocks sufficiently synchronized. If this is not the case
|
||||
@ -33,6 +33,7 @@
|
||||
If reliability is BEST_EFFORT then the Service is allowed to drop samples. If the reliability is
|
||||
RELIABLE, the Service will block the DataWriter or discard the sample at the DataReader in order not to lose existing
|
||||
samples.
|
||||
- It means that if the reliability is RELIABLE, and the Reader has no more space for a sample, the Reader will not accept any more samples (hence discard, and by extension block further writes in the Writer, if the Writer has also no more space for storing samples, since the Reader is no longer accepting his sends) until the application takes samples.
|
||||
* What is now the valid Parameter List length?
|
||||
According to DDSI-RTPS 9.4.2.11
|
||||
The length encodes the number of octets following the length to reach the ID of the next parameter (or the ID of the sentinel). Because every parameterId starts on a 4-byte boundary, the length is always a multiple of four.
|
||||
@ -50,8 +51,9 @@
|
||||
duplicate messages that can result from the presence of redundant communication paths."
|
||||
But then, in 8.4.15.7 it says:
|
||||
"So, an implementation should ensure that same logical HEARTBEATs are tagged with the same Count."
|
||||
Does that mean there are cases were I have to put the same count? What is a logical HEARTBEAT?
|
||||
Does that mean there are cases where I have to put the same count? What is a logical HEARTBEAT?
|
||||
* Should a "Keyed" Endpoint communicate with a "Non-Keyed"? (In the sense of Entity Kind)
|
||||
- Well, since the Topic determines if it is keyed or keyless, and since Endpoints are matched by topics, only Endpoints of either type will be matched.
|
||||
* Is the empty String a valid Topic and Type Name?
|
||||
* We can determine if a Endpoint is a Reader or Writer via the Entity ID. Is it illegal to get a SEDP with incompatible source (Reader Entity ID from Publications Announcer?)
|
||||
* Can we make an array of records of uncontrained strings? Than we could make an array of variable sized strings...
|
||||
@ -71,6 +73,7 @@
|
||||
* Assert Heartbeat period > Heartbeat Suppression Period
|
||||
* Can I request (NACK) SNs that were NOT announced by the writer (> last_sn in Heartbeat)?
|
||||
* Does AUTOMATIC Liveliness QoS also update the lease on write/assert_liveliness operations?
|
||||
- unspecified. Only requirement is that automatic liveliness is asserted at least faster than the required period
|
||||
* The Lease Duration is also updated if the Cache Change is not accepted by the DDS/HC. This in effect "skews" the "correctness" of the Writer Liveliness Protocol until the reader has no pending request from the Writer.
|
||||
* If an Instance is DISPOSED, but later has no active writers, the Instance STAYS in the NOT_ALIVE_DISPOSED state.
|
||||
* Is a Writer that is Disposing an Instance also Unregistering that instance? (Currently only Unregistering removes the remote Writer)
|
||||
@ -78,14 +81,13 @@
|
||||
* Since Lifespan is a duration, there is an inherent difference in the expiration time between writer and reader. This in addition to the fact that the reader may use the Reception time for the expiration time calculation could lead to an actual expiration duration almost double in length (If sent right before expiring locally in the writer).
|
||||
* The current implementation will sent a second unregister/dispose Sample, if the user does the unregister/dispose operation a second time. Should we handle that specially?
|
||||
* If a Keyed Reader receives a DATA Message with no Key hash and no Payload, it will drop it since there is no way to determine the instance (And the SN will never be accepted).
|
||||
* If a Best Effort Remote Reader sends a ACKNACK, he will indirectly receive a lease deadline and may timeout (DoS Attack)
|
||||
* If a Best Effort Remote Reader sends an ACKNACK, he will indirectly receive a lease deadline and may timeout (DoS Attack)
|
||||
* Since the Instance Handle has to be Unique but also orderable, we could use the actual Instance Memory Base Address. Since the Instances are in a list, we also have implicitly an order to all registered Instances. [It may be necessary to add a PREV pointer to the IMF to better support the read_previous_isntance operation]
|
||||
- Not possible, because according to 2.2.2.5.3.16 read_next_instance, DDS v1.4:
|
||||
'This ordering is between the instance handles: It [...] must be defined even for instance handles that do not correspond to instances currently managed by the DataReader.'
|
||||
* Does the DEADLINE_QOS apply also to NOT_ALIVE Instances? (Current implementation makes no distinction)
|
||||
* Does TIME_BASED_FILTER also apply to meta-samples (DISPOSED, NO_WRITERS)? That is an easy way to not get convergent state in different DDS Readers. What do other implementations do?
|
||||
* The Participant GUID of the ParticipantMessageData is theoretically not needed, since it is the same as the source GUID of the Packet. This is done, so that the ParticipantMessageData has a key and can be decrypted as every other DATA Message. Our implementation checks if it is the expected GUID and drops it otherwise.
|
||||
- see (https://issues.omg.org/issues/DDSIRTP21-4)
|
||||
* The Participant GUID of the ParticipantMessageData is theoretically not needed, since it is the same as the source GUID of the Packet, but tt forms the DDS key together with the kind field. Our implementation checks if it is the expected GUID and drops it otherwise.
|
||||
* The Discovery Module skips a Packet it doesn't understand. The Discovery Module does not parse "serialized key" of DATA messages (since the specification does not actually define what the serialized key even is). So a SPDP DATA Packet with in-line QoS (PID_STATUS_INFO) and serialized key will be dropped if the Discovery Module does not know the GUID, and that may stall the whole process pipeline (since the SN will be never acknowledged)
|
||||
* Is the parameter header of an optional member in CDR_LE also endian swapped?
|
||||
- Yes. (See Figure 24, 7.4.1.2.1, DDS-XTYPES 1.3)
|
||||
@ -112,6 +114,23 @@
|
||||
We have to change the RTPS Reader to request the last SN, if the RTPS Writer did not publish for a minimum_separation period.
|
||||
* [8.4.7.1 RTPS Writer, DDSI-RTPS 2.3] states:
|
||||
"nackSuppressionDuration = ignore requests for data from negative acknowledgments that arrive ‘too soon’ after the corresponding change is sent."
|
||||
* According to [Table 8.9, 8.2.6 The RTPS Endpoint, DDSI-RTPS 2.3], topicKind "indicates wether the Endpoint supports instance lifecycle management operations", while at the same time "indicates wether the Endpoint is associated with a DataType that has defined some fields as containing the DDS Key".
|
||||
This implies that key-less Topics DO NOT have instance lifecycle management operations (i.e. no register/unregister/dispose operations)
|
||||
* Section [8.7 Implementing DDS QoS and advanced DDS features using RTPS] states:
|
||||
"This sub clause forms a normative part of the specification for the purpose of interoperability."
|
||||
- Which means that it is part of the Specification and NOT optional. Hence why 8.4.2.2.5 requires writers to send Writer Group Information for the purposes of interoperability.
|
||||
- Since LIVELINESS is also a DDS QoS why is the Writer Liveliness Protocol described in section [8.4.13 Writer Liveliness Protocol] of the Behaviour Module? It should also be described in section 8.7. As a matter of fact, section 8.4.13 explicitly states "The DDS specification requires the presence of a liveliness mechanism. RTPS realizes this requirement with the Writer Liveliness Protocol." while section 8.7 describes how the components introduced in section 8.4.13 can be used to implement the LIVELINESS QoS.
|
||||
* Section [9.3.1.2 Mapping of the EntityId_t] describes the correct mapping for Reader/Writers with/without key. How should Entities with GUIDs not following these rules be handled? Is it even illegal?
|
||||
* Section [2.3.2 PIM to PSM Mapping Rules] of the DDS specification explicitly states "The reason is that DCPS targets 'C' as one of the key deployment languages"
|
||||
* Section [9.6.2.2 Simple Discovery Protocol built-in Endpoints] implicitly defines the DDS keys of the built-in topics, by defining a key-only DATA message. Table 9.14 than also explicitly maps PID_ENDPOINT_GUID to the TopicBuiltinTopicData::key, SubscriptionBuiltinTopicData::key, and PublicationBuiltinTopicData::key fields.
|
||||
Should the key mapping also be explicitly written in text form.
|
||||
* I don't understand the use case of the PID_DIRECTED_WRITE of the RTPS specification. It was added with OMG issue (https://issues.omg.org/issues/DDSIRTP2-16), but is explained terribly.
|
||||
"The serialized information denotes the GUIDs of the targeted reader(s)."
|
||||
Isn't that the purpose of the Reader/Writer GUID of the DATA Submessage?
|
||||
Can I have multiple PID_DIRECTED_WRITE?
|
||||
* Since the DDS Reader is waiting on USER via the 'sample_info_ack' signal before continuing, a single user can stall all other USERs/Readers (DoS) of a vector entity of the DDS Reader.
|
||||
* Source Port of SPDP is irrelevant, since it is BEST EFFORT and we do not reply (only Destination Port is of significance)
|
||||
* According to "2.2.4.2.2 Changes in Read Communication Statuses" in the DDS 1.4 Specification it seems like it is meant to modify existing samples, instead of generating new data-less ones in order to transition the instance state.
|
||||
|
||||
* Fast-RTPS does not follow DDSI-RTPS Specification
|
||||
- Open Github Issue
|
||||
@ -132,24 +151,47 @@
|
||||
interpret the Reader entityIds appearing in the Submessages that follow it.'
|
||||
But state is changed as follows 'Receiver.destGuidPrefix = InfoDestination.guidPrefix'.
|
||||
Isn't Reader -> Writer also valid? Does it have a specific direction?
|
||||
- 9.4.5.3 Data Submessage
|
||||
writerSN is incorrectly shown as only 32 bits in width
|
||||
- 8.2.3 The RTPS CacheChange
|
||||
Add IDL Specification for CacheChange_t
|
||||
- 8.3.4 The RTPS Message Receiver, Table 8.16 - Initial State of the Receiver
|
||||
Port of UnicastReplyLocatorList should be initialized to Source Port.
|
||||
- 8.3.4.1 Rules Followed by the Message Receiver
|
||||
'Submessage and when it should be considered invalid.'
|
||||
This belongs to the previous sentence.
|
||||
- 8.3.7
|
||||
"Contains information regarding the value of an application Date-object."
|
||||
Shoulbe be Data-object
|
||||
Should be Data-object
|
||||
- 8.3.7.2.3 Validity
|
||||
"inlineQos is invalid."
|
||||
It is not specified what an invalid inlineQoS is.
|
||||
- 8.3.7.4.3 Validity
|
||||
gapList.Base >= gapStart
|
||||
- 8.3.7.4.5 Logical Interpretation
|
||||
'See section 8.7.6 for how DDS uses this feature.'
|
||||
Wrong reference. 8.7.5 correct
|
||||
- 8.3.7.5.5 Logical Interpretation
|
||||
'These fields provide relate the CacheChanges of Writers belonging to a Writer Group.'
|
||||
Remove provide
|
||||
'See 8.7.6 for how DDS uses this feature.'
|
||||
Wrong reference. 8.7.5 correct
|
||||
- 8.3.7.10.3 Validity
|
||||
'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.
|
||||
- 8.3.7.11.1
|
||||
"Given the size of a SequenceNumberSet is limited to 256, an AckNack Submessage is limited to NACKing only those samples whose sequence number does not not exceed that of the first missing sample by more than 256."
|
||||
'Given the size of a SequenceNumberSet is limited to 256, an AckNack Submessage is limited to NACKing only those samples whose sequence number does not not exceed that of the first missing sample by more than 256.'
|
||||
Remove one not
|
||||
- 8.4.2.2.5 Sending Heartbeats and Gaps with Writer Group Information
|
||||
This rules seems like a last minute addition and does not follow the format until now.
|
||||
|
||||
Maybe rewrite as "Writers must send Heartbeats and Gaps with Writer Group Information"?
|
||||
|
||||
'A Writer belonging to a Group shall send HEARTBEAT or GAP Submessages to its matched Readers even if the Reader has acknowledged all of that Writer’s samples.'
|
||||
This sentence has nothing in common with the actual requirement/rule. Usually the first sentence following the actual requirement explains the requirement in more detail.
|
||||
Is this sentnce do be understood in addition or instead of the actual requirement/rule?
|
||||
|
||||
'The exception to this rule is when the Writer has sent DATA or DATA_FRAG Submessages that contain the same information.'
|
||||
Link section 8.7.6 which states how this information is sent
|
||||
- 8.4.7 RTPS Writer Reference Implementation
|
||||
According to 8.2.2 the History Cache (HC) is the interface between RTPS nad DDS, and can be invoked
|
||||
by both RTPS and DDS Entities.
|
||||
@ -160,6 +202,8 @@
|
||||
This goes against 8.4.7 (and Table 8.5), which states that the RTPS Writer is adding the Cache Changes to the HC
|
||||
and is responsible for assigning Sequence Numbers.
|
||||
- Well, according to the Virtual machine, the new_change() method is invoked on the RTPS Writer
|
||||
- 8.4.13.4 Data Types Associated with Built-in Endpoints used by Writer Liveliness Protocol
|
||||
Figure 8.26 states that GUID_t is used, but the PSM (9.6.2.1) maps GuidPrefix_t (Which also makes more sense)
|
||||
- 8.7.2.2.1 DURABILITY
|
||||
'While volatile and transient-local durability do not affect the RTPS protocol'
|
||||
But in case of Durability TRANSIENT_LOCAL the writer has to send historical Data.
|
||||
@ -171,9 +215,31 @@
|
||||
MANUAL_BY_PARTICIPANT Liveliness.
|
||||
- 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
|
||||
- 8.7.4 Changes in the Instance State
|
||||
Wrong reference 9.6.3.4 (Correct 9.6.3.9)
|
||||
- 8.7.4 Changes in the Instance State
|
||||
'The DDS DataReader can determine the nature of the change by inspecting the InstanceState instance_state field in the SampleInfo that is returned on the DDS DataReader read or take call.'
|
||||
'The serialized information within the inline QoS contains the new InstanceState, that is, whether the instance has been registered, unregistered, or disposed.'
|
||||
The Specification uses the term "InstanceState" to mean both the instance states defined in the DDS specification (ALIVE, NOT_ALIVE_DISPOSED, NOT_ALIVE_NO_WRITERS) and the ChangeKind_t (ALIVE, ALIVE_FILTERED, NOT_ALIVE_DISPOSED, NOT_ALIVE_UNREGISTERED) defined in 8.2.1.2
|
||||
This section should do a mapping between the two, or rename the "local" ones and use the respective terms uniformly.
|
||||
- 8.7.7 Directed Write
|
||||
Mention or link the PID_DIRECTED_WRITE?
|
||||
- 8.7.9 Original Writer Info
|
||||
"This service that forwards messages"
|
||||
Replace "This" with "The"
|
||||
"The RTPS protocol suports this forwarding of messages by including information of the original writer."
|
||||
supports
|
||||
- 9.2.2
|
||||
Add newline to IDL definition after "OctetArray3 entityKey;"
|
||||
- 9.3.1.2 Mapping of the EntityId_t
|
||||
Add newline to IDL definition after "typedef octet OctetArray3[3];"
|
||||
- 9.3.2.4 GroupDigest_t
|
||||
Missing "EntityId_t" struct type name on the second struct IDL definition.
|
||||
- 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.
|
||||
- 9.4.5.3 Data Submessage
|
||||
writerSN is incorrectly shown as only 32 bits in width
|
||||
- 9.4.5.3.1 Data Flags
|
||||
"D=1 and K=1 is an invalid combination in this version of the protocol."
|
||||
Does this invalidate the Submessage? Does 8.3.4.1 apply (Invalidate rest of Message)?
|
||||
@ -204,6 +270,8 @@
|
||||
- 8.2.1 Overview
|
||||
Figure 8.1 should contain the RTPS Group Entry (it even has its own section 8.2.6)
|
||||
It should also get an Entry in the Table 8.1
|
||||
- 8.5.4.4 Data Types associated with built-in Endpoints used by the Simple Endpoint Discovery Protocol
|
||||
Figure 8.30 does not represent the types defined in DDS Specification
|
||||
- 8.7.5 Group Ordered Access
|
||||
"A DataReader attached to a Subscriber configured with access scope GROUP" should be Reader (RTPS), and not DataReader (DDS)
|
||||
- This section has general incosistency in the use of the RTPS and DDS counterparts
|
||||
@ -227,64 +295,144 @@
|
||||
But the opration only returns InstanceHandle_t. Other vendors return HANDLE_NIL also on error and not only
|
||||
"if the Service does not want to allocate any handle for that instance".
|
||||
It should propably behave like the Lookup_Instance operation.
|
||||
* Source Port of SPDP is irrelevant, since it is BEST EFFORT and we do not reply (only Destination Port is of significance)
|
||||
|
||||
|
||||
- General
|
||||
Clarify semantic difference between lost and rejected samples.
|
||||
- General
|
||||
How handling of MAX_INSTANCES is affected by the HISTORY QoS Policy
|
||||
- General
|
||||
The DDS Specification does not explicitly state that the behaviour of the Register/Unregister/Dispose Operations have on non-keyed Topics
|
||||
- General
|
||||
The DDS Specification is not entirely clear how to handle transition between the NOT_ALIVE states. Going by the
|
||||
petri-net state-flowchart transitions between the NOT_ALIVE states are not allowed, meaning that the first taken
|
||||
NOT_ALIVE state stays until the instance is reborn. But since the Disposal of an Instance is of higher
|
||||
Information value, we should support transitioning from NOT_ALIVE_NO_WRITERS to NOT_ALIVE_DISPOSED.
|
||||
- General
|
||||
An RTPS CacheChange is not equal to a DDS Sample. (e.g. an unregister CacheChange does not necessarily translate
|
||||
to a DDS Sample). State the translation.
|
||||
|
||||
DESIGN DECISIONS
|
||||
================
|
||||
|
||||
GENERAL
|
||||
-------
|
||||
|
||||
* !REJECTED!
|
||||
In order to save memory GUID should only be saved once.
|
||||
Decision was made to replace GUID with internal reference index.
|
||||
Discovery module is responsible for saving the GUID and map it to a refernece index, that can then be used by other entities.
|
||||
Writer Endpoints may need access to the real GUID for message fields.
|
||||
2 options exist:
|
||||
In order to save memory GUID should only be saved once. Decision was made to replace GUID with internal reference
|
||||
index. Discovery module is responsible for saving the GUID and map it to a reference index, that can then be used
|
||||
by other entities. Writer Endpoints may need access to the real GUID for message fields.
|
||||
2 options exist:
|
||||
- All Endpoints have access to the central memory where the real GUID is saved (needs Arbiter, handle starvation)
|
||||
- Writer Endpoints fill the fields with the reference index as placeholder, and a seperate Entity will access the central memory and replace the actual values
|
||||
- Writer Endpoints fill the fields with the reference index as placeholder, and a separate Entity will access
|
||||
the central memory and replace the actual values
|
||||
The Second option was chosen (Less resources)
|
||||
RTPS Handler should lookup received message GUID in central memory (The lookup should happen in parallel with the actual message handling):
|
||||
RTPS Handler should lookup received message GUID in central memory (The lookup should happen in parallel with the
|
||||
actual message handling):
|
||||
- If not stored, and message not for Discovery Module, drop message
|
||||
- If in memory, replace with refernece index
|
||||
The central memory is accessd by 3 Entities:
|
||||
- If in memory, replace with reference index
|
||||
The central memory is accessed by 3 Entities:
|
||||
- RTPS Handler (READ, GUID Lookup)
|
||||
- Placeholder Handler (READ, GUID Lookup)
|
||||
- Discovery Module (WRITE, GUID Save) [Need initial Lookup? RTPS Handler should have already handled it. How does DM know if actual GUID or reference index?]
|
||||
- Discovery Module (WRITE, GUID Save) [Need initial Lookup? RTPS Handler should have already handled it. How
|
||||
does DM know if actual GUID or reference index?]
|
||||
Use a 2-port RAM with an arbiter for READ operations (Give Placeholder Handler priority to prevent DoS starvation)
|
||||
|
||||
* Use the lowest bit of the Heartbeat/Acknack Deadline stored in the Participant Data to differentiate
|
||||
* Use the lowest bit of the Heartbeat/Acknack Deadline stored in the memory to differentiate
|
||||
between Delay and Suppression. This reduces the resolution from 0.23 ns to 0.47 ns
|
||||
(A previous version was using the unused extra flags in the stored participant data)
|
||||
|
||||
* Originally we stored the mask of local matching endpoints in the memory frame of the remote endpoint
|
||||
in order to be able to send MATCH frames only to new matches, and UNMATCH frames only to previously
|
||||
matched local endpoints. This decision was reverted, and we just sent MATCH frames to the currently
|
||||
matched local endpoints (non depending on if they are already matched) and UNMATCH frames to the
|
||||
* Initially the RTPS/DDS Endpoints were designed as one Endpoint per Entity. This allows maximum parallel
|
||||
processing and each entity having the bare minimum HW based on generics that define the properties of
|
||||
each Endpoint. Nevertheless the amount of Resources needed to synthesize are quite substantial, and there
|
||||
is a (low) limit of how many Endpoints can be instantiated. This limit was reached when trying to
|
||||
synthesize a ROS action server, which instantiates 9 RTPS and DDS Endpoints.
|
||||
Since the only real difference between the Endpoints is the Memory, we could reuse the main state
|
||||
machine for all Endpoints and just instantiate different memories.
|
||||
A redesign of all Endpoints was decided, in which multiple Endpoints are simulated by one Entity.
|
||||
The contained Endpoints are addressed in sequential order, meaning that we lose the parallel processing,
|
||||
but since the RTPS protocol is primarily used over UDP, there is no difference in performance.
|
||||
Although the ports of the entity could remain single dimension (since only one Endpoint is
|
||||
reading/writing at a time), we would lose the information of which Endpoint is addressed and would have
|
||||
to extend the inter-communication schema to relay this information. To avoid this, and to be backwards
|
||||
compatible (allow to instantiate multiple Endpoint Entities), the dimensions of the ports of the
|
||||
Endpoints will be extended by the dimension of Endpoints contained with some exceptions.
|
||||
These exceptions are the all RTPS Output ports, and the read, data_in, and last_word_in RTPS Handler
|
||||
and DISCOVERY Module ports. This prevents wasting resources on FIFOs, but still conveys addressing
|
||||
information via the empty signal.
|
||||
This works, because the RTPS Handler and DISCOVERY MODULE write in a multicast fashion (meaning that all
|
||||
addressed Entities become the same data).
|
||||
|
||||
* The above decision brings with it another challenge. Since now the input signals are unbalanced
|
||||
(empty port is vector, but read, data_in, and last_word_in are not) we need a special kind of FIFO
|
||||
to connect to the input ports of the Endpoints. This special FIFO is called "vector_FIFO" and contains
|
||||
a FIFO for the data, and a FIFO for the write signal, that is internally converted to the empty signal
|
||||
and simulates multiple FIFOs.
|
||||
|
||||
DISCOVERY MODULE
|
||||
----------------
|
||||
|
||||
* Originally we stored the mask of local matching endpoints in the memory frame of the remote participant
|
||||
in order to be able to send MATCH frames only to new matches, and UNMATCH frames only to previously
|
||||
matched local endpoints. This decision was reverted, and we just sent MATCH frames to the currently
|
||||
matched local endpoints (non depending on if they are already matched) and UNMATCH frames to the
|
||||
rest of the local endpoints (non depending on if they were previously matched).
|
||||
So we basically push the responsibility to the local endpoints, which have to handle these situations
|
||||
accordingly. Since META traffic is not supposed to be generated as often, this should not produce
|
||||
any significant overhead. As optimization, on new matched remote endpoints UNMATCH frames can be
|
||||
So we basically push the responsibility to the local endpoints, which have to handle these situations
|
||||
accordingly. Since META traffic is not supposed to be generated as often, this should not produce
|
||||
any significant overhead. As optimization, on new matched remote endpoints UNMATCH frames can be
|
||||
ignored.
|
||||
|
||||
* The HEARTBEATs are sent out together with the liveliness assertions. This adds a 96-Byte overhead
|
||||
to the output RTPS Message. This was done to prevent having to loop through the memory to find
|
||||
* The HEARTBEATs are sent out together with the liveliness assertions. This adds a 96-Byte overhead
|
||||
to the output RTPS Message. This was done to prevent having to loop through the memory to find
|
||||
remote participant destination more than once.
|
||||
|
||||
* The Publisher, Subscriber, and Message Data is written on separate RTPS Messages, even though they are
|
||||
sent simutanously. This decision was made to support as many local Endpoints as possible. We could
|
||||
make a compile-time check and sent them in the same RTPS Message/UDP Packet, but the overhead is
|
||||
* The Publisher, Subscriber, and Message Data is written on separate RTPS Messages, even though they are
|
||||
sent simultaneously. This decision was made to support as many local Endpoints as possible. We could
|
||||
make a compile-time check and sent them in the same RTPS Message/UDP Packet, but the overhead is
|
||||
quite small and not worth the hassle.
|
||||
|
||||
* Even though the Reader does not need to keep track of received SN with respect to each Writer with
|
||||
exception of the Highest/Last received (since it only keeps the SN in order and does only need to
|
||||
request from the last stored SN on), the writer does need to keep track of the requested SN (and
|
||||
|
||||
RTPS ENDPOINTS
|
||||
--------------
|
||||
|
||||
* Even though the Reader does not need to keep track of received SN with respect to each Writer with
|
||||
exception of the Highest/Last received (since it only keeps the SN in order and does only need to
|
||||
request from the last stored SN on), the writer does need to keep track of the requested SN (and
|
||||
possibly also the acknowledgements).
|
||||
This could be solved by either storing the SN in a bitmap in the endpoint data, or be storing the
|
||||
requester bitmap (endpoint data address) in the change data.
|
||||
But since the writer might drop SN in any order, the highest and lowest SN inside the cache history
|
||||
is unbounded. We can thus only reference to still available SN, and not to GAPs.
|
||||
In order to acoomodate for that, we could store the lowest (and possibly highest) SN of a requested
|
||||
This could be solved by either storing the SN in a bitmap in the endpoint data, or by storing the
|
||||
requester bitmap (endpoint data address) in the cache change data.
|
||||
But since the writer might drop SNs in any order, the highest and lowest SN inside the cache history
|
||||
is unbounded. We can thus only reference to still available SNs, and not to GAPs.
|
||||
In order to accommodate for that, we could store the lowest (and possibly highest) SN of a requested
|
||||
lost SN and always send ALL GAPs in that range.
|
||||
|
||||
* Since the RTPS Writer only gets ACKNACK Messages from the matched Readers, and these Messages are
|
||||
dropped by the rtps_handler if smaller than expected, we do not need a "READ GUARD" in the RTPS
|
||||
Writer.
|
||||
|
||||
* Because "Once Acknowledged, Always Acknowledged" the Base of an ACKNACK can only be bigger or
|
||||
equal to the SN of the last ACKNACK. It is also reasonable, that the Reader will always request
|
||||
ALL missing segments each time it sends an ACKNACK (i.e. does not assume once requested, always
|
||||
requested until reception). This means that during the ACKNACK response delay, we can just parse
|
||||
the new request bitmap and overwrite the last old one.
|
||||
|
||||
* In the RTPS Writer remote Volatile Reliable Readers are initialized with a SN equal to
|
||||
the last written. This means that while the Reader can access the historical SNs via ACKNACK, the SNs
|
||||
are not NACKed in the HC, and can therefore be removed at any time, not depending on the state of the
|
||||
remote reader.
|
||||
|
||||
* The RTPS Writer is only sending GAPs when processing ACKNACK Requests or sending Historical DATA.
|
||||
That means that if the HC pulls the 'data_available' Signal and deletes Cache Changes before the
|
||||
RTPS Writer has requested them, it will just ignore the Cache Change. A GAP will only be generated
|
||||
if a reliable Reader subsequently requests this Cache Change.
|
||||
|
||||
* If PUSH_MODE is false, packets are only written as response to ACKNACK requests (except HEARTBEATS).
|
||||
This means that a Reliable RTPS Writer in PUSH_MODE = FALSE cannot communicate with Best Effort Readers.
|
||||
Historical Data is also only sent out on request (But NACKed in the HC, until the remote Reader ACKs them).
|
||||
|
||||
* Following the vector entity change, since the message format from RTPS reader to DDS reader contains information
|
||||
specific to the individual writer (Writer ID, Lifespan Deadline), we cannot write to multiple DDS endpoints at the
|
||||
same time. This means that we have to temporarily store the payload and push it to each DDS Endpoint individually.
|
||||
|
||||
DDS ENDPOINTS
|
||||
-------------
|
||||
|
||||
* The meta_data (sample info) of a cache change is fixed size, and a cache change may be connected to
|
||||
data (payload), which may be variable in size. For this reason, we store the cache change and
|
||||
@ -294,7 +442,8 @@ DESIGN DECISIONS
|
||||
of the next linked memory frame. If this is the last frame (or if the payload is static and there
|
||||
are no linked frames), the address is MAX_ADDRESS.
|
||||
|
||||
* !REJECTED! The last bit of this address is the "occupied" bit. This bit signifies if the memory
|
||||
* !REJECTED!
|
||||
The last bit of this address is the "occupied" bit. This bit signifies if the memory
|
||||
frame is used or free, and is used for the insert operation to find a new empty slot. This in
|
||||
effect means that all frame sizes have to be a multiple of 2 (all frame addresses have to be
|
||||
aligned to 2).
|
||||
@ -303,7 +452,8 @@ DESIGN DECISIONS
|
||||
Payload slot, we mark this via a bit in the sample info memory, and store the last address of the
|
||||
actual payload in the last address of the payload slot.
|
||||
|
||||
* !REJECTED! The History Cache (HC) is the interface between RTPS and DDS. The History Cache contains
|
||||
* !REJECTED!
|
||||
The History Cache (HC) is the interface between RTPS and DDS. The History Cache contains
|
||||
the Sample Info and Payload memories. The HC has two input "sides", one is connected to the DDS
|
||||
and one to the RTPS entity. Housing the memories inside the HC entity and abstracting the direct
|
||||
memory address via opcode requests allows the memory interface to be replaced in future (e.g. AXI
|
||||
@ -321,12 +471,15 @@ DESIGN DECISIONS
|
||||
* Since most of the DDS QoS need information that is directly available to the History Cache (HC),
|
||||
it makes sense to integrate most of the DDS functionality directly into the HC to save up space
|
||||
and performance. Further more the needed stored information for a DDS Entity is different enough
|
||||
from the generic HC defined in the RTPS Specification to warrant a seperate entity for both.
|
||||
from the generic HC defined in the RTPS Specification to warrant a separate entity for both.
|
||||
The DDS Entity will directly connect to the RTPS Endpoint. A separate generic HC will be
|
||||
implemented, that follows the RTPS Specification.
|
||||
The RTPS Endpoint will have to output multiple versions of Changes, depending on the connected
|
||||
Entity, in order to facilitate this design decision.
|
||||
|
||||
* Since the "reading" side needs to have consistent state during it's processing, it does not make
|
||||
sense to implement dual port RAMs for the History Cache.
|
||||
|
||||
* Because the Key Hash has to be known in order to make an ACCEPT/REJECT decision for the new
|
||||
Sample, and the fact that the Key Hash is not always given and has to be manually calculated from
|
||||
the payload, we need "buffer" slots to store the Sample and Payload until the decision can be
|
||||
@ -344,42 +497,6 @@ DESIGN DECISIONS
|
||||
to multiple Sample removals (One prior the addition in order to free up a Payload "buffer", and
|
||||
one after addition as a result of QoS policies).
|
||||
|
||||
* Since the "reading" side needs to have consistent state during it's processing, it does not make
|
||||
sense to implement dual port RAMs for the History Cache.
|
||||
|
||||
* Since the RTPS Writer only gets ACKNACK Messages from the matched Readers, and these Messages are
|
||||
dropped by the rtps_handler if smaller than expected, we do not need a "READ GUARD" in the RTPS
|
||||
Writer.
|
||||
|
||||
* Because "Once Acknowledged, Always Acknowledged" the Base of an ACKNACK can only be bigger or
|
||||
equal to the SN of the last ACKNACK. It is also reasonable, that the Reader will always request
|
||||
ALL missing segments each time it sends an ACKNACK (i.e. does not assume once requested, always
|
||||
requested until reception). This means that during the ACKNACK response delay, we can just parse
|
||||
the new request bitmap and overwrite the last old one.
|
||||
|
||||
* In the RTPS Writer remote Volatile Reliable Readers are initialized with a SN equal to
|
||||
the last written. This means that while the Reader can access the historical SNs via ACKNACK, the SNs
|
||||
are not NACKed in the HC, and can therefore be removed at any time, not depending on the state of the
|
||||
remote reader.
|
||||
|
||||
* Since all code related to encoding/decoding the DATA stream is dependent on the IDL type
|
||||
specification, we have to encapsule that code separately and link them as necessary. Two such
|
||||
dynamic Entities are defined: KEY_HOLDER, and <TYPENAME>_INTERFACE.
|
||||
The KEY_HOLDER Entity contains a Byte-Wide internal memory (In size equal to the maximum key size),
|
||||
that can be filled with PLAIN_CDR/PL_CDR DATA Streams, and Serialized Key Streams.
|
||||
The Entity allows outputting the memory contents (Key) either in a KEY_HASH format (needs
|
||||
to instantiate a MD5 calculator), or in Serialized Key Format. The Entity uses the start/opcode/ack
|
||||
interface for operations (similar to the RTPS/DDS Interface).
|
||||
The <TYPENAME>_INTERFACE entity has all type-components linked to ports and latched in registers/memory.
|
||||
In output mode the entity is able to fill the registers/memory with a PLAIN_CDR/PL_CDR Data Stream, and
|
||||
in input mode the registers are filled directly from the input ports and the Entity is able to produce
|
||||
a PLAIN_CDR/PL_CDR Data Stream from the registers/memory.
|
||||
Due to the type-specific nature of the entities, those are not instantiated inside the DDS Endpoints,
|
||||
but will be instantiated in a seperate entity (Interface) and linked through port mapping with the
|
||||
DDS Endpoints.
|
||||
X: Due to port mapping differences between DDS Reader and Writer the <TYPENAME>_INTERFACE is splitt into
|
||||
<TYPENAME>_READER_INTERFACE and <TYPENAME>_WRITER_INTERFACE.
|
||||
|
||||
* Due to the requirements of read_next_instance/take_next_instance of the DDS Reader, the Instances are
|
||||
inserted in numerical Key Hash order into the Instance Memory. This extra sorting logic is not needed
|
||||
in the DDS Writer, where Instances are inserted normally to the end of the List.
|
||||
@ -394,12 +511,13 @@ DESIGN DECISIONS
|
||||
lead to inconsistent behavior (see REF.txt). RTI has thus decided to only delete unregistered
|
||||
instances. I will copy this behavior.
|
||||
|
||||
* !REJECTED! DATA WRITER: Once an instance is unregistered, it is eligible for deletion except if it is
|
||||
* !REJECTED!
|
||||
DATA WRITER: Once an instance is unregistered, it is eligible for deletion except if it is
|
||||
Re-registered, or a write operation occurs on that instance. Disposal of an unregistered Instance
|
||||
does not re-register the instance (State remains NOT_ALIVE) and is still eligible for deletion.
|
||||
NOTE: The statement above is incorrect, as a writer wanting to dispose an Intsnace has to re-register
|
||||
NOTE: The statement above is incorrect, as a writer wanting to dispose an Instance has to re-register
|
||||
the Instance. Hence, it is re-registered (and the disposing writer is again active), the state
|
||||
Instance remains howerer in a NOT_ALIVE state.
|
||||
Instance remains however in a NOT_ALIVE state.
|
||||
|
||||
* The DDS Specification does not explicitly state that the behaviour of the Register/Unregister/Dispose
|
||||
Operations have on non-keyed Topics. RTI basically does a NOP and does not modify the instance in
|
||||
@ -409,7 +527,7 @@ DESIGN DECISIONS
|
||||
|
||||
* The DDS Specification states that if after an Unregister Operation "the application wants to modify
|
||||
(write or dispose) the instance, it has to register it again, or else use the special handle value
|
||||
HANDLE_NIL". I do not have this prerequirement. It will return BAD_PARAMETER only if the Instance
|
||||
HANDLE_NIL". I do not have this pre-requirement. It will return BAD_PARAMETER only if the Instance
|
||||
is not in the memory anymore.
|
||||
|
||||
* The DDS Specification is not entirely clear how to handle transition between the NOT_ALIVE states.
|
||||
@ -448,22 +566,37 @@ DESIGN DECISIONS
|
||||
Data Readers having different Generation Counters (depending on their reception order).
|
||||
NOTE: The NOT_ALIVE Samples are always added to the end of the list, not depending on their TS. This
|
||||
is the only exception in which samples TS does not follow their list order.
|
||||
|
||||
|
||||
* The DEADLINE check times of the DDS Entities are aligned to the release of the reset, and not on the addition of
|
||||
a new instance. That means that all Instances are checked at the same time, non depending on when they were added.
|
||||
|
||||
IDL
|
||||
---
|
||||
|
||||
* Since all code related to encoding/decoding the DATA stream is dependent on the IDL type
|
||||
specification, we have to encapsulate that code separately and link them as necessary. Two such
|
||||
dynamic Entities are defined: KEY_HOLDER, and <TYPENAME>_INTERFACE.
|
||||
The KEY_HOLDER Entity contains a Byte-Wide internal memory (In size equal to the maximum key size),
|
||||
that can be filled with PLAIN_CDR/PL_CDR DATA Streams, and Serialized Key Streams.
|
||||
The Entity allows outputting the memory contents (Key) either in a KEY_HASH format (needs
|
||||
to instantiate a MD5 calculator), or in Serialized Key Format. The Entity uses the start/opcode/ack
|
||||
interface for operations (similar to the RTPS/DDS Interface).
|
||||
The <TYPENAME>_INTERFACE entity has all type-components linked to ports and latched in registers/memory.
|
||||
In output mode the entity is able to fill the registers/memory with a PLAIN_CDR/PL_CDR Data Stream, and
|
||||
in input mode the registers are filled directly from the input ports and the Entity is able to produce
|
||||
a PLAIN_CDR/PL_CDR Data Stream from the registers/memory.
|
||||
Due to the type-specific nature of the entities, those are not instantiated inside the DDS Endpoints,
|
||||
but will be instantiated in a separate entity (Interface) and linked through port mapping with the
|
||||
DDS Endpoints.
|
||||
X: Due to port mapping differences between DDS Reader and Writer the <TYPENAME>_INTERFACE is split into
|
||||
<TYPENAME>_READER_INTERFACE and <TYPENAME>_WRITER_INTERFACE.
|
||||
|
||||
* MUTABLE extensibility is currently unsupported, as the PL_CDR encoding needs to be able to dynamically
|
||||
calculate the sizes of type members, which was deemed to complicated.
|
||||
calculate the sizes of type members, which was deemed too complicated.
|
||||
|
||||
* Similar to the previous decision, only optional members with fixed size are supported (Since the optional
|
||||
members need a parameter list header, which has a length field).
|
||||
|
||||
* The RTPS Writer is only sending GAPs when processing ACKNACK Requests or sending Historical DATA.
|
||||
That means that if the HC pulls the 'data_available' Signal and deletes Cache Changes before the
|
||||
RTPS Writer has requested them, it will just ignore the Cache Change. A GAP will only be generated
|
||||
if a reliable Reader subsequently requests this Cache Change.
|
||||
|
||||
* If PUSH_MODE is false, packets are only written as response to ACKNACK requests (except HEARTBEATS).
|
||||
This means that a Reliable RTPS Writer in PUSH_MODE = FALSE cannot communicate with Best Effort Readers.
|
||||
Historical Data is also only sent out on request (But NACKed in the HC, until the remote Reader ACKs them).
|
||||
|
||||
* Whereas the DDS Writer/Reader are flexible in the handling of variable sized Payloads - they write the
|
||||
payload in multiple memory slots, effectively eating away from the MAX_SAMPLES limit, since there are
|
||||
only MAX_SAMPLES memory slots avialable - the decoding in TYPENAME_interface requires and explicitly
|
||||
@ -472,6 +605,9 @@ DESIGN DECISIONS
|
||||
does enforce those limits implicitly, since it encodes the memory/registers that are physically limited
|
||||
to those specified upper bounds during static generation.
|
||||
|
||||
ROS
|
||||
---
|
||||
|
||||
* RTPS/DDS use a time representation of 64-bit seconds in 32Q32 fixed point format. The ROS libraries
|
||||
use a 64-bit unsigned nanosecond representation, and ROS sends time (defined in
|
||||
rcl_interfaces/builtin_interfaces) in 32-bit second and 32-bit nanosecond respresentation.
|
||||
@ -479,67 +615,96 @@ DESIGN DECISIONS
|
||||
between the representations are quite resource and latency heavy.
|
||||
Since the ros action server directly interfaces ros services with the builtin_interfaces definition,
|
||||
it was decided that the entire server works on this representation to avoid costly conversions. This in
|
||||
effect mitigates the converion problem to the instantiating entity, but a single conversion point could
|
||||
effect mitigates the conversion problem to the instantiating entity, but a single conversion point could
|
||||
be defined that can be used throughout the system.
|
||||
|
||||
* Initialy the RTPS/DDS Endpoints were designed as one Endpoint per Entity. This allows maximum parallel
|
||||
processing and each entity having the bare minimum HW beased on generics that define the properties of
|
||||
each Endpoint. Nevertheless the amount of Resources needed to synthesize are quite substantial, and there
|
||||
is a (low) limit of how many Endpoints can be instantiated. This limit was reached when trying to
|
||||
synthesize a ROS action server, which instantiates 9 RTPS and DDS Endpoints.
|
||||
Since the only real difference between the Endpoints is the Memory, we could reuse the main state
|
||||
machine for all Endpoints and just instantiate different memories.
|
||||
A redesign of all Endpoints was decided, in which multiple Endpoints are simulated by one Entity.
|
||||
The contained Endpoints are addressed in sequential order, meaning that we lose the parrallel processing,
|
||||
but since the RTPS protocol is primarilly used over UDP, there is no difference in performance.
|
||||
Although the ports of the entity could remain single dimension (since only one Endpoint is
|
||||
reading/writing at a time), we would lose the information of which Endpoint is addressed and would have
|
||||
to extend the inter-communication shema to relay this information. To avoid this, and to be backwards
|
||||
compatible (allow to instantiate multiple Endpoint Entities), the dimensions of the ports of the
|
||||
Endpoints will be extended by the dimension of Endpoinst contained with some exceptions.
|
||||
These exceptions are the all RTPS Output ports, and the read,data_in, and last_word_in RTPS Handler
|
||||
and DISCOVERY Module ports. This prevents wasting resources on FIFOs, but still conveys addressing
|
||||
information via the empty signal.
|
||||
This works, because the RTPS Handler and DISCOVERY MODULE write in a multicast fashion (meaning that all
|
||||
addressed Entities become the smae data).
|
||||
|
||||
* The above decision brings which it another challenge. Sice now the input signals are unbalanced
|
||||
(empty port is vector, but read, data_in, and last_word_in are not) we need a special kind of FIFO
|
||||
to connect to the input ports of the Endpoints. This special FIFO is called "vector_FIFO" and contains
|
||||
a FIFO for the data, and a FIFO for the write signal, that is internally converted to the empty signal
|
||||
and simulates multiple FIFOs.
|
||||
|
||||
* Since the message format from RTPS reader to DDS reader contains information specific to the individual
|
||||
writer (Writer ID, Lifespan Deadline), we cannot write to multiple DDS endpoints at the same time.
|
||||
This means that we have to temporarily store the payload and push it to each DDS Endpoint individually.
|
||||
|
||||
* Since the DDS Reader is waiting on USER via the 'sample_info_ack' signal before continuing, a singel
|
||||
user can stall all other USERs/Readers (DoS) of a vector entity of the DDS Reader.
|
||||
|
||||
* The DEADLINE check times of the DDS Entities are aligned to the release of the reset, and not on the
|
||||
addition of a new instance. That means that all Instances are checked at the smae time, non depending
|
||||
on when they were added.
|
||||
|
||||
* Because the DATA_AVAILABLE bit of the status of the DDS Reader is reset on first read, the DATA_AVAILABLE
|
||||
bit can be zero even if the DDS Reader still contains unread data. For this reason the ROS entities are
|
||||
showing data_available until the first empty read after the DATA_AVAILABLE bit is set.
|
||||
This has the inverse effect, that even if the DDS Reader has no more data it is showing DATA_AVAILABLE
|
||||
(since a empty read has to be done to reset the bit). This trait has to be taken into account.
|
||||
The ros_action_server, for instance, will for instance remove a goal entering terminal state, if the
|
||||
MAX_GOALS limit is reached
|
||||
|
||||
This has the inverse effect, that even if the DDS Reader has no more data the ROS Entity is showing DATA_AVAILABLE
|
||||
(since an empty read has to be done to reset the bit). This trait has to be taken into account.
|
||||
The ros_action_server, for instance, has to remove a goal in terminal state if the MAX_GOALS limit
|
||||
is reached, and relying solely on the DATA_AVAILABLE signal could unnecessarily trigger a goal removal.
|
||||
|
||||
* It was decided to not follow the ROS Action Server RCL API to the letter, as the ROS Action server is more
|
||||
involved and needs to do extra stuff, that the user should not really be bothered with. Using the provided
|
||||
API as is requires the user to trigger various server functionality and also requires data to be unnecessarily
|
||||
moved out and into the server. (Which makes sense, considering that there should be a RMW layer above this RCL
|
||||
functionality).
|
||||
Therefore a different API is conceptualized for the ROS Action server, that only requires User interaction to the
|
||||
parts that actually matter to the user. That means that all ROS Service interactions are now hidden inside
|
||||
the ROS Action server. The user is only prompted (via high active signals) for user interaction (like accepting
|
||||
a new goal or cancellation request). The user primarily interacts with the server with goal handles, which are
|
||||
the memory addresses of the stored goals in the goal memory. The user can fetch currently stored/accepted goals
|
||||
and modify their state. The user can also directly publish feedback for specific goals. The goal results are
|
||||
stored in an array, which the user directly interacts with (It is the responsibility of the user to store the
|
||||
results in the array before transitioning the goal state to the SUCCEEDED state).
|
||||
|
||||
* According to the ROS "specification" the ROS action server should discard stored goal result based on a
|
||||
configurable timeout period. A timeout period of -1 disables goal result removal (result are kept indefinitely),
|
||||
and a timeout period of 0 removes goal result immediately (after serving any pending result requests).
|
||||
Since we are resource limited, the timeout "option" -1 cannot be implemented as is.
|
||||
Also, since the goal and result memories are linked, we are not storing and removing goal results, but the stored
|
||||
goals themselves.
|
||||
The design decision was made that if the timeout period is set to infinite, the oldest goal is removed if the memory
|
||||
is full and a new goal request comes in.
|
||||
The 0 timeout option is ignored entirely, since it is pointless and provides no benefit at all.
|
||||
|
||||
BRAINSTORMING
|
||||
-------------
|
||||
|
||||
* Add all Participant specific configuration into a generic array (maybe array of record?) and modify the
|
||||
discovery module to be centric to ALL participants. That means that the Participant Memory will
|
||||
contain ALL remortely matched participants (even if they are matched only be 1 local participant).
|
||||
contain ALL remotely matched participants (even if they are matched only be 1 local participant).
|
||||
The discovery module will also need to differentiate between the local participants for replies
|
||||
(Parse RTPPS GUID and set local array index).
|
||||
(Parse RTPS GUID and set local array index).
|
||||
The port interface of the discovery module will not change, meaning that ALL the endpoints of all the
|
||||
local participants will be flattened into one array for communication purposes (Maybe define "static"
|
||||
demangle package function?).
|
||||
|
||||
* Since Publisher and Subscriber Groups are static, we can also generate the GroupDigests statically
|
||||
and avoid having to use a HW MD5 calculator.
|
||||
|
||||
* An important step for later testing automation would be to simulate the hardware implementation with
|
||||
existing software implementations.
|
||||
Currently I do not know how the hardware/software interconnection can work in the simulation level.
|
||||
Can we build a SystemC wrapper around a software implementation and simulate it together with the
|
||||
VHDL implementation? (QuestaSim is allowing mixed language simulations)
|
||||
- Following post (https://discourse.ros.org/t/proposal-for-ros-2-hardware-acceleration-working-group-hawg/20112/22)
|
||||
gave me a different idea. Do the HLS tools simulate PS and PL side together? If so implementing the software
|
||||
implementation on the PS side and communicating to the PL side would implicitly allow to simulate both together.
|
||||
- Wait, I think I am over-complicating stuff. Why do I need to integrate an existing software in its entirety in
|
||||
a simulation capable form? Can I not just implement a SIMULATION-to-UDP bridge similar to the current module
|
||||
sitting in the PS side connecting the FPGA implementation with a software implementation?
|
||||
I guess only timing relevant problems would arise (Timeouts in the sw implementation because the hw implementation
|
||||
takes to long to simulate a response).
|
||||
|
||||
* The DDS Specification differentiates between lost and rejected samples, but does not state what the semantic
|
||||
difference between them is. RTI defines lost samples as dropped samples that will not be NACKed anymore. They
|
||||
even extended the SAMPLE_LOST_STATUS with reasons.
|
||||
My implementation is making a distinction between rejected, lost, and dropped. A sample is Rejected if it is dropped
|
||||
without ACKing, dropped if it is dropped with ACKing, and lost if the DDS Reader never received a Sequence Number
|
||||
(analog to the LOST_BY_WRITER reason of RTI). RTI started mapping rejected samples on BEST_EFFORT communication as
|
||||
lost (since there is no way to request them).
|
||||
I think that lost samples should be only samples that we have never any knowledge about (Probably also what the Spec
|
||||
assumes, since the SAMPLE_LOST_STATUS has not reason). Thus I would not do the mapping, and document that rejected
|
||||
samples can be considered lost if the communication is BEST_EFFORT.
|
||||
On the other hand my implementation currently drops samples without any user feedback, which is quite bad. We should
|
||||
extend the communication statuses with a DROPPED_SAMPLE_STATUS. Also I think it is stupid to only state the reason
|
||||
of the last dropped sample, and we should do a flag variable (similar to the status register) collecting the
|
||||
cumulative reasons, since some reasons are of higher value for the user than others (like dropping a Dispose sample
|
||||
instead of a Filtered sample).
|
||||
REF: https://community.rti.com/kb/statuses-changes
|
||||
REF: https://community.rti.com/static/documentation/connext-dds/5.2.3/doc/manuals/connext_dds/html_files/RTI_ConnextDDS_CoreLibraries_UsersManual/Content/UsersManual/Statuses_for_DataReaders.htm
|
||||
|
||||
* The LivelinessChangedStatus of the DDS Reader requires remote endpoints to not be deleted when they lose liveliness.
|
||||
On the other hand keeping "stale" remote endpoint indefinitely may also not be a good option, so we may want to add
|
||||
a second configurable deadline that removes stale endpoints. We could even use the same liveliness deadline and
|
||||
differentiate between the 2 deadlines with the last bit (similar to how we do it for HEARTBEAT/ACKNACK delay and
|
||||
suppression)
|
||||
|
||||
* If we can find a way to dynamically 'use' a package in testbenches, we could dynamically overload some predefined
|
||||
constants/functions that testbenches use and be Type independent.
|
||||
|
||||
PROTOCOL UNCOMPLIANCE
|
||||
=====================
|
||||
@ -547,13 +712,14 @@ PROTOCOL UNCOMPLIANCE
|
||||
* Coherent Sets Not Supported
|
||||
* Built-in Endpoints (of Discovery Module) is NOT the same as a normal Endpoint
|
||||
-> No User access to Data
|
||||
* Known but unused Submessage IDs are treated as uknown
|
||||
* Known but unused Submessage IDs are treated as unknown
|
||||
-> No validity check
|
||||
* Inline QoS validated in Endpoint
|
||||
-> Cannot invalidate Rest of Message/Packet
|
||||
* RESOURCE_LIMITS applies also to "empty" samples (Samples with no valid data).
|
||||
* Write/Dispose/Untergister Operations do not return (TIMEOUT). I.e. the MAX_BLOCKING_TIME is not used.
|
||||
|
||||
* The Participant Message Data may contain additional data, and according to DDSI-RTPS 2.3 implementations must be able
|
||||
to support up to 128 Bytes of additional data.
|
||||
|
||||
|
||||
RTPS ENDPOINT
|
||||
|
||||
@ -14,7 +14,7 @@ use work.rtps_config_package.all;
|
||||
use work.rtps_test_package.all;
|
||||
use work.Type1_package.all;
|
||||
|
||||
-- This testbench tests the general system operation by interconnecting a complete system with a single writer with a complete sysetm with a single reader.
|
||||
-- This testbench tests the general system operation by interconnecting a complete system with a single writer with a complete system with a single reader.
|
||||
-- Libraries are used to allow to use systems with different configurations. Testbench_Lib2 contains a single endpoint writer (Type1), and Testbench_Lib3 contains a single endpoint reader (Type1).
|
||||
-- Both Libraries have compatible settings for matching.
|
||||
-- The testbench first registers 2 instances, and writes 2 samples for each instance (once using the instance handle, and onc using HANDLE_NIL). This initial 4 writes are done before
|
||||
@ -345,7 +345,7 @@ begin
|
||||
AlertIf(return_code_w /= RETCODE_OK, "DDS Write Operation Failed", ERROR);
|
||||
wait until rising_edge(clk);
|
||||
|
||||
Log("Write Instance 1 Sample 1 (Historical)", INFO);
|
||||
Log("Write Instance 2 Sample 2 (Historical)", INFO);
|
||||
start_w <= '1';
|
||||
opcode_w <= WRITE;
|
||||
source_ts_w <= TIME_INVALID;
|
||||
|
||||
@ -16,9 +16,9 @@ use work.Type1_package.all;
|
||||
|
||||
-- This testbench tests the general system operation by interconnecting two complete systems with a reader and a writer respectively, and perforing a loopback operation.
|
||||
-- Libraries are used to allow to use systems with different configurations.
|
||||
-- The testbench is interfacing with the readr and writer of Testbench_Lib5, and the loopback entity (test_loopback) is interfacing with the reader and writer of Testbench_Lib4.
|
||||
-- The testbench is interfacing with the reader and writer of Testbench_Lib5, and the loopback entity (test_loopback) is interfacing with the reader and writer of Testbench_Lib4.
|
||||
-- The testbench->test_loopback communication uses a Type1 Instance with id=1, and the test_loopback->testbench communication uses a Type1 Instance with id=2.
|
||||
-- The testbench performs a REGISTER_INSTANCE operation to get the Instance Handle of the response channel. The it sends 5 samples with content 1,2,3,4, and 5, respectively.
|
||||
-- The testbench performs a REGISTER_INSTANCE operation to get the Instance Handle of the response channel. Then it sends 5 samples with content 1,2,3,4, and 5, respectively.
|
||||
-- The test_loopback reads these Samples and responds with a x+1000 calculation on the Sample Contents (i.e. 1001,1002,1003,1004,1005).
|
||||
-- The testbench reads only Samples with the correct instance and checks for the expected content.
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ struct Type2 {
|
||||
TestMap_t TestMap;
|
||||
TestEnum_t TestEnum;
|
||||
@optional TestUnion_t TestUnion;
|
||||
TestBitmask_t TestBitmask
|
||||
TestBitmask_t TestBitmask;
|
||||
TestString_t TestString;
|
||||
};
|
||||
|
||||
@ -58,4 +58,4 @@ typedef sequence<NestedStruct_tKeyHolder, 4> TestSequence_tKeyHolder;
|
||||
struct Type2KeyHolder {
|
||||
long id;
|
||||
TestSequence_tKeyHolder TestSequence;
|
||||
};
|
||||
};
|
||||
|
||||
@ -363,7 +363,7 @@ begin
|
||||
-- All Elements processed
|
||||
if (TestSequence_TestArray_cnt = TESTSEQUENCE_TESTARRAY_MAX_DEPTH-1) then
|
||||
-- DES: The decoding stages are used for both PUSH_DATA and PUSH_SERIALIZED_KEY.
|
||||
-- We us the latched opcode to differentiate between them.
|
||||
-- We use the latched opcode to differentiate between them.
|
||||
if (opcode_latch = PUSH_SERIALIZED_KEY) then
|
||||
-- All Elements processed
|
||||
if (TestSequence_cnt = TestSequence_len_latch-1) then
|
||||
@ -853,4 +853,4 @@ begin
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
end architecture;
|
||||
|
||||
@ -10,6 +10,295 @@ use work.rtps_package.all;
|
||||
use work.user_config.all;
|
||||
use work.rtps_config_package.all;
|
||||
|
||||
-- DDS READER
|
||||
-- This Entity is implementing the DDS reader endpoints.
|
||||
-- The entity represents multiple reader endpoints (configurable via the NUM_READERS generic).
|
||||
-- In terms of the RTPS/DDS interaction structure, the HistoryCache (which is the communication point of both the RTPS
|
||||
-- and DDS endpoints) is integrated into the DDS endpoints, because the DDS endpoints need to perform modifying memory
|
||||
-- operations, and storing everything twice is a waste of resources.
|
||||
-- This entity has 3 memories: an instance memory, a sample memory, and a payload memory.
|
||||
-- The instance memory contains instances (samples with the same key and topic form an instance) of received samples.
|
||||
-- The sample memory contains the sample(CacheChange) "meta" data, and the payload memory contains the respective data
|
||||
-- of the samples (if available).
|
||||
-- This entity receives operations from both the RTPS endpoint, and the downstream user endpoints using a start/done
|
||||
-- schema.
|
||||
|
||||
-- The allowed RTPS operations are ADD_CACHE_CHANGE, and REMOVE_WRITER. See below for the data input formats.
|
||||
-- If the data of the ADD_CACHE_CHANGE does not include a Key Hash it has to be calculated manually. For this reason
|
||||
-- a KEY HOLDER is instantiated for each reader, which is fed the payload/serialized key and calculates the Key Hash.
|
||||
-- Because this has to be done before we can make an ACCEPT/REJECT decision for the sample, the sample and its possible
|
||||
-- associated payload has to be temporarily buffered. This is solved by extending both the sample memory and payload
|
||||
-- memory by one slot, that is not counted towards the RESOURCE_LIMITS QoS.
|
||||
-- If the Key Hash of the ADD_CACHE_CHANGE is of an unknown instance, a new instance is added in the instance memory.
|
||||
-- The instance is added in numerical Key Hash order to the instance memory, in order to support some specific DDS
|
||||
-- operations (see READ_NEXT_INSTANCE and TAKE_NEXT_INSTANCE below).
|
||||
-- If the instance memory is full, the first stale instance is removed to make space for the new instance. An instance
|
||||
-- is stale if the sample memory has no samples associated with the instance, and no writer is currently associated
|
||||
-- with the instance (REMOVE_WRITER was called for all writers known to write this instance). If no stale instance is
|
||||
-- available, the ADD_CACHE_CHANGE operation is rejected.
|
||||
-- CacheChanges are inserted into the Sample memory in receive order (ADD_CACHE_CHANGE order), except if the
|
||||
-- DESTINATION_ORDER QoS is set to BY_SOURCE_TIMESTAMP, in which case they are inserted based on their timestamp.
|
||||
-- Note that in the case of BY_SOURCE_TIMESTAMP DESTINATION_ORDER QoS, no CacheChange with a timestamp earlier than the
|
||||
-- last read sample is accepted.
|
||||
-- Even though the meta-information stored in the sample memory is always the same size, the same can not be said for the
|
||||
-- payload, which can have (depending on the associated IDL type) a more dynamic size. Despite that, the payload memory
|
||||
-- also works with fixed-size slots. If a payload is bigger it just occupies multiple linked memory slots. If the end
|
||||
-- of the payload is not aligned with the end of the memory slot (which is always known due to the fixed-size nature), the
|
||||
-- end address of the payload is stored in the end of the memory slot. This dynamic nature of the payload arises the
|
||||
-- situation, that during an ADD_CACHE_CHANGE operation a sample memory slot is available, but all payload memory slots
|
||||
-- are occupied. In this situation (depending on the configured QoS) either the operation is directly rejected, or the
|
||||
-- oldest sample is removed from the memories. Note that since the oldest sample may have no associated payload,
|
||||
-- multiple sample removals may be triggered. Also note that this happens also when the sample to be added has no
|
||||
-- associated payload, since we cannot know this in advance. On the other hand, because this action is preliminary and
|
||||
-- before the actual decision based on the sample to be added (which again may reject the operation or remove a specific
|
||||
-- sample), a situation may arise were a single ADD_CACHE_CHANGE operation may trigger multiple sample removals
|
||||
-- (one/multiple to make space for the payload, and one based on the sample to be added, like maximum number of samples
|
||||
-- per instance).
|
||||
-- CacheChanges without associated payload are only stored, if the sample causes an instance state change (Between
|
||||
-- ALIVE, NOT_ALIVE_NO_WRITERS, NOT_ALIVE_DISPOSED). An instance state change to the NOT_ALIVE_NO_WRITERS instance state
|
||||
-- (meaning that no writer is writing this instance anymore) can also occur without receiving a CacheChange (e.g. Due
|
||||
-- to the last writer failing to assert his liveliness). For this special instance state transition a sample is
|
||||
-- generated for the respective instance.
|
||||
-- The REMOVE_WRITER operation removes the specified writer form all currently stored instances, and is used to track
|
||||
-- stale instances (see above).
|
||||
-- To start an operation the 'start' signal is asserted with the respective opcode in 'opcode' and waits until the
|
||||
-- operation is acknowledged by asserting the 'ack' signal. The REMOVE_WRITER operation needs to also transfer a single
|
||||
-- word of data for the operation (see below for Format), which has to be on the 'data' signal while the 'start' signal
|
||||
-- is asserted. The ADD_CACHE_CHANGE operation also needs a data transfer, but uses a valid/ready schema for the
|
||||
-- transfer. The 'valid' signal is asserted whenever the data signal contains valid data, and if the 'ready' signal is
|
||||
-- asserted, the data is considered latched by the recipient. An asserted 'last_word' signal marks the last word of the
|
||||
-- transaction. After the operation is completed, the 'done' signal is asserted for one clock cycle, and the return
|
||||
-- status can be found in the 'ret' signal on the same clock cycle.
|
||||
|
||||
-- The allowed DDS (user) operations are READ, TAKE, READ_NEXT_SAMPLE, TAKE_NEXT_SAMPLE, READ_INSTANCE, TAKE_INSTANCE,
|
||||
-- READ_NEXT_INSTANCE, TAKE_NEXT_INSTANCE, GET_SAMPLE_REJECTED_STATUS, and GET_REQUESTED_DEADLINE_MISSED_STATUS.
|
||||
-- The description of the operations, their inputs, and outputs can be taken directly from the DDS specification.
|
||||
-- Similar to the RTPS operations, the 'start' signal is asserted with the respective opcode in 'opcode' to start an
|
||||
-- operation until the 'ack' signal is asserted, and an asserted 'done' signal signifies the end of the operation with
|
||||
-- the return status found in the 'return_code' signal on the same clock cycle. The READ and TAKE operation also need
|
||||
-- valid 'sample_state', 'view_state', 'instance_state', and 'max_samples' signals while the 'start' signal is asserted,
|
||||
-- whereas the READ_INSTANCE, TAKE_INSTANCE, READ_NEXT_INSTANCE, and TAKE_NEXT_INSTANCE operations need in addition to
|
||||
-- those signals also a valid 'instance_handle' signal. After completion ('done' signal asserted), the GET_* operations
|
||||
-- initiate a data transfer (using valid/ready schema like for the RTPS operations) for the requested data (see below
|
||||
-- for output format). All READ_* and TAKE_* operations will return at least one sample info after the operation is
|
||||
-- completed ('done' signal asserted) and the return code is "RETCODE_OK". All the 'sample_info.*' signals are valid
|
||||
-- when the 'sample_info_valid' signal is asserted. The 'sample_info.*' signals stay valid until the 'sample_info_ack'
|
||||
-- signal is asserted. If the sample has associated data ('sample_info.valid_data' asserted), the data can be requested
|
||||
-- by asserting the 'get_data' signal on the same clock cycle the 'sample_info_ack' signal is asserted. In this case a
|
||||
-- data transfer (using a valid/ready schema like for the RTPS operations) is initiated. If no more samples are to be
|
||||
-- returned, the 'eoc' (End Of Collection) signal is asserted for one clock cycle, signifying the end of the operation.
|
||||
|
||||
-- NOTE: Dispose and Unregister CacheChanges are dropped if BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS is used and a
|
||||
-- newer Sample of the same Instance exists. (This is done to keep a consistent history)
|
||||
|
||||
-- ADD_CACHE_CHANGE DATA FORMAT
|
||||
-- ============================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| STATUS_INFO |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + TIMESTAMP +
|
||||
-- 03| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 04| |
|
||||
-- + LIFESPAN_DEADLINE +
|
||||
-- 05| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 06| |
|
||||
-- + +
|
||||
-- 07| |
|
||||
-- + KEY_HASH [only if K=1] +
|
||||
-- 08| |
|
||||
-- + +
|
||||
-- 09| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 10| WRITER_ID |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 11| |
|
||||
-- ~ PAYLOAD [only if P=1 or P=K=0] ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
--
|
||||
-- STATUS INFO
|
||||
-- -----------
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +-+-+-+-+-------------------------------------------------+-+-+-+
|
||||
-- | |P| |K| UNUSED |F|U|D|
|
||||
-- +-+-+-+-+-------------------------------------------------+-+-+-+
|
||||
-- P...Sample has associated DATA Payload
|
||||
-- K...Key Hash available
|
||||
-- F...FilteredFlag (1:1 PID_STATUS_INFO Mapping)
|
||||
-- U...UnregisteredFlag (1:1 PID_STATUS_INFO Mapping)
|
||||
-- D...DisposedFlag (1:1 PID_STATUS_INFO Mapping)
|
||||
-- NOTE: If P=0 and K=0, the Payload contains the Serialized Key
|
||||
|
||||
-- REMOVE_WRITER DATA FORMAT
|
||||
-- =========================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| WRITER_ID |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- GET_SAMPLE_REJECTED_STATUS DATA FORMAT
|
||||
-- ======================================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| TOTAL_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| TOTAL_COUNT_CHANGE |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 03| LAST_REASON |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 04| |
|
||||
-- + +
|
||||
-- 05| |
|
||||
-- + LAST_INSTANCE_HANDLE +
|
||||
-- 06| |
|
||||
-- + +
|
||||
-- 07| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- GET_REQUESTED_DEADLINE_MISSED_STATUS DATA FORMAT
|
||||
-- ================================================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| TOTAL_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| TOTAL_COUNT_CHANGE |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 03| |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- + LAST_INSTANCE_HANDLE +
|
||||
-- 05| |
|
||||
-- + +
|
||||
-- 06| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- MEMORY LAYOUT
|
||||
-- This entity is using double linked lists of fixed-size memory frames for the sample and instance memories, while
|
||||
-- using single linked list for the payload memory.
|
||||
-- 2 lists of frames are kept for the sample and instance memories, one for the empty frames, and one for the occupied
|
||||
-- frames, whereas only one list for the empty frames is kept for the payload memory.
|
||||
-- The memory frames have following structure:
|
||||
-- SAMPLE DATA MEMORY FORMAT
|
||||
-- =========================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| STATUS_INFO |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + TIMESTAMP +
|
||||
-- 03| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 04| |
|
||||
-- + LIFESPAN_DEADLINE +
|
||||
-- 05| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 06| PAYLOAD_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 07| INSTANCE_ADDRESS [only if WITH_KEY] |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 08| DISPOSED_GENERATION_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 09| NO_WRITERS_GENERATION_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 10| PREV_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 11| NEXT_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
--
|
||||
-- STATUS INFO
|
||||
-- -----------
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +-+-+-+---------------------------------------------------+-+-+-+
|
||||
-- |R|P|A| UNUSED |F|U|D|
|
||||
-- +-+-+-+---------------------------------------------------+-+-+-+
|
||||
-- R...Sample has been Read
|
||||
-- P...Sample has associated DATA Payload
|
||||
-- A...Associated Payload is aligned (Payload does extend until end of last Payload Slot)
|
||||
-- F...FilteredFlag (1:1 PID_STATUS_INFO Mapping)
|
||||
-- U...UnregisteredFlag (1:1 PID_STATUS_INFO Mapping)
|
||||
-- D...DisposedFlag (1:1 PID_STATUS_INFO Mapping)
|
||||
|
||||
-- INSTANCE DATA MEMORY FORMAT
|
||||
-- ===========================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| NEXT_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| PREV_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 03| |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- + KEY_HASH +
|
||||
-- 05| |
|
||||
-- + +
|
||||
-- 06| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 07| STATUS_INFO |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 08| SAMPLE_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 09| DISPOSED_GENERATION_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 10| NO_WRITERS_GENERATION_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 11| |
|
||||
-- + IGNORE_DEADLINE +
|
||||
-- 12| [only if TIME_BASED_FILTER /= 0] |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 13| |
|
||||
-- ~ WRITER_BITMAP ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
--
|
||||
-- STATUS INFO
|
||||
-- -----------
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------+-+-+-+-+-+-+
|
||||
-- | UNUSED |G|M|V|L|W|D|
|
||||
-- +---------------------------------------------------+-+-+-+-+-+-+
|
||||
-- D...NOT_ALIVE_DISPOSED
|
||||
-- W...NOT_ALIVE_NO_WRITERS
|
||||
-- L...LIVELINESS FLAG
|
||||
-- V...VIEW STATE
|
||||
-- M...MARK
|
||||
-- G...GENERATE SAMPLE
|
||||
|
||||
-- PAYLOAD DATA MEMORY FORMAT
|
||||
-- ==========================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| NEXT_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- ~ PAYLOAD ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
entity dds_reader is
|
||||
generic (
|
||||
NUM_READERS : natural;
|
||||
@ -900,7 +1189,7 @@ begin
|
||||
|
||||
-- *Main State Machine*
|
||||
-- STATE DESCRIPTION
|
||||
-- IDLE Idle State. Initiates Deadline Miss Checks, Lifespan Expiry Checks, RTPS Operation handling, and DDS Operation handling, in that priority order.
|
||||
-- IDLE Idle State. Initiates Deadline Miss Checks, Lifespan Expiry Checks, Instance State Sample Generation, RTPS Operation handling, Instance unmarking, and DDS Operation handling, in that priority order.
|
||||
-- RETURN_DDS Return latched DDS Return Code
|
||||
-- RETURN_RTPS Return latched RTPS Return Code
|
||||
-- ADD_SAMPLE_INFO Latch and store Cache Change (pre-payload)
|
||||
@ -921,15 +1210,11 @@ begin
|
||||
-- FIND_OLDEST_INST_SAMPLE Find the oldest sample of a specific Instance
|
||||
-- REMOVE_SAMPLE Remove sample and linked payload
|
||||
-- POST_SAMPLE_REMOVE Update Instance Data of removed sample. If Instance Memory is full, and Instance is now eligible for removal, it is removed.
|
||||
-- SKIP_AND_RETURN Skip DDS Input and return latched Return Code
|
||||
-- SKIP_AND_RETURN Skip RTPS Input and return latched Return Code
|
||||
-- REMOVE_WRITER Unmark specified Writer Bitmap Position from all stored Instances. (Also updates Instance Data if necessary)
|
||||
-- REMOVE_STALE_INSTANCE Find and remove the first eligible Instance in the memory
|
||||
-- GET_NEXT_SAMPLE Find the next sample in the requested collection
|
||||
-- PRE_CALCULATE Calculate ranks for the selected sample in the requested collection.
|
||||
-- FINALIZE_SAMPLE_INFO Finalize the Sample Info Data, and present them.
|
||||
-- WAIT_READ Synchronisation state between main and read FSM. Waits until read/take operation is complete and triggers sample removal and payload fetch.
|
||||
-- GET_PAYLOAD Push linked Payload to output
|
||||
-- FIND_NEXT_INSTANCE Find next Instance that passes requested masks
|
||||
-- CHECK_INSTANCE Check if selected Instance passes requested masks
|
||||
-- CHECK_LIFESPAN Check and remove samples with expired Lifespans
|
||||
-- PROCESS_PENDING_SAMPLE_GENERATION Iterate through the Instances and Generate Samples where required (A Sample is generated for NOT_ALIVE_NO_WRITERS transitions)
|
||||
-- GET_SAMPLE_REJECTED_STATUS Return Sample Rejected Status
|
||||
@ -1103,8 +1388,6 @@ begin
|
||||
sample_rej_last_inst_next(ind) <= HANDLE_NIL;
|
||||
else
|
||||
assert (oldest_sample(ind) /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
|
||||
-- Do not ACK Operation
|
||||
ack_dds(ind) <= '0';
|
||||
|
||||
remove_oldest_sample_next <= '1';
|
||||
stage_next <= GET_OLDEST_SAMPLE_INSTANCE;
|
||||
@ -1443,7 +1726,7 @@ begin
|
||||
-- has_data has_key_hash
|
||||
-- 1 1 The payload is written to memory
|
||||
-- 1 0 The payload is written to memory and the KHG at the same time (KHG controls the flow)
|
||||
-- 0 0 There is no payload to write, but the input contains the key for the KHG
|
||||
-- 0 0 There is no payload to write, but the input contains the serialized key for the KHG
|
||||
|
||||
case (cnt) is
|
||||
-- Push to memory
|
||||
@ -1589,7 +1872,7 @@ begin
|
||||
when 0 =>
|
||||
sample_valid_in1 <= '1';
|
||||
sample_addr1 <= cur_sample + SMF_STATUS_INFO_OFFSET;
|
||||
sample_write_data1 <= sample_status_info;
|
||||
sample_write_data1 <= sample_status_info; -- TODO: This overwrites the removed flags
|
||||
sample_write_data1(SSI_ALIGNED_FLAG) <= '0';
|
||||
|
||||
-- Memory Control Flow Guard
|
||||
@ -2133,7 +2416,7 @@ begin
|
||||
tmp_bitmap := from_writer_bitmap_array(inst_data.writer_bitmap);
|
||||
-- ALIVE/FILTERED/DISPOSE Operation
|
||||
if (sample_status_info(SSI_UNREGISTERED_FLAG) /= '1') then
|
||||
-- Write if Writer New for Instance
|
||||
-- Insert if Writer New for Instance
|
||||
if (tmp_bitmap(writer_id) /= '1') then
|
||||
-- Insert Writer
|
||||
tmp_bitmap(writer_id) := '1';
|
||||
@ -2142,9 +2425,9 @@ begin
|
||||
tmp_update := tmp_update or IMF_WRITER_BITMAP_FLAG;
|
||||
end if;
|
||||
else
|
||||
-- Write if Writer New for Instance
|
||||
-- Writer previously inserted
|
||||
if (tmp_bitmap(writer_id) /= '0') then
|
||||
-- Insert Writer
|
||||
-- Remove Writer
|
||||
tmp_bitmap(writer_id) := '0';
|
||||
-- Convert Back
|
||||
inst_r1.writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
|
||||
@ -2174,7 +2457,7 @@ begin
|
||||
-- NOT_ALIVE_DISPOSED -> NOT_ALIVE_DISPOSED
|
||||
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1') then
|
||||
tmp_bool := FALSE;
|
||||
-- Only Update Instance State if Sample if newest
|
||||
-- Only Update Instance State if Sample is newest
|
||||
elsif (newer_inst_sample = '0') then
|
||||
inst_r1.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '1';
|
||||
inst_r1.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
|
||||
@ -2199,7 +2482,7 @@ begin
|
||||
else
|
||||
assert (has_data = '1') severity FAILURE;
|
||||
end if;
|
||||
-- Only Update Instance State if Sample if newest
|
||||
-- Only Update Instance State if Sample is newest
|
||||
elsif (newer_inst_sample = '0') then
|
||||
inst_r1.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0';
|
||||
inst_r1.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
|
||||
@ -3895,6 +4178,17 @@ begin
|
||||
end case;
|
||||
end process;
|
||||
|
||||
-- *Main State Machine*
|
||||
-- STATE DESCRIPTION
|
||||
-- IDLE Idle State. Synchronization state between main and read FSM. Waits until main FSM triggers a read/take operation.
|
||||
-- GET_NEXT_SAMPLE Find the next sample in the requested collection
|
||||
-- PRE_CALCULATE Calculate ranks for the selected sample in the requested collection.
|
||||
-- FINALIZE_SAMPLE_INFO Finalize the Sample Info Data, and present them.
|
||||
-- FIND_NEXT_INSTANCE Find next Instance that passes requested masks
|
||||
-- CHECK_INSTANCE Check if selected Instance passes requested masks
|
||||
-- WAIT_PAYLOAD Synchronization state between main and read FSM. Waits until main FSM finishes payload transfer.
|
||||
-- WAIT_REMOVE Synchronization state between main and read FSM. Waits until main FSM finishes sample removal.
|
||||
-- DONE Signal end of operation to main FSM.
|
||||
read_prc : process (all)
|
||||
variable tmp_bool : boolean;
|
||||
alias sample_p1 : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_4;
|
||||
|
||||
@ -10,6 +10,217 @@ use work.rtps_package.all;
|
||||
use work.user_config.all;
|
||||
use work.rtps_config_package.all;
|
||||
|
||||
-- DDS WRITER
|
||||
-- This Entity is implementing the DDS writer endpoints.
|
||||
-- The entity represents multiple writer endpoints (configurable via the NUM_WRITERS generic).
|
||||
-- Similar to the DDS reader the HistoryCache is integrated into the DDS writer.
|
||||
-- This entity has 3 memories: an instance memory, a sample memory, and a payload memory.
|
||||
-- The instance memory contains instances (samples with the same key and topic form an instance) of received samples.
|
||||
-- The sample memory contains the sample(CacheChange) "meta" data, and the payload memory contains the respective data
|
||||
-- of the samples (if available).
|
||||
-- This entity receives operations from both the RTPS endpoint, and the downstream user endpoints using a start/done
|
||||
-- schema.
|
||||
|
||||
-- The allowed RTPS operations are GET_CACHE_CHANGE, ACK_CACHE_CHANGE, NACK_CACHE_CHANGE, REMOVE_CACHE_CHANGE,
|
||||
-- GET_MIN_SN, GET_MAX_SN. See below for the data input formats.
|
||||
-- The GET_CACHE_CHANGE operation returns the requested CacheChange (All 'cc_*' signals are valid) based on the provided
|
||||
-- SequenceNumber, whereas the REMOVE_CACHE_CHANGE operation removes the CacheChange from memory. The ACK_CACHE_CHANGE
|
||||
-- operation marks the CacheChange based on the provided SequenceNumber as acknowledged, whereas the NACK_CACHE_CHANGE
|
||||
-- marks the CacheChange as not acknowledged. The GET_MIN_SN returns (in the 'cc_seq_nr' signal) the SequenceNumber of
|
||||
-- the oldest sample in the sample memory (list tail), whereas the GET_MAX_SN returns the SequenceNumber of the newest
|
||||
-- sample in the sample memory (list head).
|
||||
-- To start an operation the 'start' signal is asserted with the respective opcode in 'opcode' and waits until the
|
||||
-- operation is acknowledged by asserting the 'ack' signal. All operations except GET_MIN_SN and GET_MAX_SN need to also
|
||||
-- set the 'seq_nr_hc' along with the 'start_hc' signal (Denotes the SN for which the operation is relevant). After the
|
||||
-- operation is completed, the 'done' signal is asserted for one clock cycle, and the return status can be found in the
|
||||
-- 'ret' signal on the same clock cycle. On a GET_CACHE_CHANGE operation if the CacheChange also has data (determinable
|
||||
-- from the CacheChange kind), it can be requested by asserting the 'get_data_hc' signal on the same clock cycle the
|
||||
-- 'done' signal is asserted. Asserting 'get_data_hc' on a CacheChange with no data is silently ignored. The requested
|
||||
-- data is transferred using a valid/ready schema. The 'valid' signal is asserted whenever the data signal contains
|
||||
-- valid data, and if the 'ready' signal is asserted, the data is considered latched by the recipient. An asserted
|
||||
-- 'last_word' signal marks the last word of the transaction. The transferred data is the payload of the DATA RTPS
|
||||
-- Submessage. From the point the operation is done ('done' signal asserted) until the acknowledgement of the next
|
||||
-- operation ('ack' asserted), the 'cc_*' signals are valid and contain information on the CacheChange for the GET_*
|
||||
-- operations.
|
||||
|
||||
-- The allowed DDS (user) operations are REGISTER_INSTANCE, WRITE, DISPOSE, UNREGISTER_INSTANCE, LOOKUP_INSTANCE,
|
||||
-- WAIT_FOR_ACKNOWLEDGEMENTS, GET_OFFERED_DEADLINE_MISSED_STATUS, ASSERT_LIVELINESS, GET_LIVELINESS_LOST_STATUS.
|
||||
-- The description of the operations, their inputs, and outputs can be taken directly from the DDS specification.
|
||||
-- Instances are added to the instance memory either directly through the REGISTER_INSTANCE operation, or indirectly
|
||||
-- through the WRITE operation with an HANDLE_NIL instance handle. For this reason a KEY HOLDER is instantiated for
|
||||
-- each DDS Writer, which is fed the payload and calculates the Key Hash of the instance. If the instance memory is
|
||||
-- full, the first stale instance is removed to make space for the new instance. An instance is stale if all the
|
||||
-- associated samples in the sample memory are acknowledged and the instance state is UNREGISTERED. If no stale instance
|
||||
-- is available, the operations are rejected.
|
||||
-- Samples are added with the WRITE, DISPOSE, and UNREGISTER_INSTANCE operations.
|
||||
-- Because these operations can be called with instance handle HANDLE_NIL, which means that the instance handle has to
|
||||
-- be calculated from the provided data before the ACCEPT/REJECT decision for the sample can be made, the sample and
|
||||
-- its associated payload has to be temporarily buffered. This is solved by extending both the sample memory and payload
|
||||
-- memory by one slot, that is not counted towards the RESOURCE_LIMITS QoS.
|
||||
-- Even though the meta-information stored in the sample memory is always the same size, the same can not be said for the
|
||||
-- payload, which can have (depending on the associated IDL type) a more dynamic size. Despite that, the payload memory
|
||||
-- also works with fixed-size slots. If a payload is bigger it just occupies multiple linked memory slots. If the end
|
||||
-- of the payload is not aligned with the end of the memory slot (which is always know due to the fixed-size nature), the
|
||||
-- end address of the payload is stored in the end of the memory slot. This dynamic nature of the payload arises the
|
||||
-- situation, that during a WRITE operation a sample memory slot is available, but all payload memory slots are
|
||||
-- occupied. In this situation (depending on the configured QoS) either the operation is directly rejected, or the
|
||||
-- oldest (ACKed) sample is removed from the memories. Note that since the oldest sample may have no associated payload,
|
||||
-- multiple sample removals may be triggered. Also note that this happens also when the sample to be added has no
|
||||
-- associated payload, since we cannot know this in advance. On the other hand, because this action is preliminary and
|
||||
-- before the actual decision based on the sample to be added (which again may reject the operation or remove a specific
|
||||
-- sample), a situation may arise were a single DDS operation may trigger multiple sample removals (one/multiple to make
|
||||
-- space for the payload, and one based on the sample to be added, like maximum number of samples per instance).
|
||||
-- Similar to the RTPS operations, the 'start' signal is asserted with the respective opcode in 'opcode' to start an
|
||||
-- operation until the 'ack' signal is asserted, and an asserted 'done' signal signifies the end of the operation with
|
||||
-- the return status found in the 'return_code' signal on the same clock cycle. The WRITE, DISPOSE, and
|
||||
-- UNREGISTER_INSTANCE operations also expect valid 'instance_handle_in' and 'source_ts' signals, whereas the
|
||||
-- WAIT_FOR_ACKNOWLEDGEMENTS operation expects a valid 'max_wait' signal (while the 'start' signal is asserted).
|
||||
-- The WRITE, DISPOSE, UNREGISTER_INSTANCE, REGISTER_INSTANCE, and LOOKUP_INSTANCE operation are followed by a data
|
||||
-- transfer of the actual sample payload (using the valid/ready schema) after the acknowledgment of the operations
|
||||
-- ('ack' signal asserted). After completion ('done' signal asserted), the GET_* operations initiate a data transfer
|
||||
-- (using valid/ready schema like for the RTPS operations) for the requested data (see below for output format).
|
||||
|
||||
-- NOTE: The DISPOSE and UNREGISTER_INSTANCE DDS operations, unlike in the DDS specification, always need the sample
|
||||
-- data to be provided, not depending on if the provided instance_handle is HANDLE_NIL.
|
||||
-- NOTE: The 'max_wait' signal is only used for the WAIT_FOR_ACKNOWLEDGEMENTS operation. All other operations reject
|
||||
-- without delay.
|
||||
-- NOTE: This entity makes no special distinction on the configured RELIABILITY QoS, and thus depends on the RTPS
|
||||
-- Writer to also ACK CacheChanges when BEST_EFFORT RELIABILITY is used.
|
||||
-- NOTE: One could argue that the sample memory does not actually contain DDS samples, but RTPS CacheChanges.
|
||||
|
||||
|
||||
-- GET_OFFERED_DEADLINE_MISSED_STATUS DATA FORMAT
|
||||
-- ==============================================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| TOTAL_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| TOTAL_COUNT_CHANGE |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 03| |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- + LAST_INSTANCE_HANDLE +
|
||||
-- 05| |
|
||||
-- + +
|
||||
-- 06| |
|
||||
-- +---------------------------------------------------------------+
|
||||
--
|
||||
-- GET_LIVELINESS_LOST_STATUS DATA FORMAT
|
||||
-- ======================================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| TOTAL_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| TOTAL_COUNT_CHANGE |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
|
||||
-- MEMORY LAYOUT
|
||||
-- This entity is using double linked lists of fixed-size memory frames for the sample and instance memories, while
|
||||
-- using single linked list for the payload memory.
|
||||
-- 2 lists of frames are kept for the sample and instance memories, one for the empty frames, and one for the occupied
|
||||
-- frames, whereas only one list for the empty frames is kept for the payload memory.
|
||||
-- The memory frames have following structure:
|
||||
|
||||
-- SAMPLE DATA MEMORY FORMAT
|
||||
-- =========================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| STATUS_INFO |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + SEQ_NR +
|
||||
-- 03| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 04| |
|
||||
-- + TIMESTAMP +
|
||||
-- 05| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 06| |
|
||||
-- + LIFESPAN_DEADLINE +
|
||||
-- 07| [only if LIFESPAN /= INFINITE] |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 08| PAYLOAD_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 09| INSTANCE_ADDRESS [only if WITH_KEY] |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 10| PREV_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 11| NEXT_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- STATUS INFO
|
||||
-- -----------
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +-+-+-+---------------------------------------------------+-+-+-+
|
||||
-- |R|P|A| UNUSED |F|U|D|
|
||||
-- +-+-+-+---------------------------------------------------+-+-+-+
|
||||
-- R...Sample has been ACKed
|
||||
-- P...Sample has associated DATA Payload
|
||||
-- A...Associated Payload is aligned (Payload does extend until end of last Palyload Slot)
|
||||
-- F...FilteredFlag (1:1 PID_STATUS_INFO Mapping)
|
||||
-- U...UnregisteredFlag (1:1 PID_STATUS_INFO Mapping)
|
||||
-- D...DisposedFlag (1:1 PID_STATUS_INFO Mapping)
|
||||
|
||||
-- INSTANCE DATA MEMORY FORMAT
|
||||
-- ===========================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| NEXT_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| PREV_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 03| |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- + KEY_HASH +
|
||||
-- 05| |
|
||||
-- + +
|
||||
-- 06| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 07| STATUS_INFO |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 08| SAMPLE_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 09| ACK_COUNT |
|
||||
-- +---------------------------------------------------------------+
|
||||
--
|
||||
-- STATUS INFO
|
||||
-- -----------
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------+-+-+-+
|
||||
-- | UNUSED |L|U|D|
|
||||
-- +---------------------------------------------------------+-+-+-+
|
||||
-- D...DISPOSED
|
||||
-- W...UNREGISTERED
|
||||
-- L...LIVELINESS FLAG
|
||||
|
||||
-- PAYLOAD DATA MEMORY FORMAT
|
||||
-- ==========================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| NEXT_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- ~ PAYLOAD ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
entity dds_writer is
|
||||
generic (
|
||||
NUM_WRITERS : natural;
|
||||
@ -488,7 +699,7 @@ architecture arch of dds_writer is
|
||||
signal register_op, register_op_next : std_logic;
|
||||
-- Signifies if a Instance Lookup Operation is in progress
|
||||
signal lookup_op, lookup_op_next : std_logic;
|
||||
-- Signifies if a WAIT_FOR_ACKNOWLEDGEMENT Operation is in progress
|
||||
-- Signifies if a WAIT_FOR_ACKNOWLEDGEMENTS Operation is in progress
|
||||
signal ack_wait, ack_wait_next : std_logic_vector(0 to NUM_WRITERS-1);
|
||||
-- Triggers an ACK Wait Check
|
||||
signal ack_wait_check, ack_wait_check_next : std_logic;
|
||||
@ -770,7 +981,7 @@ begin
|
||||
|
||||
-- *Main State Machine*
|
||||
-- STATE DESCRIPTION
|
||||
-- IDLE Idle State. Initiates Deadline Miss Checks, Lifespan Expiry Checks, RTPS Operation handling, and DDS Operation handling, in that priority order.
|
||||
-- IDLE Idle State. Initiates Orphan Sample Check, Deadline Miss Checks, Liveliness Deadline Check, Lifespan Expiry Checks, RTPS Operation handling, and DDS Operation handling, in that priority order.
|
||||
-- UNKNOWN_OPERATION_DDS Dummy State for not supported/unknown DDS Operations
|
||||
-- UNKNOWN_OPERATION_RTPS Dummy State for not supported/unknown RTPS Operations
|
||||
-- UNKNOWN_SEQ_NR Dummy State for RTPS Operation with unknown Sequence Number
|
||||
@ -785,10 +996,10 @@ begin
|
||||
-- LOOKUP_OPERATION Check Instance lookup results and return special value in case Instance was not found.
|
||||
-- PUSH_KEY_HASH Push stored Instance Handle/Key hash to DDS output
|
||||
-- FILTER_STAGE This state decides if the Cache Change is accepted, or rejected. It also decides what sample (if any) has to be removed.
|
||||
-- UPDATE_INSTANCE Update the Data of the Instance of the received saample (Cache Change)
|
||||
-- UPDATE_INSTANCE Update the Data of the Instance of the received sample (Cache Change)
|
||||
-- FINALIZE_PAYLOAD Finalize the payload addition (Update pointers).
|
||||
-- FINALIZE_SAMPLE Update inserted sample and list pointers. (Second Step of Sample Addition Finalization)
|
||||
-- GET_OLDEST_SAMPLE_INSTANCE Fetch the Instance Data of the oldest sample
|
||||
-- GET_OLDEST_SAMPLE_INSTANCE Fetch the Instance Data of the oldest sample. This is a sample pre-remove stage.
|
||||
-- FIND_SAMPLE Find the specified Sample (Oldest ACKed Sample, Oldest Sample of specific Instance, Oldest ACKed Sample of specific Instance)
|
||||
-- REMOVE_ORPHAN_SAMPLES Remove all Samples of the removed Instance (dead_inst)
|
||||
-- REMOVE_SAMPLE Remove sample and linked payload
|
||||
@ -798,7 +1009,7 @@ begin
|
||||
-- REMOVE_STALE_INSTANCE Find and remove the first eligible Instance in the memory
|
||||
-- GET_SEQ_NR Push Sequence Number of specified Sample to RTPS output.
|
||||
-- FIND_SEQ_NR Find Sample with specified Sequence Number.
|
||||
-- ACKNACK_SAMPLE Acknowledge/Unacknowledge specied Sample
|
||||
-- ACKNACK_SAMPLE Acknowledge/Unacknowledged specified Sample
|
||||
-- GET_SAMPLE Push Sample Data to RTPS output
|
||||
-- GET_PAYLOAD Push linked Payload to output, or to the serialized key generator
|
||||
-- CHECK_LIFESPAN Check and remove samples with expired Lifespans
|
||||
@ -806,7 +1017,7 @@ begin
|
||||
-- GET_OFFERED_DEADLINE_MISSED_STATUS Return Offered Deadline Missed Status
|
||||
-- CHECK_DEADLINE Check and Mark Instances with missed Deadlines
|
||||
-- CHECK_LIVELINESS Check liveliness status of all Writers
|
||||
-- CHECK_ACK_WAIT Check WAIT_FOR_ACKNOWLEDGEMENT operation exit conditions
|
||||
-- CHECK_ACK_WAIT Check WAIT_FOR_ACKNOWLEDGEMENTS operation exit conditions
|
||||
-- RESET_SAMPLE_MEMORY Reset Sample Memory to Empty State
|
||||
-- RESET_PAYLOAD_MEMORY Reset Payload Memory to Empty State
|
||||
parse_a_prc : process (all)
|
||||
@ -953,7 +1164,7 @@ begin
|
||||
ind_next <= 0;
|
||||
stage_next <= CHECK_LIVELINESS;
|
||||
cnt_next <= 1; -- CHECK LEASE
|
||||
-- WAIT_FOR_ACKNOWLEDGEMENT Trigger
|
||||
-- WAIT_FOR_ACKNOWLEDGEMENTS Trigger
|
||||
elsif (ack_wait /= (ack_wait'range => '0') and (ack_wait_check = '1' or timeout_check_time <= time)) then
|
||||
ind_next <= 0;
|
||||
|
||||
@ -1031,7 +1242,7 @@ begin
|
||||
end if;
|
||||
when ACK_CACHE_CHANGE =>
|
||||
ack_rtps(ind) <= '1';
|
||||
is_ack_next <= '1';
|
||||
is_ack_next <= '1';
|
||||
|
||||
-- No Samples Available
|
||||
if (newest_sample(ind) = SAMPLE_MEMORY_MAX_ADDRESS) then
|
||||
@ -1175,7 +1386,7 @@ begin
|
||||
sample_status_info_next <= (SSI_DATA_FLAG => '1', SSI_ALIGNED_FLAG => '1', SSI_DISPOSED_FLAG => '1', others => '0');
|
||||
cur_sample_next <= empty_sample_list_head(ind);
|
||||
|
||||
-- NOTE: We always expect a Serialized Key as Input of this Opration, so we also check the Payload memory
|
||||
-- NOTE: We always expect a Serialized Key as Input of this Operation, so we also check the Payload memory
|
||||
-- Payload Memory Full
|
||||
if (empty_payload_list_head(ind) = PAYLOAD_MEMORY_MAX_ADDRESS) then
|
||||
if (global_ack_cnt(ind) = 0 and CONFIG_ARRAY_T(ind).HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
|
||||
@ -1269,7 +1480,7 @@ begin
|
||||
return_stage_next <= PUSH_KEY_HASH;
|
||||
end if;
|
||||
when WAIT_FOR_ACKNOWLEDGEMENTS =>
|
||||
-- NOTE: In case of BEST_EFFORT the RTPS Writer still manually ACK the Samples, so we do not handle this case differently here.
|
||||
-- NOTE: In case of BEST_EFFORT the RTPS Writer still manually ACKs the Samples, so we do not handle this case differently here.
|
||||
ack_dds(ind) <= '1';
|
||||
ack_wait_next(ind) <= '1';
|
||||
tmp_dw := time + max_wait_dds(ind);
|
||||
@ -1738,6 +1949,7 @@ begin
|
||||
end if;
|
||||
when PUSH_KEY_HASH =>
|
||||
done_dds(ind) <= '1';
|
||||
return_code_dds(ind) <= RETCODE_OK;
|
||||
instance_handle_out_dds(ind) <= key_hash;
|
||||
-- DONE
|
||||
stage_next <= IDLE;
|
||||
@ -3688,7 +3900,7 @@ begin
|
||||
end if;
|
||||
-- CHECK ACK STATE
|
||||
when 1 =>
|
||||
-- Writer in WAIT_FOR_ACKNOWLEDGEMENT Operation
|
||||
-- Writer in WAIT_FOR_ACKNOWLEDGEMENTS Operation
|
||||
if(ack_wait(ind) = '1') then
|
||||
-- All Writer Samples are ACKed
|
||||
if (global_ack_cnt(ind) = global_sample_cnt(ind)) then
|
||||
@ -3711,7 +3923,7 @@ begin
|
||||
when 2 =>
|
||||
assert (ack_wait(ind) = '1') severity FAILURE;
|
||||
|
||||
-- WAIT_FOR_ACKNOWLEDGEMENT Operation Timeout
|
||||
-- WAIT_FOR_ACKNOWLEDGEMENTS Operation Timeout
|
||||
if (timeout_time(ind) <= time) then
|
||||
-- Reset
|
||||
ack_wait_next(ind) <= '0';
|
||||
|
||||
@ -4,8 +4,8 @@ PUBLISH/SUBSCRIBE
|
||||
GENERAL
|
||||
=======
|
||||
|
||||
The wrapper Entities that define and implement the ROS Publisher and Subscriber - named <TOPICNAME>_ros_pub
|
||||
and <TOPICNAME>_ros_sub - are basically carbon copies of a normal <TYPENAME>_reader_interface and
|
||||
The wrapper Entities that define and implement the ROS Publisher and Subscriber - named <MESSAGENAME>_ros_pub
|
||||
and <MESSAGENAME>_ros_sub - are basically carbon copies of a normal <TYPENAME>_reader_interface and
|
||||
<TYPENAME>_writer_interface, with the exception of hiding all the user facing DDS signals and being
|
||||
responsible for interacting with the DDS entity directly.
|
||||
All these changes are static for all ROS messages, and the actual message dependent VHDL generation is the
|
||||
@ -25,7 +25,7 @@ The files also contain extra logic that may be necessary to parse the SERVICE_OV
|
||||
present in the payload.
|
||||
The code generation follows the normal code generation for encoding and decoding with following changes:
|
||||
|
||||
* Encoding and Decoding stages get a "RQ_"or "RR_" prepended to the <NAME> to differentiate between
|
||||
* Encoding and Decoding stages get a "RQ_" or "RR_" prefixed to the <NAME> to differentiate between
|
||||
Request and Response message members, respectively.
|
||||
e.g. GET_A -> GET_RQ_A, WRITE_SUM -> WRITE_RR_SUM
|
||||
* Similar to the previous point, the <SERVICENAME>_package differentiates the MAX_* sizes of the Request
|
||||
@ -55,27 +55,27 @@ For each Action (i.e. .action File) 8 files are generated:
|
||||
<ACTIONNAME>_ros_action_server (Action server)
|
||||
<ACTIONNAME>_ros_action_client (Action client)
|
||||
|
||||
The GOAL and RESULT serrvice files are similar to normal ROS Service files generation, with the addition
|
||||
The GOAL and RESULT service files are similar to normal ROS Service files generation, with the addition
|
||||
of static logic responsible for encoding/decoding static parts of the action messages.
|
||||
|
||||
Similarly the FEEDBACK publsiher/subscriber files is also similar to normal ROS publisher/subscriber files,
|
||||
Similarly the FEEDBACK publisher/subscriber files are also similar to normal ROS publisher/subscriber files,
|
||||
with the addition of static logic responsible for encoding/decoding static parts of the action messages.
|
||||
|
||||
ACTION SERVER
|
||||
-------------
|
||||
The ROS Action server is responsible for storing up to MAX_GOALS results.
|
||||
This is achieved by storing results in memories of MAX_GOALS depth.
|
||||
The ros_action_server entity contains the ROS action server logic, where as all the memories responsible
|
||||
The ros_action_server entity contains the ROS action server logic, whereas all the memories responsible
|
||||
for storing the results reside in <ACTIONNAME>_ros_action_server.
|
||||
The <ACTIONNAME>_ros_action_server contains a FSM responsible for fetching the requested RESULT on demand,
|
||||
which is communcated from ros_action_server via the r_index, r_sel, and r_sel_ack signals.
|
||||
which is communicated from ros_action_server via the r_index, r_sel, and r_sel_ack signals.
|
||||
In the IDLE stage, similar to the normal code generation, the memory signals are directly driven by the
|
||||
user facing port signals, allowing the user to write the RESULT. The 'index_result' signal is used to index
|
||||
user facing port signals, allowing the user to write the RESULT. The 'result_addr' signal is used to index
|
||||
the (outer) memories.
|
||||
If r_sel is '1', the FETCH_RESULT stage is entered, which is responsible for fetching the correct RESULT.
|
||||
The FETCH_RESULT stage is split into 2 sub-stages, a GET and a READ sub-stage. The GET sub-stage is waiting
|
||||
for all memories to be ready (ANDing the ready_in signals) before toggling the valid_in signal to initiate
|
||||
the memory read operation and proceeding to th next sub-stage. The READ sub-stage is waiting for all
|
||||
the memory read operation and proceeding to the next sub-stage. The READ sub-stage is waiting for all
|
||||
memory read operations to finish (ANDing the valid_out signals) before proceeding to the next stage.
|
||||
If the RESULT contains collections, they have to be manually pushed to the
|
||||
<ACTIONNAME>_ros_action_result_srv_server. In that case the next stage is a stage called PUSH_<COLLECTIONNAME>,
|
||||
@ -104,4 +104,4 @@ The <ACTIONNAME>_ros_action_client contains a FSM responsible for interfacing al
|
||||
clients and subscribers. Since this state machine is static, only the port connection of the
|
||||
instantiated entities has to be generated.
|
||||
Similarly to the action server, if ENABLE_FEEDBACK is '0', the FEEDBACK output ports have to manually be
|
||||
set to default values.
|
||||
set to default values.
|
||||
|
||||
@ -12,7 +12,7 @@ use work.GoalStatus_package;
|
||||
use work.GoalStatusArray_package;
|
||||
use work.CancelGoal_package;
|
||||
|
||||
entity Fibonacci_ros_action_client is
|
||||
entity TEMPLATE_ros_action_client is
|
||||
generic (
|
||||
ENABLE_FEEDBACK : std_logic := '1';
|
||||
LITTLE_ENDIAN : std_logic := '0'
|
||||
@ -212,7 +212,7 @@ entity Fibonacci_ros_action_client is
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture arch of Fibonacci_ros_action_client is
|
||||
architecture arch of TEMPLATE_ros_action_client is
|
||||
|
||||
--*****TYPE DECLARATION*****
|
||||
type STAGE_TYPE is (IDLE,SEND_GOAL_REQUEST,TAKE_GOAL_RESPONSE,SEND_RESULT_REQUEST,TAKE_RESULT_RESPONSE,SEND_CANCEL_REQUEST,TAKE_CANCEL_RESPONSE,TAKE_FEEDBACK,RETURN_ROS);
|
||||
@ -237,7 +237,7 @@ architecture arch of Fibonacci_ros_action_client is
|
||||
|
||||
begin
|
||||
|
||||
goal_srv_client_inst : entity work.Fibonacci_ros_action_goal_srv_client(arch)
|
||||
goal_srv_client_inst : entity work.TEMPLATE_ros_action_goal_srv_client(arch)
|
||||
generic map (
|
||||
LITTLE_ENDIAN => LITTLE_ENDIAN
|
||||
)
|
||||
@ -301,7 +301,7 @@ begin
|
||||
|
||||
goal_stamp <= to_ROS_TIME(goal_stamp_sig);
|
||||
|
||||
result_srv_client_inst : entity work.Fibonacci_ros_action_result_srv_client(arch)
|
||||
result_srv_client_inst : entity work.TEMPLATE_ros_action_result_srv_client(arch)
|
||||
generic map (
|
||||
LITTLE_ENDIAN => LITTLE_ENDIAN
|
||||
)
|
||||
@ -430,7 +430,7 @@ begin
|
||||
);
|
||||
|
||||
feedback_gen : if ENABLE_FEEDBACK = '1' generate
|
||||
feedback_sub_inst : entity work.Fibonacci_ros_action_feedback_sub(arch)
|
||||
feedback_sub_inst : entity work.TEMPLATE_ros_action_feedback_sub(arch)
|
||||
port map (
|
||||
clk => clk,
|
||||
reset => reset,
|
||||
|
||||
@ -12,7 +12,7 @@ use work.GoalStatus_package;
|
||||
use work.GoalStatusArray_package;
|
||||
use work.CancelGoal_package;
|
||||
|
||||
entity Fibonacci_ros_action_server is
|
||||
entity TEMPLATE_ros_action_server is
|
||||
generic (
|
||||
TIMEOUT_DURATION : ROS_DURATION_TYPE;
|
||||
MAX_GOALS : natural;
|
||||
@ -221,7 +221,7 @@ entity Fibonacci_ros_action_server is
|
||||
result_valid : out std_logic;
|
||||
result_ack : in std_logic;
|
||||
-- ###GENERATED START###
|
||||
-- RESULT PORTS (Prepend with result_)
|
||||
-- RESULT PORTS (Prepend with result_, both _w and _r signals are generated)
|
||||
-- ###GENERATED END###
|
||||
-- FEEDBACK SIGNALS
|
||||
-- ###GENERATED START###
|
||||
@ -230,7 +230,7 @@ entity Fibonacci_ros_action_server is
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture arch of Fibonacci_ros_action_server is
|
||||
architecture arch of TEMPLATE_ros_action_server is
|
||||
|
||||
--*****CONSTANT DECLARATION*****
|
||||
constant RESULT_INDEX_WIDTH : natural := log2c(MAX_GOALS);
|
||||
@ -278,7 +278,7 @@ architecture arch of Fibonacci_ros_action_server is
|
||||
|
||||
begin
|
||||
|
||||
goal_srv_server_inst : entity work.Fibonacci_ros_action_goal_srv_server(arch)
|
||||
goal_srv_server_inst : entity work.TEMPLATE_ros_action_goal_srv_server(arch)
|
||||
generic map (
|
||||
LITTLE_ENDIAN => LITTLE_ENDIAN
|
||||
)
|
||||
@ -340,7 +340,7 @@ begin
|
||||
return_code_user => g_return_code_user
|
||||
);
|
||||
|
||||
result_srv_server_inst : entity work.Fibonacci_ros_action_result_srv_server(arch)
|
||||
result_srv_server_inst : entity work.TEMPLATE_ros_action_result_srv_server(arch)
|
||||
generic map (
|
||||
LITTLE_ENDIAN => LITTLE_ENDIAN
|
||||
)
|
||||
@ -472,7 +472,7 @@ begin
|
||||
);
|
||||
|
||||
feedback_gen : if ENABLE_FEEDBACK = '1' generate
|
||||
feedback_pub_inst : entity work.Fibonacci_ros_action_feedback_pub(arch)
|
||||
feedback_pub_inst : entity work.TEMPLATE_ros_action_feedback_pub(arch)
|
||||
generic map (
|
||||
LITTLE_ENDIAN => LITTLE_ENDIAN
|
||||
)
|
||||
|
||||
@ -413,6 +413,9 @@ REQUEST_ID
|
||||
----------
|
||||
writer_guid, sequence_number
|
||||
|
||||
MESSAGE_INFO
|
||||
------------
|
||||
source_timestamp, received_timestamp, publisher_gid, from_intra_process(Whether this message is from intra-process communication or not.)
|
||||
|
||||
##################################
|
||||
http://design.ros2.org/articles/legacy_interface_definition.html
|
||||
|
||||
@ -14,10 +14,129 @@ use work.GoalStatus_package;
|
||||
use work.CancelGoal_package;
|
||||
use work.GoalStatusArray_package;
|
||||
|
||||
-- NOTE: New Goals coming from the Goal Service are not checked against their goal id, which may lead two multiple goals with same goal id being stored in memory.
|
||||
-- But this is expected behaviour and not the responsibility of the action server.
|
||||
-- NOTE: If both the goal id and time of a cancel request are set, and the goal with the set goal id falls also in the requested time range, a double user cancel
|
||||
-- prompt on the same goal may happen if the first prompt is rejected.
|
||||
-- ROS ACTION SERVER
|
||||
-- This Entity is implementing the ROS Action Server functionality, and keeps user interaction to a minimum.
|
||||
-- This server does not contain any type-dependent code, and is therefore static for all ROS actions. A wrapper
|
||||
-- has to present the type dependent ports of the underlying ROS entities to the user next to the signals of this
|
||||
-- entity. This wrapper entity should also contain a "memory array" (equal in depth to the MAX_GOALS generic) of
|
||||
-- results, that the user has direct access to.
|
||||
-- Internally the entity contains 2 memories, one for accepted goals tracking their status (size configurable via the
|
||||
-- MAX_GOALS generic), and one for stored result requests in order to reply as soon as the respective goal is finished
|
||||
-- (size configurable via the MAX_RESULT_REQUESTS generic).
|
||||
-- This entity uses the memory addresses of the stored goals in memory as a handles with which the user can reference
|
||||
-- goals for operations.
|
||||
|
||||
-- Whenever the GOAL service has available data, the goal request is fetched and presented to the user
|
||||
-- ('new_goal_request' signal asserted, 'new_goal_handle' signal containing the goal handle of the new goal, and
|
||||
-- 'new_goal_result_index' signal containing the target memory address/index of the result array for this goal).
|
||||
-- The entity waits until the user asserts the 'new_goal_response' signal, and the 'new_goal_accepted' signal denotes
|
||||
-- if the user accepted (signal asserted) or rejected the goal request, and the GOAL Service response is sent
|
||||
-- accordingly.
|
||||
-- If the goal memory is full and the TIMEOUT_DURATION generic is set to infinite duration, the entity will remove the
|
||||
-- oldest stored goal in a terminal state, if a new goal request is available from the GOAL service. If on the other
|
||||
-- hand the the TIMEOUT_DURATION is set, the goal will be automatically removed by the configured duration after the
|
||||
-- goal enters a terminal state.
|
||||
-- Whenever the RESULT service has available data, the result request is fetched and handled. If the target goal is
|
||||
-- not stored in the memory or the goal has already entered a terminal state, the response is sent immediately.
|
||||
-- If the target goal has not yet entered a terminal state, the result request is stored in the result request memory.
|
||||
-- (New result requests from the RESULT service are only fetched if the result memory has space).
|
||||
-- Whenever a goal enters a terminal state, the stored result requests of the respective goal are handled and removed
|
||||
-- from the memory.
|
||||
-- Whenever the CANCEL service has available data, the cancel request is fetched, and all relevant goal cancellation
|
||||
-- requests are presented to the user ('cancel_request' signal asserted, and 'cancel_request_handle' signal contains
|
||||
-- the goal handle of the goal to be canceled). The entity waits until the user asserts the 'cancel_response' signal,
|
||||
-- and the 'cancel_accepted' signal denotes if the user accepted (signal asserted) or rejected the cancellation request,
|
||||
-- and the CANCEL service response is sent accordingly.
|
||||
|
||||
-- The allowed ROS action server operations are GET_GOAL, GET_LAST_GOAL, GET_FIRST_GOAL, GET_NEXT_GOAL,
|
||||
-- GET_PREVIOUS_GOAL, UPDATE_GOAL_STATE, PUBLISH_FEEDBACK.
|
||||
-- To start an operation the 'start' signal is asserted with the respective opcode in the 'opcode' signal until the
|
||||
-- operation is acknowledged by the entity by asserting the 'ack' signal. After the operation is completed, the 'done'
|
||||
-- signal is asserted for one clock cycle, and the return code can be found in the 'return_code' signal on the same
|
||||
-- clock cycle.
|
||||
-- The GET_GOAL operation allows the user to get the goal ID, the current goal state, the target memory address/index
|
||||
-- of the result array, the goal acceptance timestamp, and the goal handle of a particular goal denoted by the goal
|
||||
-- handle in the 'goal_handle_in' in the 'goal_id', 'goal_state_out', 'goal_result_index', 'goal_stamp', and
|
||||
-- 'goal_handle_out' signals, respectively.
|
||||
-- Similarly the GET_FIRST_GOAL and GET_LAST_GOAL operations return the oldest and newest accepted goal in the list,
|
||||
-- whereas the GET_NEXT_GOAL and GET_PREVIOUS_GOAL operations return the next and previous goal based on the goal handle
|
||||
-- provided in the 'goal_handle_in' signal, and can be used to iterate through the goal list.
|
||||
-- The UPDATE_GOAL_STATE operation is used to update the goal state of the goal denoted by the goal handle in the
|
||||
-- 'goal_handle_in' signal to the state provided in the 'goal_state_in' signal. When transitioning to the "SUCCEEDED"
|
||||
-- state the user has to make sure, that the goal results are stored in the respective memory address/index of result
|
||||
-- array prior to this operation.
|
||||
-- The PUBLISH_FEEDBACK operation triggers the server to publish in the feedback topic and is used to publish feedback
|
||||
-- for the goal denoted by the goal handle in the 'goal_handle_in' signal. The user has to hold the type-dependent
|
||||
-- feedback signals valid until the return of the operation.
|
||||
|
||||
-- NOTE: New Goals coming from the Goal Service are not checked against their goal id, which may lead to multiple
|
||||
-- goals with same goal id being stored in memory. But this is expected behaviour and not the responsibility
|
||||
-- of the action server.
|
||||
-- NOTE: If both the goal id and time of a cancel request are set, and the goal with the set goal id falls also in
|
||||
-- the requested cancellation time range, a second user cancel prompt on the same goal may occur if the first
|
||||
-- prompt is rejected.
|
||||
|
||||
-- MEMORY LAYOUT
|
||||
-- This entity is using double linked lists of fixed-size memory frames.
|
||||
-- For each memory 2 lists of frames exist, one for the empty frames, and one for the occupied frames.
|
||||
-- The memory frames have following structure:
|
||||
|
||||
-- GOAL DATA MEMORY FORMAT
|
||||
-- =======================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +-----------------------------------------------+---------------+
|
||||
-- 01| UNUSED | GOAL_STATE |
|
||||
-- +-----------------------------------------------+---------------+
|
||||
-- 02| |
|
||||
-- + +
|
||||
-- 03| |
|
||||
-- + GOAL_ID +
|
||||
-- 04| |
|
||||
-- + +
|
||||
-- 05| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 06| |
|
||||
-- + STAMP +
|
||||
-- 07| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 08| |
|
||||
-- + DEADLINE +
|
||||
-- 09| [only if TIMEOUT_DURATION /= DURATION_INFINITE] |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 10| RESULT_INDEX |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 11| NEXT_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 12| PREV_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- RESULT REQUEST DATA MEMORY FORMAT
|
||||
-- =================================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| GOAL_HANDLE |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + +
|
||||
-- 03| |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- + REQUEST_ID +
|
||||
-- 05| |
|
||||
-- + +
|
||||
-- 06| |
|
||||
-- + +
|
||||
-- 07| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 08| NEXT_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 09| PREV_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
|
||||
entity ros_action_server is
|
||||
generic (
|
||||
@ -442,7 +561,7 @@ begin
|
||||
|
||||
-- *Main State Machine*
|
||||
-- STATE DESCRIPTION
|
||||
-- IDLE Idle state
|
||||
-- IDLE Idle State. Initiates STATUS topic publications, ROS Operation handling, (overflow) Goal removal, GOAL service request handling, RESULT service request handling, CANCEL service request handling, and (timeout) Goal removal, in that priority order.
|
||||
-- GET_S_DATA Get goal data from memory
|
||||
-- PUSH_STATUS Add goal data to status list
|
||||
-- PUBLISH_STATUS Publish status list
|
||||
@ -456,7 +575,7 @@ begin
|
||||
-- RETURN_USER User return
|
||||
-- PUBLISH_FEEDBACK Publish feedback
|
||||
-- WAIT_FOR_G_DATA Wait goal service request
|
||||
-- WAIT_FOR_G_USER Wait for user input
|
||||
-- WAIT_FOR_G_USER Wait for user input (new_goal_response)
|
||||
-- ADD_GOAL Add goal to memory
|
||||
-- SEND_G_RESPONSE Send goal service response
|
||||
-- WAIT_FOR_G_RET Wait for goal service response
|
||||
@ -467,8 +586,8 @@ begin
|
||||
-- WAIT_FOR_R_RET Wait for result service response
|
||||
-- WAIT_FOR_C_DATA Wait for cancel service request
|
||||
-- GET_C_DATA Get goal data from memory
|
||||
-- CANCEL_CHECK Search fot goal cancel targets
|
||||
-- WAIT_FOR_C_USER Wait for user input
|
||||
-- CANCEL_CHECK Search for goal cancel targets
|
||||
-- WAIT_FOR_C_USER Wait for user input (cancel_response)
|
||||
-- CANCEL_GOAL Update goal state to CANCELING
|
||||
-- ADD_CANCEL Store canceling goal for later response
|
||||
-- SEND_C_RESPONSE Send cancel service response
|
||||
|
||||
@ -9,6 +9,10 @@ use work.math_pkg.all;
|
||||
use work.rtps_package.all;
|
||||
use work.ros_config_package.all;
|
||||
|
||||
-- This entity implements a specialized DDS writer, that is only publishing one statically generated sample.
|
||||
-- This is required to provide information on the ROS node to DDS endpoints mapping.
|
||||
-- REF: http://design.ros2.org/articles/Node_to_Participant_mapping.html
|
||||
|
||||
entity ros_static_discovery_writer is
|
||||
port (
|
||||
-- SYSTEM
|
||||
|
||||
@ -10,6 +10,171 @@ use work.rtps_package.all;
|
||||
use work.user_config.all;
|
||||
use work.rtps_config_package.all;
|
||||
|
||||
-- RTPS DISCOVERY MODULE
|
||||
-- This Entity is implementing the Discovery Module of the DDSI-RTPS Specification.
|
||||
-- It is responsible for parsing and generating meta traffic and implements the Participant Discovery Protocol (PDP),
|
||||
-- and the Endpoint Discovery Protocol (EDP). Currently only the Simple PDP (SPDP) and Simple EDP (SEDP) are supported.
|
||||
-- Newly discovered matching remote participants are stored in memory (see further below for what information is
|
||||
-- retained), while information of already matched remote participants are updated on change. If a previously matched
|
||||
-- remote participant is now unmatched, it is removed from memory.
|
||||
-- Discovered remote endpoints are NOT stored in memory, but are immediately forwarded to the local relevant endpoints
|
||||
-- with the information of if its a match or not. If the local endpoint is compatible with the remote discovered
|
||||
-- endpoint, a ENDPOINT_MATCH_FRAME is sent to the local endpoint. If the remote endpoint is incompatible with the local
|
||||
-- endpoint, a ENDPOINT_UNMATCH_FRAME is sent to the local endpoint. If the a previously matched remote participant is
|
||||
-- removed from memory, a PARTICIPANT_UNMATCH_FRAME is sent to all local endpoints (so that they can remove all remote
|
||||
-- endpoint of that participant).
|
||||
-- This entity is also responsible for the periodic participant announcement, and implementation of LIVELINESS QoS
|
||||
-- "AUTOMATIC" and "MANUAL_BY_PARTICIPANT". If a remote endpoint renews his Liveliness a ENDPOINT_LIVELINESS_UPDATE is
|
||||
-- sent to the relevant local endpoints.
|
||||
-- See "RTPS OUT" description for the RTPS output format and "RTPS HANDLER" description for possible input formats.
|
||||
|
||||
-- ENDPOINT MATCH FRAME
|
||||
-- ====================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| OPCODE (=0x55000000) |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + +
|
||||
-- 03| GUIDPREFIX |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 05| ENTITYID |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 06| IPv4_ADDRESS |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 07| UDP_PORT | READER_FLAGS |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 08| |
|
||||
-- + LIFESPAN_DURATION +
|
||||
-- 09| [only for Reader Endpoints] |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- READER_FLAGS
|
||||
-- ------------
|
||||
-- 15............8...............0
|
||||
-- | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +-------------------------+-+-+-+
|
||||
-- | UNUSED |B|H|Q|
|
||||
-- +-------------------------+-+-+-+
|
||||
-- Q...Reader expects in-line QoS
|
||||
-- H...Reader expects Historical Data
|
||||
-- B...Reader has RELIABILITY BEST_EFFORT
|
||||
|
||||
-- ENDPOINT UNMATCH FRAME
|
||||
-- ======================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| OPCODE (=0x55000001) |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + +
|
||||
-- 03| GUIDPREFIX |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 05| ENTITYID |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- PARTICIPANT UNMATCH FRAME
|
||||
-- =========================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| OPCODE (=0x55000002) |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + +
|
||||
-- 03| GUIDPREFIX |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- ENDPOINT LIVELINESS UPDATE
|
||||
-- ==========================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| OPCODE (=55000003) |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + +
|
||||
-- 03| GUIDPREFIX |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- MEMORY LAYOUT
|
||||
-- This entity is using double linked lists of fixed-size memory frames.
|
||||
-- 2 lists of frames exist, one for the empty frames, and one for the occupied frames.
|
||||
-- A memory frame has following structure:
|
||||
-- PARTICIPANT DATA MEMORY FRAME
|
||||
-- =============================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| |
|
||||
-- + +
|
||||
-- 02| GUIDPREFIX |
|
||||
-- + +
|
||||
-- 03| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 04| META_IPv4_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 05| DEFAULT_IPv4_ADDRESS |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 06| META_UDP_PORT | DEFAULT_UDP_PORT |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 07| |
|
||||
-- + SPDP_SEQ_NR +
|
||||
-- 08| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 09| |
|
||||
-- + LEASE_DURATION +
|
||||
-- 10| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 11| |
|
||||
-- + LEASE_DEADLINE +
|
||||
-- 12| |
|
||||
-- +---------------------------------------------------------+-+-+-+
|
||||
-- 13| UNUSED |P|S|M|
|
||||
-- +---------------------------------------------------------+-+-+-+
|
||||
-- 14| |
|
||||
-- + ACKNACK_RES_TIME +
|
||||
-- 15| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 16| |
|
||||
-- + HEARTBEAT_RES_TIME +
|
||||
-- 17| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 18| |
|
||||
-- + PUBLICATION_SEQ_NR +
|
||||
-- 19| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 20| |
|
||||
-- + SUBSCRIPTION_SEQ_NR +
|
||||
-- 21| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 22| |
|
||||
-- + MESSAGE_SEQ_NR +
|
||||
-- 23| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 24| NEXT_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 25| PREV_ADDRESS |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- M...Send Message Data (Liveliness Update)
|
||||
-- S...Send Subscriber Data
|
||||
-- P...Send Publisher Data
|
||||
|
||||
entity rtps_discovery_module is
|
||||
generic (
|
||||
PREFER_MULTICAST : boolean := FALSE;
|
||||
@ -543,7 +708,7 @@ begin
|
||||
|
||||
-- Main State Machine
|
||||
-- STATE DESCRIPTION
|
||||
-- IDLE Idle state. Initiates Participant Announcements, Heartbeat/Liveliness Assertions, Stale Participant Entry Checks ,and Packet Processing, in that priority order.
|
||||
-- IDLE Idle state. Initiates Participant Announcements, Heartbeat/Liveliness Assertions, Stale Participant Entry Checks, and Packet Processing, in that priority order.
|
||||
-- PACKET_HEADER Read the Endpoint FIFO Packet Format Header (RTPS Submessage ID/Opcode, Submessage Flags, Source UDPv4 Port)
|
||||
-- PACKET_SRC_ADDR Read Source IPv4 Address
|
||||
-- PACKET_SRC_GUIDPREFIX Read Source GUID Prefix
|
||||
@ -2391,7 +2556,7 @@ begin
|
||||
-- If MUST_UNDERSTAND Flag is set, we have incompatible communication. Drop Packet
|
||||
if (endian_swap(endian_flag,parameter_id)(PID_MUST_UNDERSTAND_FLAG_POS) = '1') then
|
||||
stage_next <= SKIP_PACKET;
|
||||
-- Else skip Uknown Parameter
|
||||
-- Else skip Unknown Parameter
|
||||
else
|
||||
stage_next <= SKIP_PARAMETER;
|
||||
end if;
|
||||
@ -3964,12 +4129,10 @@ begin
|
||||
-- Read outside of packet Length
|
||||
-- NOTE: If the Packet Length is smaller than expected there will be a read from input FIFO while
|
||||
-- the Packet Length has been reached and will be caught by this clause.
|
||||
-- The SKIP_PACKET clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
|
||||
-- The SKIP_PACKET state has a special clause that prevents it from entering this state.
|
||||
if ((last_word_in_latch = '1' and last_word_in = '0') and rd_guard = '1') then
|
||||
-- Force rd_sig low
|
||||
rd_sig <= '0';
|
||||
-- Notify Endpoints of EOP
|
||||
last_word_out_sig <= '1'; -- TODO: Necessary? (We do not pass through input to output, so a EOP should not leave us "stranded" during a write out)
|
||||
-- Continue parsing next Packet
|
||||
stage_next <= IDLE;
|
||||
-- Reset Last Word In Latch
|
||||
@ -3979,12 +4142,10 @@ begin
|
||||
-- Read outside of Parameter Length
|
||||
-- NOTE: If the Parameter Length is smaller than expected for a particular parameter, there will be a read from input FIFO while
|
||||
-- the Parameter Length has been reached and will be caught by this clause.
|
||||
-- The SKIP_PARAMETER clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
|
||||
-- The SKIP_PARAMETER state has a special clause that prevents it from entering this state.
|
||||
elsif ((read_cnt & "00") >= parameter_end and rd_guard = '1') then
|
||||
-- Force rd_sig low
|
||||
rd_sig <= '0';
|
||||
-- Notify Endpoints of EOP
|
||||
last_word_out_sig <= '1';
|
||||
-- Invalid Parameter Length, Skip Packet
|
||||
stage_next <= SKIP_PACKET;
|
||||
-- Reset Parameter End
|
||||
|
||||
@ -10,6 +10,129 @@ use work.rtps_package.all;
|
||||
use work.user_config.all;
|
||||
use work.rtps_config_package.all;
|
||||
|
||||
-- RTPS HANDLER
|
||||
-- This entity is a first-stage decoder for the RTPS protocol. It parses the RTPS Header and Submessages, splits each
|
||||
-- Submessages to a known internal format (detailed below) and forwards it to the respective destination (Discovery
|
||||
-- Module or User Endpoints).
|
||||
-- It works directly on a custom semi-decoded UDP/IPv4 packet format (detailed below).
|
||||
-- All validity checks (except for inlineQoS) are done in this entity.
|
||||
|
||||
-- INPUT FORMAT
|
||||
-- ============
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| SRC_IPv4_ADDR |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| DEST_IPv4_ADDR |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 03| SRC_UDP_PORT | DEST_UDP_PORT |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 04| PACKET_LENGTH |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 05| |
|
||||
-- ~ PACKET ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- OUTPUT FORMAT
|
||||
-- =============
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------+---------------+-------------------------------+
|
||||
-- 01| OPCODE | FLAGS | SRC_UDP_PORT |
|
||||
-- +---------------+---------------+-------------------------------+
|
||||
-- 02| SRC_IPv4_ADDR |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 03| |
|
||||
-- + +
|
||||
-- 04| SRC_GUIDPREFIX |
|
||||
-- + +
|
||||
-- 05| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 06| SRC_ENTITYID |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 07| DEST_ENTITYID [only for Discovery Module] |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 08| |
|
||||
-- + Sequence Number [only for DATA Submessage] +
|
||||
-- 09| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 10| |
|
||||
-- + Timestamp +
|
||||
-- 11| [only for DATA Submessage and User Endpoints] |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 12| |
|
||||
-- ~ PAYLOAD (SUBMESSAGE CONTENT) ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- HEARTBEAT PAYLOAD (See DDSI-RTPS v2.3)
|
||||
-- -----------------
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| |
|
||||
-- + FirstSN +
|
||||
-- 02| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 03| |
|
||||
-- + LastSN +
|
||||
-- 04| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 05| Count |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- ACKNACK PAYLOAD (See DDSI-RTPS v2.3)
|
||||
-- ---------------
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| |
|
||||
-- + ReaderSNState.BASE +
|
||||
-- 02| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 03| ReaderSNState.NumBits |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 04| |
|
||||
-- ~ [ReaderSNState.Bitmap] x 0-8 ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- **| Count |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- GAP PAYLOAD (See DDSI-RTPS v2.3)
|
||||
-- -----------
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| |
|
||||
-- + GapStart +
|
||||
-- 02| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 03| |
|
||||
-- + GapList.BASE +
|
||||
-- 04| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 05| GapList.NumBits |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 06| |
|
||||
-- ~ [GapList.Bitmap] x 0-8 ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- **| UNUSED |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- DATA PAYLOAD
|
||||
-- ------------
|
||||
-- The DATA Payload is transferred as is (Black Box).
|
||||
-- This is also why we cannot validate the inlineQoS
|
||||
|
||||
entity rtps_handler is
|
||||
port (
|
||||
-- SYSTEM
|
||||
@ -179,7 +302,7 @@ begin
|
||||
-- This process is responsible for reading the input FIFO 4-Byte Word aligned.
|
||||
-- Even though DDSI-RTPS 2.3 defines that Submessages begin at 4-byte boundries, meaning that the
|
||||
-- submessage length is always a multiple of 4, the same is not defined for the "octetstoinlineQoS".
|
||||
-- Therefore alignment is not guaranteed from the "SKIP_DATA_HEADER" stage on and has to be ensured explicitly.
|
||||
-- Therefore alignment is not guaranteed from the "SKIP_DATA_HEADER" stage onwards and has to be ensured explicitly.
|
||||
-- We store the lower 2 bits of the octet length (Which denotes the 4-Byte alignment offset), and together
|
||||
-- with the "align_sig" which stores 3 Bytes from the previous input word, we generate our aligned signal.
|
||||
align_prc : process(all)
|
||||
@ -488,8 +611,7 @@ begin
|
||||
stage_next <= SKIP_SUB;
|
||||
-- VALIDITY CHECK
|
||||
elsif (rtps_sub_flags(SUBMESSAGE_DATA_FLAG_POS) = '1' and rtps_sub_flags(SUBMESSAGE_KEY_FLAG_POS) = '1') then
|
||||
-- Invalid Submessage, skip Packet (see DDSI-RTPS 2.3 Section 9.4.5.3.1 and 8.3.4.1)
|
||||
-- TODO: Clarify if this invalidate the rest of the Message, since it is not stated in 8.3.7.2.3
|
||||
-- Invalid, skip Submessage (see DDSI-RTPS 2.3 Section 9.4.5.3.1)
|
||||
stage_next <= SKIP_SUB;
|
||||
end if;
|
||||
-- PAD (Variable Size Padding)
|
||||
@ -892,7 +1014,6 @@ begin
|
||||
cnt2_next <= 0;
|
||||
|
||||
-- VALIDITY CHECK
|
||||
-- TODO: Shouldn't that check the highest bit?
|
||||
if (unsigned(data_in_swapped) > 256) then
|
||||
-- If numBits is negative or larger than 256, Number Set is invalid (see DDSI-RTPS 2.3 Section 9.4.2.6)
|
||||
-- If gapList is invalid, skip Packet (see DDSI-RTPS 2.3 Section 8.3.7.4.3 and 8.3.4.1)
|
||||
@ -928,7 +1049,7 @@ begin
|
||||
-- Extra Flags & octetstoinlineQoS
|
||||
when 0 =>
|
||||
-- NOTE: Extra Flags are unused
|
||||
-- Latch Length to skip Uknown Data Header Part and latch offset to ensure 4-Byte alignement (see align_prc)
|
||||
-- Latch Length to skip Unknown Data Header Part and latch offset to ensure 4-Byte alignment (see align_prc)
|
||||
offset_latch_next <= std_logic_vector(rtps_sub_data_length(1 downto 0));
|
||||
data_header_end_next <= (read_cnt_plus & "00") + rtps_sub_data_length;
|
||||
cnt_next <= cnt + 1;
|
||||
@ -1092,7 +1213,7 @@ begin
|
||||
wr_sig <= '1';
|
||||
end if;
|
||||
cnt_next <= cnt + 1;
|
||||
-- Source Timestamp 1/2 [only for DATA Submessages and User Endpoints]
|
||||
-- Source Timestamp 2/2 [only for DATA Submessages and User Endpoints]
|
||||
when 10 =>
|
||||
if (opcode = SID_DATA and builtin_endpoint = '0') then
|
||||
data_out_sig <= std_logic_vector(src_ts(1));
|
||||
@ -1312,7 +1433,7 @@ begin
|
||||
-- Read outside of packet Length
|
||||
-- NOTE: If the Packet Length is smaller than expected there will be a read from input FIFO while
|
||||
-- the Packet Length has been reached and will be caught by this clause.
|
||||
-- The SKIP_PACKET clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
|
||||
-- The SKIP_PACKET state has a special clause that prevents it from entering this state.
|
||||
if (read_cnt = packet_length and rd_guard = '1') then
|
||||
-- Force rd_sig low
|
||||
rd_sig <= '0';
|
||||
@ -1326,11 +1447,11 @@ begin
|
||||
-- Read outside of Submessage Length
|
||||
-- NOTE: If the Submessage Length is smaller than expected for a particular Submessage, there will be a read from input FIFO while
|
||||
-- the Submessage Length has been reached and will be caught by this clause.
|
||||
-- The SKIP_SUB clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
|
||||
-- The SKIP_SUB state has a special clause that prevents it from entering this state.
|
||||
elsif (read_cnt = sub_end and rd_guard = '1') then
|
||||
-- Force rd_sig low
|
||||
rd_sig <= '0';
|
||||
-- Notify Endpoints of EOS
|
||||
-- Notify Endpoints of EOP
|
||||
last_word_out_sig <= '1';
|
||||
-- Invalid Submessage Length Field, Skip Packet (see DDSI-RTPS 2.3 Section 8.3.4.1)
|
||||
stage_next <= SKIP_PACKET;
|
||||
|
||||
@ -10,6 +10,57 @@ use work.rtps_package.all;
|
||||
use work.user_config.all;
|
||||
use work.rtps_config_package.all;
|
||||
|
||||
-- RTPS OUT
|
||||
-- This entity is the common output of the RTPS system.
|
||||
-- The RTPS Discovery Module, RTPS Reader, and RTPS Writer are connected to this entity, which in turn is connected
|
||||
-- to the egress network stack.
|
||||
-- The entity latches a single packet from one of the input FIFOs in round robin fashion, calculates and inserts the
|
||||
-- packet length, and writes it to the output FIFO.
|
||||
-- Because the packet length has to be calculated and stored (almost) at the beginning of the packet, the whole packet
|
||||
-- has to be stored in a buffer, before it can be moved to the output FIFO. The size of the buffer is configurable via
|
||||
-- MAX_BUFFER_SIZE and has to be big enough to hold the largest possible generated packet. If the packet does not fit
|
||||
-- in the buffer, the packet is silently dropped.
|
||||
-- While a finished packet is transferred to the output FIFO, the next packet can be stored into the buffer in parallel.
|
||||
|
||||
-- The input format (output format of RTPS Discovery Module, RTPS Reader, and RTPS Writer) is seen below:
|
||||
-- INPUT FRAME FORMAT
|
||||
-- ==================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| SRC_IPv4_ADDR |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| DEST_IPv4_ADDR |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 03| SRC_UDP_PORT | DEST_UDP_PORT |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 04| |
|
||||
-- ~ RTPS_PACKET ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
-- The output format of the RTPS OUT entity is the same as the input format of the RTPS Handler, meaning that you could
|
||||
-- directly connect the RTPS OUT to an RTPS Handler:
|
||||
-- OUTPUT FRAME FORMAT
|
||||
-- ===================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| SRC_IPv4_ADDR |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| DEST_IPv4_ADDR |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 03| SRC_UDP_PORT | DEST_UDP_PORT |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 04| PACKET_LENGTH |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 05| |
|
||||
-- ~ PACKET ~
|
||||
-- **| |
|
||||
-- +---------------------------------------------------------------+
|
||||
|
||||
entity rtps_out is
|
||||
generic (
|
||||
RTPS_OUT_WIDTH : natural := NUM_ENDPOINTS+1;
|
||||
|
||||
@ -10,10 +10,83 @@ use work.rtps_package.all;
|
||||
use work.user_config.all;
|
||||
use work.rtps_config_package.all;
|
||||
|
||||
-- RTPS READER
|
||||
-- This Entity is implementing the RTPS reader endpoints.
|
||||
-- The entity represents multiple reader endpoints (configurable via the NUM_READERS generic).
|
||||
-- Input is parsed once for all readers (DATA Submessage payloads get temporarily stored in a PAYLOAD memory), but then
|
||||
-- handled for each relevant reader individually. If the input is relevant for a reader is reflected in the 'empty_*'
|
||||
-- signal of the input FIFO.
|
||||
-- In contrast output is only written by one reader at a time, and never in parallel.
|
||||
-- See "RTPS HANDLER" description for possible input formats of user-traffic, "RTPS DISCOVERY MODULE" description
|
||||
-- for possible input formats of meta-traffic, and "RTPS OUT" description for the RTPS output format.
|
||||
-- Each reader has its own memory containing the matched remote writer endpoints (see below for memory format), based on
|
||||
-- the meta-traffic received from the discovery module. Only traffic from remote endpoints residing in the local memory
|
||||
-- is accepted.
|
||||
-- This entity can receive a HEARTBEAT, GAP, or DATA Submessage as user-traffic from remote writer endpoints.
|
||||
-- The next expected sequence number of each remote matched writer is stored in memory, and can be modified by the
|
||||
-- receival of an HEARTBEAT Submessage (if the remote writer no longer has the expected sequence number), or a GAP
|
||||
-- Submessage (if the next expected sequence number is in the GAP list).
|
||||
-- Only the Key Hash (PID_KEY_HASH) and Instance State Change (PID_STATUS_INFO) are parsed from thr inline QoS of a DATA
|
||||
-- Submessage.
|
||||
-- This entity interacts with the HistoryCache via a start/done operation schema. The allowed operations are
|
||||
-- ADD_CACHE_CHANGE and REMOVE_WRITER. See "DDS READER" for input format and operation schema.
|
||||
-- Only DATA Submessages with the next expected sequence number (from that remote endpoint writer) are accepted, and
|
||||
-- propagated to the HistoryCache with an ADD_CACHE_CHANGE operation.
|
||||
-- Whenever a previously remote writer endpoint is removed via meta-traffic, a REMOVE_WRITER operation is initiated on
|
||||
-- the HistoryCache.
|
||||
|
||||
-- MEMORY LAYOUT
|
||||
-- This entity is using double linked lists of fixed-size memory frames.
|
||||
-- 2 lists of frames exist, one for the empty frames, and one for the occupied frames.
|
||||
-- A memory frame has following structure:
|
||||
-- WRITER ENDPOINT DATA MEMORY FRAME
|
||||
-- =================================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| ENTITYID |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + +
|
||||
-- 03| GUIDPREFIX |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 05| IPv4_ADDRESS [Reliable Only] |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 06| UDP_PORT [Reliable Only] | UNUSED [Reliable Only] |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 07| |
|
||||
-- + NEXT_SEQ_NR +
|
||||
-- 08| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 09| |
|
||||
-- + LEASE_DEADLINE +
|
||||
-- 10| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 11| |
|
||||
-- + LIFESPAN_DURATION +
|
||||
-- 12| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 13| |
|
||||
-- + RES_TIME [Reliable Only] +
|
||||
-- 14| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 15| WRITER_ID |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 16| NEXT_ADDR |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 17| PREV_ADDR |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- The 'WRITER_ID' field is a read-only field that gives each memory frame a unique ID (incrementing integer), that is
|
||||
-- used by following entities (DDS READER) to identify the sender of data. This ID can be used to index bitmaps (see
|
||||
-- "DDS READER" description).
|
||||
|
||||
entity rtps_reader is
|
||||
generic (
|
||||
-- HACK: FIXME: Quartus Workaround
|
||||
-- Quartus does not allow to reference a generic insisde the generic block.
|
||||
-- Quartus does not allow to reference a generic inside the generic block.
|
||||
-- So we constrain the range later as constant
|
||||
NUM_READERS : natural;
|
||||
CONFIG_ARRAY : QUARTUS_CONFIG_ARRAY_TYPE;
|
||||
@ -735,7 +808,6 @@ begin
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
-- Memory Operation Guard
|
||||
else
|
||||
assert ((empty_user xor r_map) = (empty_user'range => '1')) severity FAILURE;
|
||||
|
||||
@ -1828,7 +1900,7 @@ begin
|
||||
mem_r.lease_deadline <= TIME_INVALID;
|
||||
end if;
|
||||
|
||||
-- NOTE: In case the operation was unsucessfull (e.g. reached Resource Limits), the Sequence Number is not updated
|
||||
-- NOTE: In case the operation was unsuccessful (e.g. reached Resource Limits), the Sequence Number is not updated
|
||||
-- and thus not "acknowledged".
|
||||
-- Operation was Accepted
|
||||
if (ret_hc(ind) = OK) then
|
||||
@ -2174,9 +2246,9 @@ begin
|
||||
|
||||
-- OVERREAD GUARD
|
||||
-- Read outside of packet Length
|
||||
-- NOTE: If the Packet Length is smaller than expected there will be a read from input FIFO while
|
||||
-- the Packet Length has been reached and will be caught by this clause.
|
||||
-- The SKIP_PACKET clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
|
||||
-- NOTE: If the payload is smaller than expected there will be a read from input FIFO while
|
||||
-- the last word has been already been read and will be caught by this clause.
|
||||
-- The SKIP_PACKET state has a special clause that prevents it from entering this state.
|
||||
if ((last_word_in_latch = '1' and last_word_in_user = '0') and rd_guard = '1') then
|
||||
-- Force rd_sig low
|
||||
rd_sig <= '0';
|
||||
@ -2189,7 +2261,7 @@ begin
|
||||
-- Read outside of Parameter Length
|
||||
-- NOTE: If the Parameter Length is smaller than expected for a particular parameter, there will be a read from input FIFO while
|
||||
-- the Parameter Length has been reached and will be caught by this clause.
|
||||
-- The SKIP_PARAMETER clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
|
||||
-- The SKIP_PARAMETER state has a special clause that prevents it from entering this state.
|
||||
elsif ((read_cnt & "00") >= parameter_end and rd_guard = '1') then
|
||||
-- Force rd_sig low
|
||||
rd_sig <= '0';
|
||||
|
||||
@ -591,8 +591,12 @@ package rtps_test_package is
|
||||
function gen_endpoint_array(readers : boolean) return ENDPOINT_DATA_ARRAY_TYPE;
|
||||
-- Extract Data from RTPS Submessage (Sequence Number, Payload, Serialized_Key) and generate Cache Change
|
||||
function gen_cache_change(ref : RTPS_SUBMESSAGE_TYPE) return CACHE_CHANGE_TYPE;
|
||||
|
||||
procedure gen_CDR(input : std_logic_vector; target_align : ALIGN_TYPE; align_offset : inout unsigned; output : inout TEST_PACKET_TYPE);
|
||||
-- Write data to serialized payload respecting the alignment.
|
||||
-- input Data to be inserted to the serialized payload
|
||||
-- target_align Alignment to be used for the input data
|
||||
-- align_offset Current alignment offset. This is modified by the procedure. Can be set to zero externally to "logically reset" the CDR stream.
|
||||
-- output Destination of written output
|
||||
procedure write_serialized_payload(input : std_logic_vector; target_align : ALIGN_TYPE; align_offset : inout unsigned; output : inout TEST_PACKET_TYPE);
|
||||
end package;
|
||||
|
||||
package body rtps_test_package is
|
||||
@ -3283,7 +3287,7 @@ package body rtps_test_package is
|
||||
end case;
|
||||
end procedure;
|
||||
|
||||
procedure gen_CDR(input : std_logic_vector; target_align : ALIGN_TYPE; align_offset : inout unsigned; output : inout TEST_PACKET_TYPE) is
|
||||
procedure write_serialized_payload(input : std_logic_vector; target_align : ALIGN_TYPE; align_offset : inout unsigned; output : inout TEST_PACKET_TYPE) is
|
||||
begin
|
||||
-- Align Stream
|
||||
while (not check_align(align_offset,target_align)) loop
|
||||
|
||||
@ -10,6 +10,97 @@ use work.rtps_package.all;
|
||||
use work.user_config.all;
|
||||
use work.rtps_config_package.all;
|
||||
|
||||
-- RTPS WRITER
|
||||
-- This Entity is implementing the RTPS writer endpoints.
|
||||
-- The entity represents multiple writer endpoints (configurable via the NUM_WRITERS generic).
|
||||
-- Input is parsed once for all writers, but then handled for each relevant writer individually. If the input is
|
||||
-- relevant for a writer is reflected in the 'empty_*' signal of the input FIFO.
|
||||
-- In contrast output is only written by one writer at a time, and never in parallel.
|
||||
-- See "RTPS HANDLER" description for possible input formats of user-traffic, "RTPS DISCOVERY MODULE" description
|
||||
-- for possible input formats of meta-traffic, and "RTPS OUT" description for the RTPS output format.
|
||||
-- Each writer has its own memory containing the matched remote reader endpoints (see below for memory format), based on
|
||||
-- the meta-traffic received from the discovery module. Only traffic from remote endpoints residing in the local memory
|
||||
-- is accepted.
|
||||
-- This entity can only receive ACKNACK Submessages as user-traffic from (reliable) remote reader endpoints.
|
||||
-- This entity has an internal sequence number that is incremented on each new cache change. Depending on the setting
|
||||
-- of 'PUSH_MODE' a new cache change is sent immediately, or only after the remote reliable reader has requested it via
|
||||
-- an ACKNACK Submessage.
|
||||
-- A request bitmap (of a range of up to 32 SN), and the sequence number of the last acknowledged SN of each remote
|
||||
-- endpoint are stored in the local memory. (Note that only reliable readers can send ACKNACKs).
|
||||
-- A global signal contains the highest common ACKed SN of all remote reader endpoints (remote best effort readers are
|
||||
-- ignored), and allows this entity to mark SNs in the HistoryCache for deletion.
|
||||
|
||||
-- This entity interacts with the HistoryCache via a start/done operation schema.
|
||||
-- The allowed operations are GET_CACHE_CHANGE, ACK_CACHE_CHANGE, NACK_CACHE_CHANGE, REMOVE_CACHE_CHANGE, GET_MIN_SN,
|
||||
-- and GET_MAX_SN.
|
||||
-- Everytime new data is available ('data_available' signal of the HistoryCache is high), or data needs to be fetched to
|
||||
-- satisfy a request the GET_CACHE_CHANGE operation is executed.
|
||||
-- Once a SN has been acknowledged by all matched remote (reliable) readers, either the ACK_CACHE_CHANGE operation is
|
||||
-- performed on the HistoryCache to convey this information, or the REMOVE_CACHE_CHANGE operation is executed to remove
|
||||
-- the CacheChange from the HistoryCache (if the local endpoint is configured with DURABILITY QoS VOLATILE).
|
||||
-- Requested SN from remote endpoint readers, on the other hand, are NACKed (reversing the ACK) using the
|
||||
-- NACK_CACHE_CHANGE operation.
|
||||
-- In order to formulate a HEARTBEAT SUbmessage the entity has to know the highest and lowest SN still available in the
|
||||
-- HistoryCache, which it gets with the GET_MIN_SN and GET_MAX_SN operations.
|
||||
|
||||
-- MEMORY LAYOUT
|
||||
-- This entity is using double linked lists of fixed-size memory frames.
|
||||
-- 2 lists of frames exist, one for the empty frames, and one for the occupied frames.
|
||||
-- A memory frame has following structure:
|
||||
-- READER ENDPOINT DATA MEMORY FRAME
|
||||
-- =================================
|
||||
-- 31............24..............16..............8...............0
|
||||
-- | | | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 01| ENTITYID |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 02| |
|
||||
-- + +
|
||||
-- 03| GUIDPREFIX |
|
||||
-- + +
|
||||
-- 04| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 05| IPv4_ADDRESS |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 06| UDP_PORT | READER_FLAGS |
|
||||
-- +-------------------------------+-------------------------------+
|
||||
-- 07| |
|
||||
-- + LEASE_DEADLINE [Reliable Only] +
|
||||
-- 08| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 09| |
|
||||
-- + RES_TIME [Reliable Only] +
|
||||
-- 10| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 11| |
|
||||
-- + ACK_SEQ_NR_BASE [Reliable Only] +
|
||||
-- 12| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 13| |
|
||||
-- + REQ_SEQ_NR_BASE [Reliable Only] +
|
||||
-- 14| |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 15| REQ_BITMAP [Reliable Only] |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 16| NEXT_ADDR |
|
||||
-- +---------------------------------------------------------------+
|
||||
-- 17| PREV_ADDR |
|
||||
-- +---------------------------------------------------------------+
|
||||
--
|
||||
-- READER_FLAGS
|
||||
-- ------------
|
||||
-- 15............8...............0
|
||||
-- | | |
|
||||
-- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
-- +-------------------------+-+-+-+
|
||||
-- | UNUSED |B|H|Q|
|
||||
-- +-------------------------+-+-+-+
|
||||
-- Q...Reader expects in-line QoS
|
||||
-- H...Reader expects Historical Data
|
||||
-- B...Reader has RELIABILITY BEST_EFFORT
|
||||
|
||||
|
||||
entity rtps_writer is
|
||||
generic (
|
||||
-- HACK: FIXME: Quartus Workaround
|
||||
@ -303,7 +394,7 @@ architecture arch of rtps_writer is
|
||||
signal mem_opcode : MEM_OPCODE_TYPE;
|
||||
-- Signals the end of a Memory Operation
|
||||
signal mem_op_done : std_logic;
|
||||
-- Signal used to pass data to memeory process
|
||||
-- Signal used to pass data to memory process
|
||||
signal mem_r : ENDPOINT_DATA_TYPE;
|
||||
-- Signal used to pass the Request Sequence Number Bitmap from main to memory process
|
||||
signal req_seq_nr_bitmap, req_seq_nr_bitmap_next : std_logic_vector(0 to WORD_WIDTH-1);
|
||||
@ -483,7 +574,7 @@ begin
|
||||
|
||||
-- *Main State Machine*
|
||||
-- STATE DESCRIPTION
|
||||
-- IDLE Idle State. Initiates Stale Endpoint Checks, Metatraffic Packet Processing, and User Packet Processing, in that priority order.
|
||||
-- IDLE Idle State. Initiates New Data Pushing, Manual Liveliness Assertion, Heartbeat Sending, Stale Endpoint Checks, Metatraffic Packet Processing, and User Packet Processing, in that priority order.
|
||||
-- LATCH_SRC_ADDR Store source IPv4 Address
|
||||
-- LATCH_GUIDPREFIX Store source GUID Prefix
|
||||
-- LATCH_ENTITYID Store source Entity ID
|
||||
|
||||
@ -5,6 +5,16 @@ library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
-- VECTOR FIFO
|
||||
-- This entity implements a special kind of FIFO, called a vector FIFO.
|
||||
-- A vector FIFO stores the same data for multiple targets, but uses only the storage for one.
|
||||
-- The information on which targets the data is relevant to is encoded in the 'write' and 'empty' signals, which gets
|
||||
-- stored in a separate "supplementary" FIFO.
|
||||
-- Due to the nature of the vector FIFO, only parallel read is possible. If needed external logic should make sure
|
||||
-- that all relevant consumers are pulling read high, before pulling the read of the FIFO high.
|
||||
|
||||
-- TODO: Since no information is encoded in the 'full' signal, make it std_logic.
|
||||
|
||||
entity vector_FIFO is
|
||||
generic(
|
||||
FIFO_DEPTH : natural := 2;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user