We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for
Did you mean:
Highlighted
Voyager
9,949 Views
Registered: ‎10-07-2011

## Making a variable a FIFO

Hi folks,

I have a pipelined function that needs to save history data to a given variable (memory). In order to achieve an initiation interval of 1, that variable shall be a FIFO. This is the "accum" variable below.

void    VectorAveraging(tAXIS *x,tAXIS *r,ap_uint<8> N)

{

ap_uint<8>  i;

ap_uint<12> j;

ap_uint<20> index = 0;

ap_uint<24>  sum, accum[MAX_DATA_BEATS_PER_PROFILE];

ProfileLoop: for (i=0;i<N;)

DataLoop: for (j=0;j<MAX_DATA_BEATS_PER_PROFILE;j++) {

if (i == 0)

sum = x[index].data;

else

sum = x[index].data + accum[j];         <<<<< accum[j] is read here

accum[j] = sum;                                          <<<<< accum[j] is written here

if (i == (N - 1)) {

r[j].data = sum / N;

r[j].last = x[index].last;

}

if (x[index++].last == 1) {

i++;

break;

}

}

}

The above function simply averages the specified number (N) of vectors. The length of the vector (M) can be anything up to 4K and N can be as much as 255. That is:

1 <= N <= 255

1 <= M <= 4096

The accumulated vector is stored in a FIFO.

So far, I had no success specifying accum as a FIFO using the directives:

set_directive_stream -depth 4096 "VectorAveraging" accum

set_directive_resource -core FIFO "VectorAveraging" accum

Vivado is saying that the stream directive can only be implemented in a dataflow region. This makes me think that a FIFO is only possible when it is used to pass data from a provider block to a consumer block (just like ping-pong buffers) but that they are not supported to recirculate data within a given block.

@E [XFORM-123] Cannot stream 'accum.V' (LiDARWaveformProcessor/code/src/VectorAveraging.cpp:81): a local variable is streamable only if it is in a dataflow region.

@E [HLS-70] Pre-synthesis failed.

If I delete the STREAM directive, then I get:

LiDARWaveformProcessor.cpp:89) on array 'accum.V' with core 'FIFO'.

Any hint on how to make such a variable a FIFO?

Many thanks!

Claude

1 Solution

Accepted Solutions
Xilinx Employee
14,977 Views
Registered: ‎08-17-2011

## Re: Making a variable a FIFO

Hello Claude,

To override this message you could use something like this #pragma HLS dependence variable=ProfileCntr inter false...

*BUT* you need to understand what it does and have a TB to test this... otherwise things may not work later.

To try to elaborate a bit more, a pipeline II=1 directive to the tool means that you wish to call this function every single clock cycle.

Because you're trying to do that and the tool thinks it's not possible you get the warning.

Most often this issue is on the boundaries and corner cases like "what happens if the if statements / loop conditions are always true and/or have the minimum values always?"

Also, some other issues happen because the datapath is too long - imagine the update of the critical variable depends on a long division.

-> will "you" be able to update the values in time before the next call?

I hope it makes some sense.. and you overriding this, really means "don't worry I know that I checked all the corner cases and it works..."

...

- Hervé

SIGNATURE:
* New Dedicated Vivado HLS forums* http://forums.xilinx.com/t5/High-Level-Synthesis-HLS/bd-p/hls

* Give Kudos to a post which you think is helpful and reply oriented.
7 Replies
9,941 Views
Registered: ‎12-18-2012

## Re: Making a variable a FIFO

These directives are defining I/O between blocks as you say. Any other array within the block becomes either a BRAM or a LUTRAM which you should be able to define.  So you can just make sure it works as a fifo defining it in the C code itself.

Voyager
9,937 Views
Registered: ‎10-07-2011

## Re: Making a variable a FIFO

Do you mean creating a static array along with read and write functions to manually manage the read and write pointers?

If so, how is HLS going to know that this extra code shall be implemented using a FIFO core?

Claude

9,925 Views
Registered: ‎12-18-2012

## Re: Making a variable a FIFO

It would not..Unless there is a way i am not aware of. But why do you need for the tool to use explicitly its FIFO core inside the IP block?

Voyager
9,917 Views
Registered: ‎10-07-2011

## Re: Making a variable a FIFO

My C code is now going through C simulation and synthesis with success. However, it has an II of 2.

I thought the problem was related to the accum[] variable that is synthesized has an array, rather than a FIFO. However, I found out that this variable is NOT the problem.

