diff --git a/applications/ta2/designs/ta2_unb2b_mm_demo/Makefile b/applications/ta2/designs/ta2_unb2b_mm_demo/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..131d1b1dcc12ee06b35992e23d72bdd45136556f --- /dev/null +++ b/applications/ta2/designs/ta2_unb2b_mm_demo/Makefile @@ -0,0 +1,120 @@ +###################### +### SETUP ### +###################### +ifeq ($(VERBOSE),1) +ECHO := +else +ECHO := @ +endif + +# Where is the Intel(R) FPGA SDK for OpenCL(TM) software? +ifeq ($(wildcard $(INTELFPGAOCLSDKROOT)),) +$(error Set INTELFPGAOCLSDKROOT to the root directory of the Intel(R) FPGA SDK for OpenCL(TM) software installation) +endif +ifeq ($(wildcard $(INTELFPGAOCLSDKROOT)/host/include/CL/opencl.h),) +$(error Set INTELFPGAOCLSDKROOT to the root directory of the Intel(R) FPGA SDK for OpenCL(TM) software installation.) +endif + +########################### +### Basic configuration ### +########################### + +# Name of unb2b BSP +UNB2B_BSP=ta2_unb2b_bsp + +# Compile directory +BUILDDIR=$(RADIOHDL_BUILD_DIR)/unb2b/OpenCL/$(lastword $(subst /, ,$(abspath $(dir $(lastword $(MAKEFILE_LIST)))))) + + +############################## +### Advanced Configuration ### +############################## + +CXX= g++ #-mcmodel=medium +CXXFLAGS= -std=c++11 -mavx2 -g -O3 -fopenmp #-DCL_ALTERA +AOC= aoc +AOCFLAGS= -v -g +#AOCRFLAGS+= -fp-relaxed +AOCRFLAGS+= -report +AOCRFLAGS+= -opt-arg=-allow-io-channel-autorun-kernel +#AOCRFLAGS+= -board=p385a_min_ax115_1710240 +AOCOFLAGS+= -board=$(UNB2B_BSP) + +AOCOFLAGS+= -I$(INTELOCLSDKROOT)/include/kernel_headers +AOCXFLAGS+= -bsp-flow=flat +ifneq ("$(SEED)", "") +AOCXFLAGS+= -seed=$(SEED) +endif +INCLUDES= $(shell aocl compile-config) #-I.. +LDFLAGS= $(shell aocl link-config) #-ldl -lacl_emulator_kernel_rt #-lbfd +CXXFLAGS+= $(INCLUDES) + +### Emulator configuration +# Emulation Compilation flags +ifeq ($(DEBUG),1) +EMUCXXFLAGS += -g +else +EMUCXXFLAGS += -O2 +endif + +# Target +TARGET := host +TARGET_DIR := $(BUILDDIR)/bin + +# Directories +INC_DIRS := host/lib/common/inc +LIB_DIRS := + +# Files +INCS := $(wildcard ) +SRCS := $(wildcard host/src/*.cpp host/lib/common/src/*.cpp host/lib/common/src/AOCLUtils/*.cpp) +LIBS := rt pthread + +### Emulator compilation +# Make it all! +%: %.cl $(TARGET_DIR)/$(TARGET) + (unset DISPLAY; mkdir -p $(BUILDDIR)/$* && $(AOC) -march=emulator -DEMULATOR $< -o $(TARGET_DIR)/$@.aocx -legacy-emulator $(AOCOFLAGS) $(AOCRFLAGS)) + +# Host executable target. +$(TARGET_DIR)/$(TARGET) : Makefile $(SRCS) $(INCS) $(TARGET_DIR) + $(ECHO)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -fPIC $(foreach D,$(INC_DIRS),-I$D) \ + $(INCLUDES) $(SRCS) $(LDFLAGS) \ + $(foreach D,$(LIB_DIRS),-L$D) \ + $(foreach L,$(LIBS),-l$L) \ + -o $(TARGET_DIR)/$(TARGET) + +$(TARGET_DIR) : + $(ECHO)mkdir -p $(TARGET_DIR) + +# Standard make targets +clean : + $(ECHO)rm -rf $(TARGET_DIR)/* + + +### Device compilation +%.d: %.cc + -$(CXX) $(CXXFLAGS) -MM -MT $@ -MT ${@:%.d=%.o} $< -o $@ + +%.o: %.cc + $(CXX) -c $(CXXFLAGS) -o $@ $< + +%.aoco: %.cl + (unset DISPLAY; mkdir -p $(BUILDDIR)/$* && cp -a $< $(BUILDDIR)/$* && cd $(BUILDDIR)/$* && $(AOC) -c $(AOCOFLAGS) $< && cd - && cp -a $(BUILDDIR)/$*/$@ .) + +%.aocr: %.aoco + (unset DISPLAY; cp -a $< $(BUILDDIR)/$* && cd $(BUILDDIR)/$* && $(AOC) -rtl $(AOCRFLAGS) $< && cd - && cp -a $(BUILDDIR)/$*/$@ .) + +%.aocx: %.aocr + (unset DISPLAY; cp -a $< $(BUILDDIR)/$* && cd $(BUILDDIR)/$* && $(AOC) $(AOCXFLAGS) $< && cd - && cp -a $(BUILDDIR)/$*/$@ .) + +%.sof: %.aocx + (unset DISPLAY; cp -a $(BUILDDIR)/$*/flat.sof ./$@) + +%.rbf: %.sof + (unset DISPLAY; cp -a $(BUILDDIR)/$*/flat.rbf ./$@) + + +%.build: + test -f $@ || test -f /tmp/stop || (echo `hostname` && cp `basename $* _$(lastword $(subst _, ,$*))`.cl $*.cl && SEED=$(lastword $(subst _, ,$*)) time make -j1 $*.aocx && fgrep MHz $(BUILDDIR)/$*/$*/quartus_sh_compile.log|tail -n 1) >$@ 2>&1 + + diff --git a/applications/ta2/designs/ta2_unb2b_mm_demo/host/lib/common/inc/common.h b/applications/ta2/designs/ta2_unb2b_mm_demo/host/lib/common/inc/common.h new file mode 100644 index 0000000000000000000000000000000000000000..d16ade9618880b8bba4bfcbd42b218f6efb69773 --- /dev/null +++ b/applications/ta2/designs/ta2_unb2b_mm_demo/host/lib/common/inc/common.h @@ -0,0 +1,48 @@ +#include <iostream> +#include <sstream> +#include <fstream> +#include <iomanip> + +#define CL_HPP_ENABLE_EXCEPTIONS +#define CL_HPP_MINIMUM_OPENCL_VERSION 120 +#define CL_HPP_TARGET_OPENCL_VERSION 120 +#define CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY +#include <CL/cl2.hpp> + +void init( + cl::Context &context, + std::vector<cl::Device> &devices); + +void print_platform( + cl::Platform &platform); + +void print_device( + cl::Device &device, + bool marker = false); + +std::string get_source( + std::string& filename); + +std::string get_flags(); + +cl::Program compile_program( + cl::Context& context, + cl::Device& device, + std::string& source); + +void write_source( + std::string& source, + std::string& filename); + +cl::Program get_program( + cl::Context& context, + cl::Device& device, + std::string& filename); + +cl::Kernel get_kernel( + cl::Program& program, + std::string& name); + +double compute_runtime( + cl::Event& start, + cl::Event& end); diff --git a/applications/ta2/designs/ta2_unb2b_mm_demo/host/lib/common/readme.css b/applications/ta2/designs/ta2_unb2b_mm_demo/host/lib/common/readme.css new file mode 100644 index 0000000000000000000000000000000000000000..ce1c649289c93957c5eeefe2dec8a7b9d8b7d36a --- /dev/null +++ b/applications/ta2/designs/ta2_unb2b_mm_demo/host/lib/common/readme.css @@ -0,0 +1,261 @@ +/* +Copyright (C) 2013-2018 Altera Corporation, San Jose, California, USA. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to +whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +This agreement shall be governed in all respects by the laws of the State of California and +by the laws of the United States of America. +*/ + +body { + margin: 0 1em 1em 1em; + font-family: sans-serif; +} +ul { + list-style-type: square; +} +pre, code, kbd, samp, tt { + font-family: monospace, sans-serif; + font-size: 1em; +} + +h1 { + font-size: 200%; + color: #fff; + background-color: #0067a6; + margin: 0 -0.5em; + padding: 0.25em 0.5em; +} +h1 .preheading { + font-size: 40%; + font-weight: normal; +} +h2 { + font-size: 125%; + background-color: #bae5ff; + margin: 1.5em -0.8em 0 -0.8em; + padding: 0.2em 0.8em; +} +h3 { + margin-top: 1.5em; + font-size: 100%; + border-bottom: 1px dotted #000; +} + +table { + border: 2px solid #0067a6; + border-collapse: collapse; +} +th { + border-bottom: 1px solid #0067a6; + border-left: 1px dotted #0067a6; + border-right: 1px dotted #0067a6; + background-color: #bae5ff; + padding: 0.3em; + font-size: 90%; +} +td { + padding: 0.3em; + border: 1px dotted #0067a6; +} + +table.reqs { + margin: 0 auto; +} +table.reqs td { + white-space: nowrap; + text-align: center; +} +table.reqs td:first-child, +table.reqs tr:first-child th:first-child { + text-align: left; +} +table.reqs td.req { + background-color: #b3ef71; + font-size: 150%; + padding: 0 0.3em; +} +table.reqs td.req .either { + font-size: 50%; +} +table.reqs td.unsupported { + white-space: normal; + background-color: #ccc; + max-width: 20em; +} +table.reqs a.note { + text-decoration: none; +} +ol.req-notes > li { + margin-bottom: 0.75em; +} + +table.history { + margin: 0 auto; +} +table.history td { + text-align: center; + vertical-align: top; +} +table.history .changes { + text-align: left; +} +table.history tbody tr:first-child td { + background-color: #b3ef71; +} +table.history ul { + margin: 0; + padding-left: 1em; +} + +table.pkg-contents { + margin: 0 auto; +} +table.pkg-contents th, +table.pkg-contents td { + text-align: left; + vertical-align: top; +} +table.pkg-contents td.path { + font-family: monospace, sans-serif; + font-size: 1em; +} +table.pkg-contents tr.highlight td { + background-color: #ffc; + font-weight: bold; + color: #000; +} +table.pkg-contents td p:first-child { + margin-top: 0; +} +table.pkg-contents td p:last-child { + margin-bottom: 0; +} + +table.parameters { + margin-left: 3em; + margin-right: 3em; + font-family: monospace, sans-serif; + font-size: 1em; +} +table.parameters th, +table.parameters td { + font-family: sans-serif; + text-align: center; + vertical-align: top; +} +table.parameters .name, +table.parameters .desc { + text-align: left; +} +table.parameters .name { + white-space: nowrap; +} +table.parameters td.name, +table.parameters td.default { + font-family: monospace, sans-serif; + font-size: 1em; +} +table.parameters ul { + margin-top: 0; +} +table.parameters td ul:last-child { + margin-bottom: 0; +} + +table.indent { + margin-left: 3em; +} + +.doc .title { + background-color: #eee; + padding: 0.35em; + margin-bottom: 0.5em; +} +.doc .title a { + font-weight: bold; +} +.doc .desc { + margin-left: 2em; + margin-right: 2em; +} + +.left { + text-align: left; +} +.center { + text-align: center; +} +.right { + text-align: right; +} + +.mono { + font-family: monospace, sans-serif; + font-size: 1em; +} +.highlight { + font-weight: bold; + color: #0067a6; +} +.nowrap { + white-space: nowrap; +} + +.command { + font-family: monospace, sans-serif; + font-size: 1em; + margin: 0 3em; + background-color: #ffc; + border: 1px solid #aaa; + padding: 0.5em 1em; +} +.console-output, +.code-block { + display: block; + font-family: monospace, sans-serif; + font-size: 1em; + margin: 0 3em; + background-color: #fff; + border: 1px solid #aaa !important; + padding: 1.8em 1em 0.5em 1em !important; + position: relative; +} +.console-output .heading, +.code-block .heading { + position: absolute; + left: 0; + top: 0; + width: 100%; + font-size: 80%; + text-transform: uppercase; + background-color: #e8e8e8; + padding: 0.3125em 0; + border-bottom: 1px dotted #888; +} +.console-output .heading span, +.code-block .heading span { + padding: 0 1.25em; +} +.not-released { + font-weight: bold; + color: red; +} +.license, +.trademark { + font-size: 80%; +} diff --git a/applications/ta2/designs/ta2_unb2b_mm_demo/host/lib/common/src/common.cpp b/applications/ta2/designs/ta2_unb2b_mm_demo/host/lib/common/src/common.cpp new file mode 100644 index 0000000000000000000000000000000000000000..928b8534b95239c6fa0a29f27640984e5605de17 --- /dev/null +++ b/applications/ta2/designs/ta2_unb2b_mm_demo/host/lib/common/src/common.cpp @@ -0,0 +1,189 @@ +#include "common.h" + +using namespace std; + +ostream &os = clog; + +void init( + cl::Context &context, + vector<cl::Device> &devices) +{ + vector<cl::Platform> platforms; + cl::Platform::get(&platforms); + + // The selected device + int i = 0; + const char *platform_name = getenv("PLATFORM"); + + if (platform_name == 0) + platform_name = getenv("CL_CONTEXT_EMULATOR_DEVICE_INTELFPGA") ? "Intel(R) FPGA Emulation Platform for OpenCL(TM)" : "Intel(R) FPGA SDK for OpenCL(TM)"; + + os << ">>> OpenCL environment: " << endl; + + // Iterate all platforms + for (cl::Platform &platform : platforms) { + print_platform(platform); + bool selected = platform.getInfo<CL_PLATFORM_NAME>() == platform_name; + + // Get devices for the current platform + vector<cl::Device> devices_; + platform.getDevices(CL_DEVICE_TYPE_ALL, &devices_); + + // Iterate all devices + for (cl::Device &device : devices_) { + if (true)//(selected) + devices.push_back(device); + + print_device(device, selected); + i++; + } + } + os << endl; + + if (devices.size() == 0) { + cerr << "Could not find any device in platform " << platform_name << endl; + exit(EXIT_FAILURE); + } + + context = cl::Context(devices); +} + +void print_platform( + cl::Platform &platform) +{ + os << ">>> Platform: " << endl; + os << "Name : " << platform.getInfo<CL_PLATFORM_NAME>() << endl; + os << "Version : " << platform.getInfo<CL_PLATFORM_VERSION>() << endl; + os << "Extensions : " << platform.getInfo<CL_PLATFORM_EXTENSIONS>() << endl; + os << endl; +} + +void print_device( + cl::Device &device, + bool marker) +{ + os << ">>> Device: "; + if (marker) os << " (selected)"; + os << endl; + os << "Name : " << device.getInfo<CL_DEVICE_NAME>() << endl; + os << "Driver version : " << device.getInfo<CL_DRIVER_VERSION>() << endl; + os << "Device version : " << device.getInfo<CL_DEVICE_VERSION>() << endl; + os << "Compute units : " << device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>() << endl; + os << "Clock frequency : " << device.getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>() << " MHz" << endl; + os << "Global memory : " << device.getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>() * 1e-9 << " Gb" << endl; + os << "Local memory : " << device.getInfo<CL_DEVICE_LOCAL_MEM_SIZE>() * 1e-6 << " Mb" << endl; + os << endl; +} + +string get_source( + string& filename) +{ + // Source directory + string srcdir = "./cl"; + + // All helper files to include in build + vector<string> helper_files; + helper_files.push_back("types.cl"); + helper_files.push_back("math.cl"); + + // Store helper files in string + stringstream source_helper_; + + for (int i = 0; i < helper_files.size(); i++) { + // Get source filename + stringstream source_file_name_; + source_file_name_ << srcdir << "/" << helper_files[i]; + string source_file_name = source_file_name_.str(); + + // Read source from file + ifstream source_file(source_file_name.c_str()); + string source(istreambuf_iterator<char>(source_file), + (istreambuf_iterator<char>())); + source_file.close(); + + // Update source helper stream + source_helper_ << source; + } + + string source_helper = source_helper_.str(); + + // Get source filename + stringstream source_file_name_; + source_file_name_ << srcdir << "/" << filename; + string source_file_name = source_file_name_.str(); + + // Read kernel source from file + ifstream source_file(source_file_name.c_str()); + string source_kernel( + istreambuf_iterator<char>(source_file), + (istreambuf_iterator<char>())); + source_file.close(); + + // Construct full source file + stringstream full_source; + full_source << source_helper; + full_source << source_kernel; + + return full_source.str(); +} + +string get_flags() +{ + return string("-cl-fast-relaxed-math"); +} + +void write_source( + string& source, + string& filename) +{ + cout << ">>> Writing source to: " << filename << endl + << endl; + ofstream source_output; + source_output.open(filename, ofstream::out); + source_output << source; + source_output.close(); +} + +cl::Program get_program( + cl::Context& context, + cl::Device& device, + string& filename) +{ + os << ">>> Loading program from binary: " << filename << endl; + try { + ifstream ifs(filename, ios::in | ios::binary); + string str((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>()); + cl::Program::Binaries binaries(1, std::make_pair(str.c_str(), str.length())); + vector<cl::Device> devices; + devices.push_back(device); + os << endl; + return cl::Program(context, devices, binaries); + } catch (cl::Error& error) { + cerr << "Loading binary failed: " << error.what() << endl; + exit(EXIT_FAILURE); + } +} + +cl::Kernel get_kernel( + cl::Program& program, + string& name) +{ + os << ">>> Loading kernel: " << name << endl; + try { + os << endl; + return cl::Kernel(program, name.c_str()); + } catch (cl::Error& error) { + cerr << "Loading kernel failed: " << error.what() << endl; + exit(EXIT_FAILURE); + } +} + +double compute_runtime( + cl::Event& start, + cl::Event& end) +{ + double runtime = 0; + runtime -= start.getProfilingInfo<CL_PROFILING_COMMAND_START>(); + runtime += end.getProfilingInfo<CL_PROFILING_COMMAND_START>(); + return runtime * 1e-9; +} diff --git a/applications/ta2/designs/ta2_unb2b_mm_demo/host/src/main.cpp b/applications/ta2/designs/ta2_unb2b_mm_demo/host/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4eca458dfffc455c1abff5bb81b16f76bf1dd952 --- /dev/null +++ b/applications/ta2/designs/ta2_unb2b_mm_demo/host/src/main.cpp @@ -0,0 +1,111 @@ +/* ************************************************************************* +* Copyright 2020 +* ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +* P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* *********************************************************************** */ + +/* ************************************************************************* +* Author: +* . Reinier vd Walle +* Purpose: +* . Test the ta2_unb2b_mm_demo OpenCL application in emulator +* Description: +* . Run: -> make ta2_unb2b_mm_demo +* . Navigate to -> cd $RADIOHDL_WORK/unb2b/OpenCL/ta2_unb2b_mm_demo/bin +* . Execute -> CL_CONTEXT_EMULATOR_DEVICE_INTELFPGA=1 ./host +* *********************************************************************** */ +#include <CL/cl_ext_intelfpga.h> +#include <iostream> +#include <fstream> +#include <vector> +#include "common.h" +#include <unistd.h> + +using namespace std; +int main(int argc, char **argv) +{ + if (argc > 2) { + cerr << "usage: " << argv[0] << " [ta2_unb2b_mm_demo.aocx]" << endl; + exit(1); + } + + // Initialize OpenCL + cl::Context context; + vector<cl::Device> devices; + init(context, devices); + cl::Device &device = devices[0]; + + // Get program + string filename_bin = string(argc == 2 ? argv[1] : "ta2_unb2b_mm_demo.aocx"); + cl::Program program = get_program(context, device, filename_bin); + + + // Setup command queues + vector<cl::CommandQueue> queues(4); + + for (cl::CommandQueue &queue : queues) { + queue = cl::CommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE); + } + + cl::Event computeDone[4]; + + // Setup FPGA kernels + cl::Kernel mmInController(program, "mm_in_controller"); + cl::Kernel mmOutController(program, "mm_out_controller"); + cl::Kernel processA(program, "process_a"); + cl::Kernel processB(program, "process_b"); + + + // Run FPGA kernels + clog << ">>> Run fpga" << endl; + try { + queues[0].enqueueTask(processA, nullptr, &computeDone[0]); + queues[1].enqueueTask(processB, nullptr, &computeDone[1]); + queues[2].enqueueTask(mmOutController, nullptr, &computeDone[2]); + queues[3].enqueueTask(mmInController, nullptr, &computeDone[3]); + + } catch (cl::Error &error) { + cerr << "Error launching kernel: " << error.what() << endl; + exit(EXIT_FAILURE); + } + + // Write IO channel file + vector<char> cmdVecs[] = {{'A', 'B', 'C', 'D', 0x33, 0x00, 0x00, 0x00, 0x01}, //write on undefined address + {'E', 'F', 'G', 'H', 0x00, 0x00, 0x00, 0x00, 0x01}, // write on addr 0 + {'I', 'J', 'K', 'L', 0x01, 0x00, 0x00, 0x00, 0x01}, // write on addr 1 + {'M', 'N', 'O', 'P', 0x02, 0x00, 0x00, 0x00, 0x01}, // write on addr 2 + {0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00}, // read on undefined address + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // read on addr 0 + {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, // read on addr 1 + {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}}; // read on addr 2 + + ofstream output_fileA("kernel_input_mm"); + ostream_iterator<char> output_iteratorA(output_fileA, ""); + for (int i = 0; i < 8; i++) + copy(cmdVecs[i].begin(), cmdVecs[i].end(), output_iteratorA); + + output_fileA.close(); + clog << ">>> Written IO file" << endl; + + // wait for mm_out_controller to be finished + computeDone[2].wait(); + + // print output IO channel file + const string inputFileB = "kernel_output_mm"; + ifstream fileB(inputFileB); + clog << fileB.rdbuf() << endl; + + return EXIT_SUCCESS; +} diff --git a/applications/ta2/designs/ta2_unb2b_mm_demo/ta2_unb2b_mm_demo.cl b/applications/ta2/designs/ta2_unb2b_mm_demo/ta2_unb2b_mm_demo.cl new file mode 100644 index 0000000000000000000000000000000000000000..77b2c03ff8f5947c91ae061d1796101ea6f38493 --- /dev/null +++ b/applications/ta2/designs/ta2_unb2b_mm_demo/ta2_unb2b_mm_demo.cl @@ -0,0 +1,199 @@ +/* ************************************************************************* +* Copyright 2020 +* ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +* P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* *********************************************************************** */ + +/* ************************************************************************* +* Author: +* . Reinier vd Walle +* Purpose: +* . Demonstrate Monitor and Control interface +* Description: +* . This application implements a way to use the MM IO channels. +* *********************************************************************** */ + +#pragma OPENCL EXTENSION cl_intel_channels : enable + +#include <ihc_apint.h> + +struct mm_in { + uint wrdata; + uint address; + uchar wr; +} __attribute__((packed)); + +struct mm_out { + uint rddata; +} __attribute__((packed)); + + +channel struct mm_in ch_in_mm __attribute__((depth(0))) __attribute__((io("kernel_input_mm"))); +channel struct mm_out ch_out_mm __attribute__((depth(0))) __attribute__((io("kernel_output_mm"))); + + +struct reg { + uint offset; + uint size; +} __attribute__((packed)); + +#define REGISTER_A 0x00 +#define REGISTER_B 0x02 + +#define NR_MM 2 +channel struct mm_in mm_channel_in[NR_MM] __attribute__((depth(0))); +channel struct mm_out mm_channel_out[NR_MM+1] __attribute__((depth(0))); // 1 extra channel for undefined addresses + +__attribute__((max_global_work_dim(0))) +#ifndef EMULATOR +__attribute__((autorun)) +#endif +__kernel void mm_in_controller() +{ + const struct reg regmap[NR_MM] = { + {REGISTER_A, 2}, + {REGISTER_B, 2} + }; + while(1) + { + bool undefined = true; + struct mm_in mm_request = read_channel_intel(ch_in_mm); + #pragma unroll + for (int i = 0; i < NR_MM; i++) + { + if (mm_request.address >= regmap[i].offset && mm_request.address < (regmap[i].offset + regmap[i].size)) + { + undefined = false; + struct mm_in local_mm_request; + local_mm_request.wr = mm_request.wr; + local_mm_request.wrdata = mm_request.wrdata; + local_mm_request.address = mm_request.address - regmap[i].offset; + write_channel_intel(mm_channel_in[i], local_mm_request); + } + } + + if (undefined && mm_request.wr == 0) { // undefined address + struct mm_out zero_response; + zero_response.rddata = 0; + write_channel_intel(mm_channel_out[NR_MM], zero_response); + } + + } +} + +__attribute__((max_global_work_dim(0))) +#ifndef EMULATOR +__attribute__((autorun)) +#endif +__kernel void mm_out_controller() +{ +#ifdef EMULATOR + for(int x = 0; x < 4; ) +#else + while(1) +#endif + { + struct mm_out mm_response; + for (int i = 0; i < NR_MM+1; i++) + { + bool valid; + mm_response = read_channel_nb_intel(mm_channel_out[i], &valid); + if (valid) + { + write_channel_intel(ch_out_mm, mm_response); +#ifdef EMULATOR + x++; +#endif + } + } + } +} + + +__attribute__((max_global_work_dim(0))) +#ifndef EMULATOR +__attribute__((autorun)) +#endif +__kernel void process_a() +{ + uint keep = 0; //address 0, value is stored when written + uint acc = 0; //address 1, value is written value + 1 + while(1){ + struct mm_in mm_request = read_channel_intel(mm_channel_in[0]); + struct mm_out mm_response; + if (0 == mm_request.address){ + if(mm_request.wr > 0) //write request + { + keep = mm_request.wrdata; + } else { //read request + mm_response.rddata = keep; + } + } + + if (1 == mm_request.address){ + if(mm_request.wr > 0) //write request + { + acc = mm_request.wrdata+1; + } else { //read request + mm_response.rddata = acc; + } + } + + if(mm_request.wr == 0) + write_channel_intel(mm_channel_out[0], mm_response); + } +} + + +__attribute__((max_global_work_dim(0))) +#ifndef EMULATOR +__attribute__((autorun)) +#endif +__kernel void process_b() +{ + uint keep = 0; //address 0, value is stored when written + uint acc = 0; //address 1, value is written value + 2 + while(1){ + struct mm_in mm_request = read_channel_intel(mm_channel_in[1]); + struct mm_out mm_response; + if (0 == mm_request.address){ + if(mm_request.wr > 0) //write request + { + keep = mm_request.wrdata; + } else { //read request + mm_response.rddata = keep; + } + } + + if (1 == mm_request.address){ + if(mm_request.wr > 0) //write request + { + acc = mm_request.wrdata+2; + } else { //read request + mm_response.rddata = acc; + } + } + + if(mm_request.wr == 0) + write_channel_intel(mm_channel_out[1], mm_response); + } +} + + +__attribute__((max_global_work_dim(0))) +__kernel void dummy() +{ +} +