Skip to content

Commit

Permalink
PR example
Browse files Browse the repository at this point in the history
  • Loading branch information
niushin committed Jan 21, 2016
1 parent 4180871 commit 5e136d6
Show file tree
Hide file tree
Showing 7 changed files with 331 additions and 0 deletions.
1 change: 1 addition & 0 deletions test/LanguageFeatures/PRImageFilter/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PR design template for image filtering
28 changes: 28 additions & 0 deletions test/LanguageFeatures/PRImageFilter/src/EdgeLaplaceKernel.maxj
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import com.maxeler.maxcompiler.v2.kernelcompiler.Kernel;
import com.maxeler.maxcompiler.v2.kernelcompiler.KernelParameters;
import com.maxeler.maxcompiler.v2.kernelcompiler.types.base.DFEVar;

public class EdgeLaplaceKernel extends Kernel {
public EdgeLaplaceKernel(KernelParameters parameters, int width) {
super(parameters);

optimization.pushEnableBitGrowth(true);

DFEVar inStream = io.input("input", dfeUInt(8));

DFEVar window[] = new DFEVar[5];
window[0] = stream.offset(inStream, -3 * width);
window[1] = stream.offset(inStream, -3);
window[2] = inStream;
window[3] = stream.offset(inStream, 3);
window[4] = stream.offset(inStream, 3 * width);

DFEVar sum = constant.var(0);
for (int i = 0; i < 5; i++)
sum += (i != 2) ? window[i] : window[i] * -4;

DFEVar result = sum > 0 ? sum : -sum;

io.output("output", dfeUInt(8)) <== result.cast(dfeUInt(8));
}
}
36 changes: 36 additions & 0 deletions test/LanguageFeatures/PRImageFilter/src/GaussianBlurKernel.maxj
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import com.maxeler.maxcompiler.v2.kernelcompiler.Kernel;
import com.maxeler.maxcompiler.v2.kernelcompiler.KernelParameters;
import com.maxeler.maxcompiler.v2.kernelcompiler.types.base.DFEVar;

public class GaussianBlurKernel extends Kernel{

public GaussianBlurKernel(KernelParameters parameters, int width) {
super(parameters);

optimization.pushEnableBitGrowth(true);

DFEVar inStream = io.input("input", dfeUInt(8));

DFEVar window[] = new DFEVar[9];
int i = 0;
for (int x = -3; x <= 3; x += 3) {
for (int y = -3; y <= 3; y += 3) {
window[i++] = stream.offset(inStream, x * width + y);
}
}

DFEVar sum = constant.var(0);
for (int j = 0; j < 9; j++) {
if (j % 2 == 0 && j != 4)
sum += window[j];
else if (j == 4)
sum += window[j] * 4;
else
sum += window[j] * 2;
}

DFEVar result = sum / 16;

io.output("output", dfeUInt(8)) <== result.cast(dfeUInt(8));
}
}
37 changes: 37 additions & 0 deletions test/LanguageFeatures/PRImageFilter/src/GrayScaleKernel.maxj
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import com.maxeler.maxcompiler.v2.kernelcompiler.Kernel;
import com.maxeler.maxcompiler.v2.kernelcompiler.KernelParameters;
import com.maxeler.maxcompiler.v2.kernelcompiler.types.base.DFEVar;

public class GrayScaleKernel extends Kernel {
public GrayScaleKernel(KernelParameters parameters) {
super(parameters);

optimization.pushEnableBitGrowth(true);

DFEVar inStream = io.input("input", dfeUInt(8));

DFEVar countColour = control.count.simpleCounter(2, 3);

DFEVar r = control.mux(countColour,
inStream,
stream.offset(inStream, -1),
stream.offset(inStream, -2));

DFEVar g = control.mux(countColour,
stream.offset(inStream, 1),
inStream,
stream.offset(inStream, -1));

DFEVar b = control.mux(countColour,
stream.offset(inStream, 2),
stream.offset(inStream, 1),
inStream);

DFEVar sum = r + g + b;

DFEVar result = sum / 3;

io.output("output", dfeUInt(8)) <== result.cast(dfeUInt(8));
}
}

