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


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