Visible to Intel only — GUID: ngn1583337015328
Ixiasoft
Visible to Intel only — GUID: ngn1583337015328
Ixiasoft
4.3. Pipes
Using external memory to move data in and out of static-object libraries or task functions can constrain the performance of your design. Pipes provide a mechanism for passing data with high efficiency and low latency by using on-device FIFO buffers to communicate.
Pipes are similar to streams, but are simpler. You can use pipes in a component or to allow tasks to communicate with each other, but pipes support only ready/valid and data signals, while streams support additional sideband signals such as startofpacket and endofpacket.
Unlike streams, you can declare an array of pipes and you can iterate over the array to write or read many pipes in a design.
Data written to a pipe remains in the pipe until it is read or until the component is reset.
The memory model of pipes allows you to use them to send and receive data from task functions in running functions in a static-object library or a running task function.
Pipe Properties
- FIFO ordering
- Data is accessible (readable) only in FIFO order. There is no concept of a memory address or pointer in a pipe, which means random data access is not possible with pipes.
- Capacity
-
Pipes have a capacity. That is, a fixed amount of data can be written to an initially empty pipe before needing to read anything from it to make room for more data.
A full pipe applies back pressure to the write site.
Pipe Accessors
Data is written to a pipe through an API that commits a single word of the pipe data type, and that word is later returned by an API that reads data from the pipe.
- Blocking API calls
-
Blocking write API calls wait until the pipe has enough capacity to commit data.
Blocking read API calls wait until the pipe contains data to be read.
- Nonblocking API calls
- Nonblocking API calls execute immediately and return a status that indicates whether the operation was successful.
You can mix blocking and nonblocking accesses to the same pipe. For example you can write data to a pipe with a blocking pipe write() call and read it from the other end using a non-blocking read() call, and vice versa.
Data Persistence in Pipes
Data written to a pipe by a component remains in the pipe until it is read or until the component is reset.
Data written to a pipe by a task remains in the pipe until another task reads from the pipe or the component containing the tasks is reset.
The sequence of data in a pipe always follows FIFO ordering.
Data in pipes does not persist across FPGA device resets or reprogramming.
Restrictions on using Pipes
- Multiple pipe call sites
- A component or task function can read from the same pipe multiple times, but multiple component or task functions cannot read from the same pipe. Similarly, a component or task function can write to the same pipe multiple times, but multiple component or task functions cannot write to the same pipe.
- Feedback and feed-forward pipes
- A component or task function should use separate pipes for pipe reads and pipe writes. Writing to and reading from the same pipe within the same function can lead to poor performance.
- Pipe accesses in loops
-
Do not use nonblocking pipes if you use a loop structure that waits for data from the pipe. That is, avoid the following code pattern for nonblocking pipe accesses:
Use a blocking access with this code pattern instead because a blocking access in this code pattern is more efficient in hardware than a nonblocking access in this code pattern.bool success = false; while (!success) { my_pipe::write(rd_src_buf[i], success); // can also be a nonblocking read }