132 changes: 132 additions & 0 deletions test/LanguageFeatures/PRImageFilter/src/PRImageFilter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "Maxfiles.h"
#include "MaxSLiCInterface.h"

extern void max_reconfig_partial_bitstream(max_engine_t *engine, const char* name);

const char* in_filename = "lena.ppm";
const char* out_filename = "lena_filtered.ppm";
const char* golden_filename = "lena_filtered_golden.ppm";


void loadImage(const char *filename, uint8_t **dest, uint64_t *width_out, uint64_t *height_out)
{
char buffer[128];
FILE *file = fopen(filename, "r");
if (file == NULL)
{
printf("Error opening file %s.", filename);
exit(1);
}

fgets(buffer, sizeof(buffer), file); // Type
if (strcmp(buffer, "P3\n"))
{
printf("Error opening file %s. Only P3 format supported", filename);
exit(1);
}

fgets(buffer, sizeof(buffer), file); // Comment
int width, height;
fscanf(file, "%d %d\n", &width, &height); // Dimensions
if (width != 256 || height != 256)
{
printf("Image size must be 256x256\n");
exit(1);
}

fgets(buffer, sizeof(buffer), file); // Max intensity

*dest = malloc(width * height * 3);

for(int i = 0; i < width * height * 3; i++) {
uint8_t v;
fscanf(file, "%hhu", &v);
(*dest)[i] = v;
}

fclose(file);

*width_out = width;
*height_out = height;
}


void writeImage(const char *filename, uint8_t *data, uint64_t width, uint64_t height)
{
FILE *file = fopen(filename, "w");

fprintf(file, "P3\n"); // Type
fprintf(file, "#generated\n"); // Comment
fprintf(file, "%d %d\n", (int) width, (int) height); // Dimensions
fprintf(file, "255\n"); // Max intensity

for(uint64_t i = 0; i < width * height * 3; i++)
fprintf(file, "%d\n", data[i]);

fclose(file);
}

int checkResult(uint8_t *result) {
uint8_t *golden;
uint64_t width, height;
loadImage(golden_filename, &golden, &width, &height);

for (uint64_t i = 0; i < width * height; i++) {
if (result[i] != golden[i]) {
free(golden);
return 1;
}
}

free(golden);
return 0;
}

int main(void)
{
printf("Loading image from '%s'\n", in_filename);
uint8_t *in_data;
uint64_t width, height;
loadImage(in_filename, &in_data, &width, &height);

uint64_t data_size = width * height * 3;
uint8_t *out_data = malloc(data_size);
printf("Configuring DFE with full bitstream\n");

max_file_t *maxfile = PRImageFilter_init();
max_engine_t *engine = max_load(maxfile, "*");

printf("Running DFE\n");
PRImageFilter_actions_t myaction = { data_size, in_data, out_data };
PRImageFilter_run(engine, &myaction);

printf("Partially reconfiguring DFE\n");
max_reconfig_partial_bitstream(engine, "EdgeLaplaceKernel");
max_reconfig_partial_bitstream(engine, "ThresholdKernel");

printf("Running DFE\n");
myaction.instream_input = out_data;
PRImageFilter_run(engine, &myaction);

max_unload(engine);

printf("Saving image to '%s'\n", out_filename);
writeImage(out_filename, out_data, width, height);

printf("Checking result against '%s'\n", golden_filename);
int ret = checkResult(out_data);
if (!ret)
printf("Result correct\n");
else
printf("Result incorrect\n");

free(in_data);
free(out_data);

return ret;
}
75 changes: 75 additions & 0 deletions test/LanguageFeatures/PRImageFilter/src/PRImageFilterManager.maxj
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import com.maxeler.maxcompiler.v2.build.EngineParameters;
import com.maxeler.maxcompiler.v2.managers.BuildConfig;
import com.maxeler.maxcompiler.v2.managers.engine_interfaces.CPUTypes;
import com.maxeler.maxcompiler.v2.managers.engine_interfaces.EngineInterface;
import com.maxeler.maxcompiler.v2.managers.engine_interfaces.InterfaceParam;
import com.maxeler.maxcompiler.v2.managers.partial_reconfiguration.PRConfiguration;
import com.maxeler.maxcompiler.v2.managers.partial_reconfiguration.PRManager;
import com.maxeler.maxcompiler.v2.managers.partial_reconfiguration.ReconfigurableBlock;

