From 5e136d6fb51188ff17dccf244ee7fdde2c204103 Mon Sep 17 00:00:00 2001 From: nx210 Date: Thu, 21 Jan 2016 18:03:20 +0000 Subject: [PATCH] PR example --- test/LanguageFeatures/PRImageFilter/Readme.md | 1 + .../PRImageFilter/src/EdgeLaplaceKernel.maxj | 28 ++++ .../PRImageFilter/src/GaussianBlurKernel.maxj | 36 +++++ .../PRImageFilter/src/GrayScaleKernel.maxj | 37 +++++ .../PRImageFilter/src/PRImageFilter.c | 132 ++++++++++++++++++ .../src/PRImageFilterManager.maxj | 75 ++++++++++ .../PRImageFilter/src/ThresholdKernel.maxj | 22 +++ 7 files changed, 331 insertions(+) create mode 100644 test/LanguageFeatures/PRImageFilter/Readme.md create mode 100644 test/LanguageFeatures/PRImageFilter/src/EdgeLaplaceKernel.maxj create mode 100644 test/LanguageFeatures/PRImageFilter/src/GaussianBlurKernel.maxj create mode 100644 test/LanguageFeatures/PRImageFilter/src/GrayScaleKernel.maxj create mode 100644 test/LanguageFeatures/PRImageFilter/src/PRImageFilter.c create mode 100644 test/LanguageFeatures/PRImageFilter/src/PRImageFilterManager.maxj create mode 100644 test/LanguageFeatures/PRImageFilter/src/ThresholdKernel.maxj diff --git a/test/LanguageFeatures/PRImageFilter/Readme.md b/test/LanguageFeatures/PRImageFilter/Readme.md new file mode 100644 index 0000000..e9fd9c2 --- /dev/null +++ b/test/LanguageFeatures/PRImageFilter/Readme.md @@ -0,0 +1 @@ +PR design template for image filtering diff --git a/test/LanguageFeatures/PRImageFilter/src/EdgeLaplaceKernel.maxj b/test/LanguageFeatures/PRImageFilter/src/EdgeLaplaceKernel.maxj new file mode 100644 index 0000000..14bd59d --- /dev/null +++ b/test/LanguageFeatures/PRImageFilter/src/EdgeLaplaceKernel.maxj @@ -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)); + } +} diff --git a/test/LanguageFeatures/PRImageFilter/src/GaussianBlurKernel.maxj b/test/LanguageFeatures/PRImageFilter/src/GaussianBlurKernel.maxj new file mode 100644 index 0000000..ce389cd --- /dev/null +++ b/test/LanguageFeatures/PRImageFilter/src/GaussianBlurKernel.maxj @@ -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)); + } +} diff --git a/test/LanguageFeatures/PRImageFilter/src/GrayScaleKernel.maxj b/test/LanguageFeatures/PRImageFilter/src/GrayScaleKernel.maxj new file mode 100644 index 0000000..e5daa25 --- /dev/null +++ b/test/LanguageFeatures/PRImageFilter/src/GrayScaleKernel.maxj @@ -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)); + } +} + diff --git a/test/LanguageFeatures/PRImageFilter/src/PRImageFilter.c b/test/LanguageFeatures/PRImageFilter/src/PRImageFilter.c new file mode 100644 index 0000000..b94c21d --- /dev/null +++ b/test/LanguageFeatures/PRImageFilter/src/PRImageFilter.c @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#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; +} diff --git a/test/LanguageFeatures/PRImageFilter/src/PRImageFilterManager.maxj b/test/LanguageFeatures/PRImageFilter/src/PRImageFilterManager.maxj new file mode 100644 index 0000000..a4ad592 --- /dev/null +++ b/test/LanguageFeatures/PRImageFilter/src/PRImageFilterManager.maxj @@ -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); + } +} + diff --git a/test/LanguageFeatures/PRImageFilter/src/ThresholdKernel.maxj b/test/LanguageFeatures/PRImageFilter/src/ThresholdKernel.maxj new file mode 100644 index 0000000..d53e207 --- /dev/null +++ b/test/LanguageFeatures/PRImageFilter/src/ThresholdKernel.maxj @@ -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; + } +}