hls::stream Class

Introduction

This class is an API compatible class with Xilinx provides hls::stream class in Vivado HLS. In the vsi::runtime implementation the hls::stream is thread safe . This document describes the vsi::runtime implementation of the hls::stream class, please refer to the Section “Using HLS Streams” in the “Vivado High Level Synthesis : User Guide (UG902)” for details on the hardware implementation of this class. Care has been taken to match the hardware behavior.

Class instance.

The hls::stream is a template class and requires a “type” to be instantiated. The data in the hls::stream class can only be accessed sequentially; the data is stored and retrieved using the First In First Out method. The following example shows an instance of hls::stream. typedef unsigned int uint; hls::stream<uint> uistrm;

Public APIs.

void hls::stream< T>.write(T&);

Is blocking operation , it pushes a value into the stream . uint w_uint =32; uistrm.write(w_uint);

The C++ “<<” operator can also be used to write data into a stream.

uistrm << w_uint;

T hls::stream< T>.read();

Is a blocking read operation , it will wait till data is available on the stream and returns the data; in the vsi::runtime implementation the calling thread is blocked from execution and will wait till some other thread puts data into the stream using hls::stream< T>.write(T&); The read operation will pop the first element from the hls::stream FIFO and return to the user.

uint r_uint = uistrm.read();

The C++ “>>” operator can also be used to pop data from the stream FIFO.

uistrm >> r_uint;

bool hls::stream< T>.write_nb(T&);

Is a non-blocking write operation, will return “true” if the write was successful else it will return “false”.


uint w_uint = 32;
if (uistrm.write_nb(w_uint)) {
    // write success code
} else {
    // write fail code
}

bool hls::stream< T>.read_nb(T&);

Is the non-blocking version of the read, if data is available the function will update the reference in the argument with the values and return “true” , it will return false if the data is not available.


uint r_uint;
if (uistrm.read_bd(r_uint)) {
    // read successful
} else {
    // read failed no data in the stream
}

bool hls::stream< T>.full();

Return “true” if there is no more space in the stream to write data, return “false” if there is space.

bool hls::stream< T>.empty();

Returns “true” if the stream is empty() , this can be used in conjunction with the read() method to implement non-blocking reads.

Examples:

Example 1:

The hls::stream class can used to implement dependencies between blocks in a complete system. In the following code example, the function vsi_mem_ctl reads an input array , and sends the data to an output stream (out_stream); then waits for response from the another function on the stream “resp” before continuing to execute.


void vsi_memory_ctl(int in_arr[1024],
                    hls::stream<ap_axis_d<32> > &out_stream,
                    hls::stream<ap_axis_d<32> > &start,
                    hls::stream<ap_axis_d<32> > &resp)
{
	static int count = 0 ;
	ap_axis_d<32> e;
	int i;

	printf("%s started %d\n",__FUNCTION__,count);
	// perform operation
	for (i = 0 ; i < 1024; i++) {
		e.data = in_arr[i];
		e.last = (i == 1023);
		out_stream.write(e); // write to output stream
		if (e.last) printf("%s last detected %d\n",__FUNCTION__,i);
	}
	ap_axis_d<32> w ;
	w.data = 1;
	w.last = 1;
	// tell next function to start
	start.write(w);
	printf("%s sent start waiting for response\n",__FUNCTION__);

	// wait for response
	ap_axis_d<32> r = resp.read();
	printf("%s done %d\n",__FUNCTION__,count++);
  }

Example 2:

This functions reads from two AXI streams and converts them into a single stream with different IDs.


void stream_mux (hls::stream<ap_axis_dkt<DATA_WIDTH> > &in1,
		 hls::stream<ap_axis_dkt<DATA_WIDTH> > &in2,
		 hls::stream<ap_axis_dkt<DATA_WIDTH> > &outp)
{
	while (!in1.empty() || !in2.empty()) { // non blocking wait
		ap_axis_dkt<DATA_WIDTH> out;
		ap_axis_dkt<DATA_WIDTH> in;
		ap_uint<1> tid;
		bool set = false;
		if (!in1.empty()) {
			in = in1.read();
			tid = 0;
			set = true;
		} else if (!in2.empty()) {
			in = in2.read();
			tid = 1;
			set = true;
		}
		out.data = in.data;
		out.keep = in.keep;
		out.last = in.last;
		out.id   = tid;
		if (set) outp.write(out);
	}

More examples can be found in the source $(VSI_INSTALL)/target/common/hls_examples/stream_mux/stream_mux.cc