public class PRImageFilterManager extends PRManager {

private final static int s_width = 256;

public PRImageFilterManager(EngineParameters engineParameters) {
super(engineParameters);

// Instantiate filter kernels
GrayScaleKernel gray = new GrayScaleKernel(makeKernelParameters("GrayScaleKernel"));
GaussianBlurKernel gauss = new GaussianBlurKernel(makeKernelParameters("GaussianBlurKernel"), s_width);
EdgeLaplaceKernel edge = new EdgeLaplaceKernel(makeKernelParameters("EdgeLaplaceKernel"), s_width);
ThresholdKernel thresh = new ThresholdKernel(makeKernelParameters("ThresholdKernel"));

// Create block in clock region X0Y8, capable of taking Kernels 'gray' and 'edge'
ReconfigurableBlock block1 = addReconfigurableBlock("block1", 0, 8, 0, 8, gray, edge);

// Create block in clock region X0Y7, capable of taking Kernels 'gauss' and 'thresh'
ReconfigurableBlock block2 = addReconfigurableBlock("block2", 0, 7, 0, 7, gauss, thresh);

// Connect streams: CPU --> block1 --> block2 --> CPU
block1.getInput("input") <== addStreamFromCPU("input");
block2.getInput("input") <== block1.getOutput("output");
addStreamToCPU("output") <== block2.getOutput("output");
}

private static EngineInterface modeDefault() {
EngineInterface engine_interface = new EngineInterface();

InterfaceParam N = engine_interface.addParam("N", CPUTypes.UINT64);
engine_interface.setTicks("block1", N);
engine_interface.setTicks("block2", N);
engine_interface.setStream("input", CPUTypes.UINT8, N);
engine_interface.setStream("output", CPUTypes.UINT8, N);

return engine_interface;
}

private void configBuild(EngineParameters params) {
BuildConfig buildConfig = getBuildConfig();
buildConfig.setMPPRCostTableSearchRange(params.getMPPRStartCT(), params.getMPPREndCT());
buildConfig.setMPPRParallelism(params.getMPPRThreads());
buildConfig.setMPPRRetryNearMissesThreshold(params.getMPPRRetryThreshold());
}

public static void main(String[] args) {
EngineParameters params = new EngineParameters(args);
PRImageFilterManager manager = new PRImageFilterManager(params);

// Create configuration with GrayScale and GaussianBlur Kernels
PRConfiguration conf1 = new PRConfiguration("conf1");
conf1.setKernel("block1", "GrayScaleKernel");
conf1.setKernel("block2", "GaussianBlurKernel");

// Create configuration with EdgeLaplace and Threshold Kernels
PRConfiguration conf2 = new PRConfiguration("conf2");
conf2.setKernel("block1", "EdgeLaplaceKernel");
conf2.setKernel("block2", "ThresholdKernel");

manager.createSLiCinterface(modeDefault());
manager.configBuild(params);

// Build with conf1 as the default (initial) configuration
manager.build(conf1, conf2);
}
}

22 changes: 22 additions & 0 deletions test/LanguageFeatures/PRImageFilter/src/ThresholdKernel.maxj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import com.maxeler.maxcompiler.v2.kernelcompiler.Kernel;
import com.maxeler.maxcompiler.v2.kernelcompiler.KernelParameters;
import com.maxeler.maxcompiler.v2.kernelcompiler.types.base.DFEVar;

public class ThresholdKernel extends Kernel {
private final static int s_min = 0;
private final static int s_max = 255;
private final static int s_thresh = 10;

public ThresholdKernel(KernelParameters parameters) {
super(parameters);

DFEVar inStream = io.input("input", dfeUInt(8));

DFEVar min = constant.var(dfeUInt(8), s_min);
DFEVar max = constant.var(dfeUInt(8), s_max);

DFEVar result = (inStream > s_thresh) ? max : min;

io.output("output", dfeUInt(8)) <== result;
}
}

0 comments on commit 5e136d6

Please sign in to comment.