Skip to content

Commit

Permalink
add MRI-Q accelerator designed with the Stratus HLS flow (sld-columbi…
Browse files Browse the repository at this point in the history
  • Loading branch information
pei2748 authored and paulmnt committed May 10, 2021
1 parent a2f785a commit d994018
Show file tree
Hide file tree
Showing 40 changed files with 3,492 additions and 2 deletions.
1 change: 0 additions & 1 deletion accelerators/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ vivado_src
solver.*
*final.xml
cgraph.graphml
data
inout
*.o
*.opp
Expand Down
57 changes: 57 additions & 0 deletions accelerators/stratus_hls/mriq_stratus/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
### Directory introduction:

* `hw/`

* `mriq.xml`

* `memlist.txt`

* `hls/`

* `sim/`

* `tb/`

* `src/`

* `inc/`

* `data/`
* 32\_32\_32\_dataset.bin:
* It comes from Parboil benchmark, with numX as 32768, numK as 3072. We use this file to generate test data with smaller sizes.
* genData.c :
* generate a smaller dataset from 32\_32\_32\_dataset.bin. It needs two arguments: numX and numK. It writes new data into an input file with name test\_32\_x<numX>\_k<numK>.bin and a golden output file test\_32\_x<numX>\_k<numK>.bin with the same data layout. So we can use the two programs provided by Parboil benchmark to read data into pointer variables.
* wrt_bmData.c
* This program is used to generate test data for baremetal application. We need to provide six arguments: 1, numX, 2. numK, 3. batch\_size\_k, 4. num\_batch\_k, 5. batch\_size\_x, 6. num\_batch\_x.
* Makefile
* compile genData.c and wrt_bmData.c


* `sw/`

* `baremetal`

* `linux`

* `common/`
* helper.h
* Contains functions reading data from input file and golden output file. It is included by init_buff.h file
* init_buff.h
* Generate input data and golden output data. It is used in hw/tb/system.cpp and sw/linux/app/mriq.c.
* sw_exec.h
* It is only used in sw/linux/app/mriq.c. sw_exec() measures executing time of software computation.
* utils.h
* Has two functions: init\_parameters() and validate\_buffer(). They are used by hw/tb/system.cpp, sw/baremetal/mriq.c, sw/linux/app/mriq.c

### Testing Instructions:
#### Testing with testbench
The file path and name are specified in hls/project.tcl. We hardcoded the test file names and path in hls/project.tcl as hw/data/test\_small.bin and hw/data/test\_small.out. Its configuration parameters are [batch\_size\_x, num\_batch\_x, batch\_size\_k, num\_batch\_k] = [4, 1, 16, 1]. If you want to use other paramters, you can firstly specify them in tb/system.hpp file, then use the same parameters to generate the corresponding testing data with programs in hw/data. You can rename the testing file in project.tcl or use the same name "test\_small"
#### Testing with baremetal app
We can generate the corresponding test data with the two programs under hw/data/ folder. The instructions of how to generate test data are in the README file of hw/data/. We then set the configuration parameters in sw/baremetal/mriq.c and include the file in init\_buf() function.

#### Testing with Linux app

There are three arguments of linux app: name-of-input-file, name-of-golden-outputfile, and the answer to "do you want to run software program of this accelerator?". For example:
> ./mriq_stratus.exe test_small.bin test_small.out 0
The 3rd argment tells the linux app whether you want to run the software code of computation and measure its execution time on FPGA. "0" means "No" and "1" is "Yes". Files should be transfered to the ~/applications/test/ folder on Linux.
158 changes: 158 additions & 0 deletions accelerators/stratus_hls/mriq_stratus/common/helper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/***************************************************************************
*cr
*cr (C) Copyright 2007 The Board of Trustees of the
*cr University of Illinois
*cr All Rights Reserved
*cr
***************************************************************************/

#include <endian.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <inttypes.h>
#include <math.h>


#include <string.h>


#define Pix2 6.2831853071795864769252867665590058f

#ifdef __cplusplus
extern "C" {
#endif


void inputData(const char* fName, int* _numK, int* _numX,
float** kx, float** ky, float** kz,
float** x, float** y, float** z,
float** phiR, float** phiI);

void outputData(const char* fName, float** outR, float** outI, int* numX);

void ComputeQ(int numK, int numX,
float *plm_kx, float *plm_ky, float *plm_kz,
float* plm_x, float* plm_y, float* plm_z,
float *plm_phiR, float *plm_phiI,
float *plm_Qr, float *plm_Qi);
void createDataStructsforCompute(int numX, float** Qr, float** Qi);


#ifdef __cplusplus
}
#endif

void inputData(const char* fName, int * _numK, int* _numX,
float** kx, float** ky, float** kz,
float** x, float** y, float** z,
float** phiR, float** phiI)
{


FILE* fid = fopen(fName, "r");
int numK, numX;

if (fid == NULL)
{
fprintf(stderr, "Cannot open input file\n");
exit(-1);
}
fread (&numK, sizeof (int), 1, fid);
*_numK = numK;

fread (&numX, sizeof (int), 1, fid);
*_numX = numX;


*kx = (float *) memalign(16, numK * sizeof (float));
fread (*kx, sizeof (float), numK, fid);
*ky = (float *) memalign(16, numK * sizeof (float));
fread (*ky, sizeof (float), numK, fid);
*kz = (float *) memalign(16, numK * sizeof (float));
fread (*kz, sizeof (float), numK, fid);
*x = (float *) memalign(16, numX * sizeof (float));
fread (*x, sizeof (float), numX, fid);
*y = (float *) memalign(16, numX * sizeof (float));
fread (*y, sizeof (float), numX, fid);
*z = (float *) memalign(16, numX * sizeof (float));
fread (*z, sizeof (float), numX, fid);
*phiR = (float *) memalign(16, numK * sizeof (float));
fread (*phiR, sizeof (float), numK, fid);
*phiI = (float *) memalign(16, numK * sizeof (float));
fread (*phiI, sizeof (float), numK, fid);
fclose (fid);


}





void outputData(const char* fName, float** outR, float** outI, int* _numX)
{
int numX;
FILE* fid = fopen(fName, "r");

if (fid == NULL)
{
fprintf(stderr, "Cannot open output file\n");
exit(-1);
}


fread(&numX, sizeof(int), 1, fid);
*_numX = numX;


*outR = (float *) memalign(16, numX * sizeof (float));
fread(*outR, sizeof(float), numX, fid);

*outI = (float *) memalign(16, numX * sizeof (float));
fread(*outI, sizeof(float), numX, fid);
fclose (fid);
}


void ComputeQ(int numK, int numX,
float *plm_kx, float *plm_ky, float *plm_kz,
float* plm_x, float* plm_y, float* plm_z,
float *plm_phiR, float *plm_phiI,
float *plm_Qr, float *plm_Qi) {
float expArg;
float cosArg;
float sinArg;
float phiMag;
int indexK, indexX;
for (indexX = 0; indexX < numX; indexX++) {
// Sum the contributions to this point over all frequencies
float Qracc = 0.0f;
float Qiacc = 0.0f;
for (indexK = 0; indexK < numK; indexK++) {
phiMag = plm_phiR[indexK]*plm_phiR[indexK] + plm_phiI[indexK]*plm_phiI[indexK];


expArg = Pix2 * (plm_kx[indexK] * plm_x[indexX] +
plm_ky[indexK] * plm_y[indexX] +
plm_kz[indexK] * plm_z[indexX]);
cosArg = cosf(expArg);
sinArg = sinf(expArg);

Qracc += phiMag * cosArg;
Qiacc += phiMag * sinArg;
}
plm_Qr[indexX] = Qracc;
plm_Qi[indexX] = Qiacc;
}
}


void createDataStructsforCompute(int numX, float** Qr, float** Qi)
{

*Qr = (float*) memalign(16, numX * sizeof (float));
memset((void *)*Qr, 0, numX * sizeof(float));
*Qi = (float*) memalign(16, numX * sizeof (float));
memset((void *)*Qi, 0, numX * sizeof(float));
}
116 changes: 116 additions & 0 deletions accelerators/stratus_hls/mriq_stratus/common/init_buff.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include "helper.h"

// init_buffer function can't be used in baremetal app




void init_buffer(float *in, float *gold,
const char* inputFile,
const char* goldFile,
int32_t batch_size_x, int32_t num_batch_x,
int32_t batch_size_k, int32_t num_batch_k)
{

int numX_bm, numK_bm;
float *kx, *ky, *kz, *x, *y, *z, *phiR, *phiI;

inputData(inputFile,
&numK_bm,
&numX_bm,
&kx, &ky, &kz,
&x, &y, &z,
&phiR, &phiI);


int i, j;
int offset_idx = 0;
int idx_single;


for(i=0; i < num_batch_k; i++) {

idx_single = i * batch_size_k;


for(j=0; j < batch_size_k; j++)
in[offset_idx + j] = kx[idx_single + j];

offset_idx += batch_size_k; // 1

for(j=0; j < batch_size_k; j++)
in[offset_idx + j] = ky[idx_single + j];

offset_idx += batch_size_k; // 2

for(j=0; j < batch_size_k; j++)
in[offset_idx + j] = kz[idx_single + j];

offset_idx += batch_size_k; // 3

for(j=0; j < batch_size_k; j++)
in[offset_idx + j] = phiR[idx_single + j];

offset_idx += batch_size_k; // 4

for(j=0; j < batch_size_k; j++)
in[offset_idx + j] = phiI[idx_single + j];

offset_idx += batch_size_k; // 5
}


for(i = 0; i < num_batch_x; i++) {
idx_single = i * batch_size_x;

for(j=0; j < batch_size_x; j++)
in[offset_idx + j] = x[idx_single + j];

offset_idx += batch_size_x; // 1

for(j=0; j < batch_size_x; j++)
in[offset_idx + j] = y[idx_single + j];

offset_idx += batch_size_x; // 2

for(j=0; j < batch_size_x; j++)
in[offset_idx + j] = z[idx_single + j];

offset_idx += batch_size_x; // 3
}


// read golden output from files and store to gold buf

float *Qr, *Qi;
outputData(goldFile, &Qr, &Qi, &numX_bm);

for (int b = 0; b < num_batch_x; b++) {
unsigned base_in = 2 * b * batch_size_x;

unsigned base = b * batch_size_x;

for (int i = 0; i < batch_size_x; i++)
gold[base_in + i] = Qr[base + i];

base_in += batch_size_x;

for (int i = 0; i < batch_size_x; i++)
gold[base_in + i] = Qi[base + i];

}


free(x);
free(y);
free(z);
free(kx);
free(ky);
free(kz);
free(phiR);
free(phiI);

free(Qr);
free(Qi);

}
Loading

0 comments on commit d994018

Please sign in to comment.