Commit 9345165e authored by Andrei Tosa's avatar Andrei Tosa
Browse files

Added testbench

parent 7ab381e4
#include "cont.hpp"
void cont(const unsigned seed, const unsigned count, unsigned *out) {
#pragma HLS INTERFACE m_axi port=out offset=slave bundle=gmem
#pragma HLS INTERFACE s_axilite port=seed bundle=control
#pragma HLS INTERFACE s_axilite port=out bundle=control
#pragma HLS INTERFACE s_axilite port=return bundle=control
#pragma HLS DATAFLOW
stream<unsigned> rndout;
#pragma HLS STREAM variable = rndout depth = 16
rndgen(seed, count, rndout);
for (int i = 0; i < count; i++)
rndout >> out[i];
}
#include "rndgen.hpp"
#include <hls_stream.h>
#include <ap_int.h>
using namespace hls;
using namespace std;
void cont(const unsigned seed, const unsigned count, unsigned *out);
#include "cont.hpp"
int main()
{
unsigned seed = 1;
unsigned count = 50;
unsigned res[100];
cont(seed, count, res);
for (int p = 0; p < count; p++)
{
std::cout << res[p] << ' ';
}
return 0;
}
#pragma once
#define REG_SIZE 32
#define SET_SIZE 10000
#define F1(x, y, z) ((x) ^ ((y) | (z)))
#define F2(x, y, z) (!(x) ^ ((y) | (z)))
#define F(x, y, z) F1((x), (y), (z))
#include "host.hpp"
#include "defines.hpp"
#include <iostream>
#include <fstream>
#include <chrono>
using namespace std::chrono;
int main(int argc, char** argv)
{
uint32_t count;
if (argc == 2) {
count = SET_SIZE;
}
else if (argc == 3) {
count = atoi(argv[2]);
}
else {
std::cout << "Usage: " << argv[0] << " <XCLBIN File> *SET SIZE*" << std::endl;
return EXIT_FAILURE;
}
std::string binaryFile = argv[1];
size_t vector_size_bytes = sizeof(int) * count;
cl_int err;
unsigned fileBufSize;
// Allocate Memory in Host Memory
uint32_t seed = 2;
std::vector<uint32_t,aligned_allocator<uint32_t>> hw_results(SET_SIZE);
std::vector<uint32_t,aligned_allocator<uint32_t>> sw_results(SET_SIZE);
// Create the test data
// for(int i = 0 ; i < count ; i++)
// hw_results[i] = 0;
// populate_results(sw_results, seed);
// OPENCL HOST CODE AREA START
std::vector<cl::Device> devices = get_devices("Xilinx");
devices.resize(1);
cl::Device device = devices[0];
OCL_CHECK(err, cl::Context context(device, NULL, NULL, NULL, &err));
OCL_CHECK(err, cl::CommandQueue q(context, device, CL_QUEUE_PROFILING_ENABLE, &err));
char* fileBuf = read_binary_file(binaryFile, fileBufSize);
cl::Program::Binaries bins{{fileBuf, fileBufSize}};
OCL_CHECK(err, cl::Program program(context, devices, bins, NULL, &err));
OCL_CHECK(err, cl::Kernel krnl_rnd_gen(program,"cont", &err));
OCL_CHECK(err, cl::Buffer buffer_output(context,CL_MEM_USE_HOST_PTR | CL_MEM_WRITE_ONLY, vector_size_bytes, hw_results.data(), &err));
OCL_CHECK(err, err = krnl_rnd_gen.setArg(0, seed));
OCL_CHECK(err, err = krnl_rnd_gen.setArg(1, count));
OCL_CHECK(err, err = krnl_rnd_gen.setArg(2, buffer_output));
std::cout << "* * * RUN STARTED\n";
auto t1 = high_resolution_clock::now();
OCL_CHECK(err, err = q.enqueueTask(krnl_rnd_gen));
OCL_CHECK(err, err = q.enqueueMigrateMemObjects({buffer_output},CL_MIGRATE_MEM_OBJECT_HOST));
q.finish();
auto t2 = high_resolution_clock::now(); //clock_t c2 = clock();
std::cout << "* * * RUN DONE\n";
// OPENCL HOST CODE AREA END
auto d1 = duration_cast<microseconds>(t2 - t1);
std::cout << "Task: " << d1.count() << '\n';
// Compare the results of the Device to the simulation
bool match = true;
/*
std::ofstream fout("results/data.out");
for (int i = 0 ; i < count; i++){
fout << hw_results[i] << '\n';
if (sw_results[i] != hw_results[i]) {
match = false;
std::cout << "Not matched: " << sw_results[i] << ' ' << hw_results[i] << '\n';
break;
}
}
fout.close(); */
delete[] fileBuf;
// std::cout << "TEST " << (match ? "PASSED" : "FAILED") << std::endl;
return (match ? EXIT_SUCCESS : EXIT_FAILURE);
}
#define CL_HPP_CL_1_2_DEFAULT_BUILD
#define CL_HPP_TARGET_OPENCL_VERSION 120
#define CL_HPP_MINIMUM_OPENCL_VERSION 120
#define CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY 1
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
//OCL_CHECK doesn't work if call has templatized function call
#define OCL_CHECK(error,call) \
call; \
if (error != CL_SUCCESS) { \
printf("%s:%d Error calling " #call ", error code is: %d\n", \
__FILE__,__LINE__, error); \
exit(EXIT_FAILURE); \
}
#define DATA_SIZE 100
#include <vector>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <CL/cl2.hpp>
#include "defines.hpp"
template <typename T>
struct aligned_allocator
{
using value_type = T;
T* allocate(std::size_t num)
{
void* ptr = nullptr;
if (posix_memalign(&ptr,4096,num*sizeof(T)))
throw std::bad_alloc();
return reinterpret_cast<T*>(ptr);
}
void deallocate(T* p, std::size_t num)
{
free(p);
}
};
std::vector<cl::Device> get_devices(const std::string& vendor_name) {
size_t i;
cl_int err;
std::vector<cl::Platform> platforms;
OCL_CHECK(err, err = cl::Platform::get(&platforms));
cl::Platform platform;
for (i = 0 ; i < platforms.size(); i++){
platform = platforms[i];
OCL_CHECK(err, std::string platformName = platform.getInfo<CL_PLATFORM_NAME>(&err));
if (platformName == vendor_name){
std::cout << "Found Platform" << std::endl;
std::cout << "Platform Name: " << platformName.c_str() << std::endl;
break;
}
}
if (i == platforms.size()) {
std::cout << "Error: Failed to find Xilinx platform" << std::endl;
exit(EXIT_FAILURE);
}
//Getting ACCELERATOR Devices and selecting 1st such device
std::vector<cl::Device> devices;
OCL_CHECK(err, err = platform.getDevices(CL_DEVICE_TYPE_ACCELERATOR, &devices));
return devices;
}
char* read_binary_file(const std::string &xclbin_file_name, unsigned &nb)
{
std::cout << "INFO: Reading " << xclbin_file_name << std::endl;
if(access(xclbin_file_name.c_str(), R_OK) != 0) {
printf("ERROR: %s xclbin not available please build\n", xclbin_file_name.c_str());
exit(EXIT_FAILURE);
}
//Loading XCL Bin into char buffer
std::cout << "Loading: '" << xclbin_file_name.c_str() << "'\n";
std::ifstream bin_file(xclbin_file_name.c_str(), std::ifstream::binary);
bin_file.seekg (0, bin_file.end);
nb = bin_file.tellg();
bin_file.seekg (0, bin_file.beg);
char *buf = new char [nb];
bin_file.read(buf, nb);
return buf;
}
void populate_results(std::vector<uint32_t,aligned_allocator<uint32_t>> &v, uint32_t seed) {
uint32_t X, Y;
X = seed;
for (uint32_t i = 0; i < SET_SIZE; i++) {
Y = 0;
for (uint32_t j = 0; j < REG_SIZE; j++) {
uint32_t b1 = (X & (1 << ((j + REG_SIZE-1) % REG_SIZE))) >> ((j + REG_SIZE-1) % REG_SIZE);
uint32_t b2 = (X & (1 << j)) >> j;
uint32_t b3 = (X & (1 << ((j + 1) % REG_SIZE))) >> ((j + 1) % REG_SIZE);
uint32_t r = F(b1, b2, b3) << j;
Y |= r;
}
v[i] = Y;
X = Y;
}
}
#include "rndgen.hpp"
void rndgen(
const unsigned int seed,
const unsigned int count,
stream<unsigned> &out
)
{
ap_uint<REG_SIZE> X, Y;
X = seed;
generator: for (int i = 0; i < count; i++) {
#pragma HLS pipeline II=1
for (int j = 1; j < REG_SIZE - 1; j++) {
#pragma HLS unroll factor=30
Y[j] = F(X[j - 1], X[j], X[j+1]);
}
Y[0] = F(X[REG_SIZE - 1], X[0], X[1]);
Y[REG_SIZE - 1] = F(X[REG_SIZE - 2], X[REG_SIZE - 1], X[0]);
out << Y.to_uint();
X = Y;
}
}
#include "defines.hpp"
#include <hls_stream.h>
#include <ap_int.h>
using namespace hls;
using namespace std;
void rndgen(
const unsigned int seed,
const unsigned int count,
stream<unsigned> &out
);
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment