AR# 50777

AutoESL: Array partition using structs or array partition of struct member with array of structs

描述

The following is a specific example for a generic situation.

I am trying to synthesize a C code in order to accelerate it.
 
The below example is a reduced section of code to illustrate the questions.
 
The main objective is a deep control over array partition when I use structs.

#define NPOINTS 1000
#define N_CONS 5
#define O_CONS 3
typedef struct _point_data {
  double xx[O_CONS]; /* */
  double consflux[N_CONS];
  double dtvol;
  double otherdouble;
} PointData;

void fpga_runge_kutta_step( PointData point_data[NPOINTS])
{
  double coeff = 0.15;
  double fac;
  int pnt, eq;
  L1: for(pnt = 0; pnt < NPOINTS; pnt++){
    fac = coeff * point_data[pnt].dtvol;
    L2: for(eq = 0; eq < N_CONS; eq++){
      point_data[pnt].consflux[eq] *= fac;
    }
  }
}


I have pipelined L1 (then L2 is unrolled) but the pipeline II is 5 because consflux is an array.
 
It generates a port point_data_consflux
 
I want to partition this point_data_consflux in 5 (N_CONS) ports: point_data_consflux_0, point_data_consflux_1, . . .


How can I do this?

解决方案

This can be accomplished without changing the code structure in two ways, the same as for any other general directives: either pragmas or Tcl directives. 

The trick is figuring out how to dereference the object to which you want to apply the directive. 
 
Essentially, the input array is just a pointer to _point_data types, which include the array they want partitioned. 
 
Using this fact, you should be able to de-reference the pointer using the '->' member access operator.

The '.' access will not work, because that would require dereferencing a specific element of point_data[]...

Method 1:
 
The first technique is to embed a pragma version of the directive into the source code:

void fpga_runge_kutta_step(    PointData point_data[NPOINTS])
{

    double coeff = 0.15;
    double fac;
    int pnt, eq;
#pragma AP array_partition complete variable=point_data->consflux
...


An advantage to this is that it is set for all solutions that might be created to explore other optimizations.

Method 2:
The second technique is to use the following Tcl command, either in a batch mode script or entered into the "directive.tcl" file via the GUI, for a given solution:
set_directive_array_partition -type complete fpga_runge_kutta_step point_data->consflux

Both of these techniques work (with AutoESL / Vivado HLS 2012.1) and get the expected port mapping, i.e. 5x 1000 element RAM ports for 'consflux' and a single 1000 element RAM port for 'dtvol' (the other members from the example are unused so do not appear as ports).

AR# 50777
日期 06/10/2015
状态 Active
Type 综合文章
Tools