UPGRADE YOUR BROWSER

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 
Search instead for 
Did you mean: 
Voyager
Voyager
9,943 Views
Registered: ‎10-07-2011

Making a variable a FIFO

Jump to solution

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:

 

@E [SCHED-42] Cannot implement operation 'load' operation ('accum_V_load', LiDARWaveformProcessor/code/src/

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

 

 

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

 

Many thanks!

 

Claude

0 Kudos
1 Solution

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

Re: Making a variable a FIFO

Jump to solution

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
* Readme/Guidance* http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

* Please mark the Answer as "Accept as solution" if information provided is helpful.
* Give Kudos to a post which you think is helpful and reply oriented.
7 Replies
Adventurer
Adventurer
9,935 Views
Registered: ‎12-18-2012

Re: Making a variable a FIFO

Jump to solution

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. 

 

0 Kudos
Voyager
Voyager
9,931 Views
Registered: ‎10-07-2011

Re: Making a variable a FIFO

Jump to solution

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

 

 

0 Kudos
Adventurer
Adventurer
9,919 Views
Registered: ‎12-18-2012

Re: Making a variable a FIFO

Jump to solution

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?

 

0 Kudos
Voyager
Voyager
9,911 Views
Registered: ‎10-07-2011

Re: Making a variable a FIFO

Jump to solution

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

0 Kudos
Xilinx Employee
Xilinx Employee
14,972 Views
Registered: ‎08-17-2011

Re: Making a variable a FIFO

Jump to solution

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
* Readme/Guidance* http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

* Please mark the Answer as "Accept as solution" if information provided is helpful.
* Give Kudos to a post which you think is helpful and reply oriented.
Voyager
Voyager
9,899 Views
Registered: ‎10-07-2011

Re: Making a variable a FIFO

Jump to solution

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

0 Kudos
Voyager
Voyager
9,896 Views
Registered: ‎10-07-2011

Re: Making a variable a FIFO

Jump to solution

Forget it. It's working.

 

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

 

Thanks to everybody!

 

Claude

0 Kudos