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!

AR# 50777

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

Description

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?

Solution

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
Date Created 07/11/2012
Last Updated 06/10/2015
Status Active
Type General Article
Tools
  • AutoESL