The problem is with a ProfileCntr variable, as summarized below.

@I [SCHED-61] Pipelining function 'LiDARWaveformProcessor'.

@W [SCHED-68] Unable to enforce a carried dependency constraint (II = 1, distance = 1)

between 'store' operation (LiDARWaveformProcessor/code/src/

LiDARWaveformProcessor.cpp:130) of variable 'tmp_1' on static variable 'ProfileCntr_V' and 'load' operation ('t.V', LiDARWaveformProcessor/code/src/LiDARWaveformProcessor.cpp:106) on static variable 'ProfileCntr_V'.

@I [SCHED-61] Pipelining result: Target II: 1, Final II: 2, Depth: 29.

The variable is defined as below within the top-level function:

static uint32_t ProfileCntr = 1;

In fact, the whole function ges like this, with lines 106 and 130 marked by <<<<<<<<<<<<<:

void    LiDARWaveformProcessor(tAXIS *x,tAXIS *r,ap_uint<8> N)

{

static tAXIS result = { 0, 0};

static ap_uint<12> DataCntr = 0;

static ap_uint<8> ProfileCntr = 1;

ap_uint<24>  sum;

if (ProfileCntr == 1)                                                                      // <<<<<<<<<<<<<<<<<<<<<<<<<

// Data from first profile go through (ie not summed with the accumulator)

sum = x->data;

else

// Data from other profiles are summed with the accumulator

sum = x->data + accum[DataCntr];

// Update the accumulator

accum[DataCntr++] = sum;

// Update the result if needed

if (ProfileCntr == N) {

// Last profile is triggering the output

result.data = sum / N;

result.last = x->last;

}

// Output the result

r->data = result.data;

r->last = result.last;

// Update and manage the counters

if ((x->last == 1) || (DataCntr == MAX_PROFILE_LENGTH)) {

DataCntr = 0;

(ProfileCntr == N) ? ProfileCntr = 1 : ProfileCntr++;                           // <<<<<<<<<<<<<<<<<<<<<<<<<

}

}

My understanding is that the variable need to be loaded and then, modifed and stored. If I was to code that in RTL, that variable would be a state machine register and would be always available (ie no need to load; just modify and update on every clock).

Is there a way to specify such a behavior with HLS?

Cheers!

Claude

Xilinx Employee
14,978 Views
Registered: ‎08-17-2011

## Re: Making a variable a FIFO

Hello Claude,

To override this message you could use something like this #pragma HLS dependence variable=ProfileCntr inter false...

*BUT* you need to understand what it does and have a TB to test this... otherwise things may not work later.

To try to elaborate a bit more, a pipeline II=1 directive to the tool means that you wish to call this function every single clock cycle.

Because you're trying to do that and the tool thinks it's not possible you get the warning.

Most often this issue is on the boundaries and corner cases like "what happens if the if statements / loop conditions are always true and/or have the minimum values always?"

Also, some other issues happen because the datapath is too long - imagine the update of the critical variable depends on a long division.

-> will "you" be able to update the values in time before the next call?

I hope it makes some sense.. and you overriding this, really means "don't worry I know that I checked all the corner cases and it works..."

...

- Hervé

SIGNATURE:
* New Dedicated Vivado HLS forums* http://forums.xilinx.com/t5/High-Level-Synthesis-HLS/bd-p/hls

* Give Kudos to a post which you think is helpful and reply oriented.
Voyager
9,905 Views
Registered: ‎10-07-2011

## Re: Making a variable a FIFO

Tried it; no success!

@I [SCHED-61] Pipelining function 'LiDARWaveformProcessor'.

@W [SCHED-68] Unable to enforce a carried dependency constraint (II = 1, distance = 1)

between fifo read on port 'x_last_V' (LiDARWaveformProcessor/code/src/

LiDARWaveformProcessor.cpp:128) and fifo read on port 'x_last_V' (LiDARWaveformProcessor/code/src/LiDARWaveformProcessor.cpp:120).

@I [SCHED-61] Pipelining result: Target II: 1, Final II: 2, Depth: 29.

Again, the question is: How to make a variable act like a register. The output of a register is always available for use and that output is updated every clock cycle. Hence, no need for separate load and store operations.

Thanks!

Claude

Voyager
9,902 Views
Registered: ‎10-07-2011

## Re: Making a variable a FIFO

Forget it. It's working.

I had to set the pragma on a second variable as well.

Thanks to everybody!

Claude