Accessing External I/O via Direct Hardware Connections
Whereas the previous example demonstrated how applications can access system I/O through memory buffers, a platform can also provide direct hardware connectivity to hardware accelerators within an application generated in the SDSoC Environment. The following figure shows how a function s2mm_data_copy communicates to the platform via an AXI4-Stream channel, and writes to DDR memory using the zero_copy datamover (implemented as an AXI4 master interface). This design template is called Unpacketized AXI4-Stream to DDR design example in the samples/platforms/zc702_axis_io platform (a similar design for the Zybo board is in samples/xc7z010/zybo_axis_io).
Figure: Unpacketized AXI-MM DataMover Design
In this example, the zc702_axis_io platform proxies actual I/O by providing a free-running binary counter (labeled Platform IP in the diagram) running at 50 MHz, connected to an AXI4-Stream Data FIFO IP block that exports an AXI4-Stream master interface to the platform clocked at the data motion clock (which might differ from the 50 MHz input clock).
The direct I/O software interface can be found in the zc702_axis_io.h header file located in the SDSoC install directory under samples/platforms/zc702/aarch32-linux/include.
#pragma SDS data access_pattern(rbuf:SEQUENTIAL)
void pf_read_stream(unsigned *rbuf);
In the code snippet below, the application defines a direct signal path from the platform input to a hardware function before transferring the output to memory.
// This function's data flow defines the accelerator network
void s2mm_data_copy_wrapper(unsigned *buf)
{
unsigned rbuf0[1];
pf_read_stream(rbuf0);
s2mm_data_copy(rbuf0,buf);
}
The platform library provides the pf_read_stream function that the sds++ linker maps onto the hardware stream port. Because the only use of the rbuf0 output is the input to the s2mm_data_copy function, the linker creates a direct hardware connection over an AXI4-Stream channel. Because the s2mm_data_copy function transfers buf using the zero_copy data mover, the buffer must be allocated in physically contiguous memory using sds_alloc, and released using sds_free.
int main()
{
unsigned *bufs[NUM_BUFFERS];
for(int i=0; i<NUM_BUFFERS; i++) {
bufs[i] = (unsigned*) sds_alloc(BUF_SIZE * sizeof(unsigned));
}
// call accelerator data path and check result
for(int i=0; i<NUM_BUFFERS; i++) {
sds_free(bufs[i]);
}
return 0;
}
A tutorial of how to use this example design is provided in SDSoC Environment Tutorial: Introduction (UG1028).
A detailed tutorial on creating a platform using AXI4-Stream to write memory directly can be found in Introduction.