cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
fash_1
Visitor
Visitor
1,505 Views
Registered: ‎12-07-2018

ERROR: Read-before-write is not supported on array

Jump to solution

Hi,

 

I want to basically read data from an array, execute data and write result into array by using dataflow pragma.  However, when i synthesize my design, HLS give the following error;

ERROR: [XFORM 203-711] Array 'register_file' failed dataflow checking: Read-before-write is not supported on array. 

I searched in the forum and saw some similar problem yet i couldnt find the solution. The below code is not my main code, i wrote it to understand the situation easily. How can i solve this problem?

Thank you,

Fatih

 

/* REGISTER FILE */
unsigned int register_file[10];


void registers_read(unsigned int read_reg_1, unsigned int read_reg_2,
unsigned int &read_data_1, unsigned int &read_data_2)
{

read_data_1 = register_file[read_reg_1];
read_data_2 = register_file[read_reg_2];

}



void registers_write( unsigned int write_reg, unsigned int write_data)
{

if(write_reg == 0)
return;

register_file[write_reg] = write_data;

}



void add_reg (unsigned int read_reg_1, unsigned int read_reg_2,
unsigned int &execution_res)
{
execution_res = read_reg_1+read_reg_2;
}




void test_dataflow (unsigned int read_reg_1, unsigned int read_reg_2, unsigned int write_reg)
{
unsigned int read_data_1, read_data_2;
unsigned int execution_res;


#pragma HLS DATAFLOW
registers_read(read_reg_1, read_reg_2, read_data_1, read_data_2);

add_reg(read_data_1, read_data_2, execution_res);

registers_write(write_reg, execution_res);
}
0 Kudos
1 Solution

Accepted Solutions
u4223374
Advisor
Advisor
1,410 Views
Registered: ‎04-26-2015

The idea behind dataflow is, as the name suggests, that data flows from one process to the next. It's probably best to just assume that it'll be implemented as a FIFO. In your application there are a few problems:

 

- Read-before-write. In your code, the first function reads from the FIFO ... which is empty because the other function in the dataflow region hasn't filled it yet. The second function writes to the FIFO ... and that data just disappears into the aether, because there's nothing to read it.

- Non-local variables. Dataflow assumes that dataflow variables have two end-points - there's one function filling a variable, and another emptying it. Doesn't matter whether they're FIFOs or ping-pong buffers. Implementing dataflow with more end-points (at either end) is a major challenge; you have all sorts of interesting problems associated with concurrent/parallel computing (deadlocks, unpredictable/unrepeatable behavior, etc) - and it's also not very practical because most Xilinx hardware (eg. BRAM and LUT RAM) only has two ports anyway.If there are only two end-points, and both of them are functions within the dataflow region, then the variable might as well be in the dataflow region too. If it's not in the dataflow region, that implies that you're going to have another end-point outside the dataflow region.

 

Having HLS implement dataflow with ping-pong buffers solves some of the inherent limitations of FIFOs, but dataflow is still going to be upset about both of those points. Ping-pong buffering also eliminates all advantages of using dataflow in this situation, so you might as well just take out the dataflow pragma and let HLS implement it "normally".

View solution in original post

0 Kudos
6 Replies
xilinxacct
Professor
Professor
1,493 Views
Registered: ‎10-23-2018

@fash_1 

Try initializing your register file, so it is 'written-before read'.

Hope that Helps

If so, Please mark as solution accepted. Kudos also welcomed. :-)

0 Kudos
fash_1
Visitor
Visitor
1,479 Views
Registered: ‎12-07-2018

I add the below piece of code to initialize register as you said. 

for(int i=0; i<10;i++)
     register_file[i] = 0;

However, in addition to previous error, I took following ERROR;

ERROR: [XFORM 203-711] Non-internal global variable 'register_file' failed dataflow checking: it can only be written
in one process function. 

I change the place of init code but the result was same.

 

Fatih

 

0 Kudos
xilinxacct
Professor
Professor
1,468 Views
Registered: ‎10-23-2018

@fash_1 

This solution may give some insight... https://forums.xilinx.com/t5/Vivado-High-Level-Synthesis-HLS/XFORM-203-711-failed-dataflow-checking-it-can-only-be-used-in/td-p/783556

Also, there are different ways to initalize.

Hope that Helps

If so, Please mark as solution accepted. Kudos also welcomed. :-)

0 Kudos
fash_1
Visitor
Visitor
1,441 Views
Registered: ‎12-07-2018

@xilinxacct 

 

I check the link you gave and modified my code as below. However, the result is same, HLS gives the same error. 

 

/* REGISTER FILE */



void registers_read(unsigned int read_reg_1, unsigned int read_reg_2,
unsigned int &read_data_1, unsigned int &read_data_2, unsigned int *register_file)
{

read_data_1 = register_file[read_reg_1];
read_data_2 = register_file[read_reg_2];

}



void registers_write( unsigned int write_reg, unsigned int write_data, unsigned int *register_file)
{

if(write_reg == 0)
return;

register_file[write_reg] = write_data;

}



void add_reg (unsigned int read_reg_1, unsigned int read_reg_2,
unsigned int &execution_res)
{
execution_res = read_reg_1+read_reg_2;
}




void test_dataflow (unsigned int read_reg_1, unsigned int read_reg_2, unsigned int write_reg)
{
unsigned int read_data_1, read_data_2;
unsigned int execution_res;


#pragma HLS DATAFLOW
static unsigned int register_file[10];


registers_read(read_reg_1, read_reg_2, read_data_1, read_data_2, register_file);

add_reg(read_data_1, read_data_2, execution_res);

registers_write(write_reg, execution_res, register_file);
}
0 Kudos
nmoeller
Xilinx Employee
Xilinx Employee
1,427 Views
Registered: ‎09-05-2018

Hey @fash_1 ,

I think you've run into a limitation of the dataflow optimization. This seems to be an example of functions that utilize feedback, as well as a non-local array, which is also not supported.

You can read more about these limitation and suggested guidelines starting on page 151 of UG902 v2018.3.

Nicholas Moellers

Xilinx Adaptive Computing Tools
u4223374
Advisor
Advisor
1,411 Views
Registered: ‎04-26-2015

The idea behind dataflow is, as the name suggests, that data flows from one process to the next. It's probably best to just assume that it'll be implemented as a FIFO. In your application there are a few problems:

 

- Read-before-write. In your code, the first function reads from the FIFO ... which is empty because the other function in the dataflow region hasn't filled it yet. The second function writes to the FIFO ... and that data just disappears into the aether, because there's nothing to read it.

- Non-local variables. Dataflow assumes that dataflow variables have two end-points - there's one function filling a variable, and another emptying it. Doesn't matter whether they're FIFOs or ping-pong buffers. Implementing dataflow with more end-points (at either end) is a major challenge; you have all sorts of interesting problems associated with concurrent/parallel computing (deadlocks, unpredictable/unrepeatable behavior, etc) - and it's also not very practical because most Xilinx hardware (eg. BRAM and LUT RAM) only has two ports anyway.If there are only two end-points, and both of them are functions within the dataflow region, then the variable might as well be in the dataflow region too. If it's not in the dataflow region, that implies that you're going to have another end-point outside the dataflow region.

 

Having HLS implement dataflow with ping-pong buffers solves some of the inherent limitations of FIFOs, but dataflow is still going to be upset about both of those points. Ping-pong buffering also eliminates all advantages of using dataflow in this situation, so you might as well just take out the dataflow pragma and let HLS implement it "normally".

View solution in original post

0 Kudos