mirror of
https://github.com/DrasLorus/hls_max_template.git
synced 2024-11-21 12:13:18 +01:00
Use catch as testbench.
- Still work in progress - Add tests for other scheduling flavor
This commit is contained in:
parent
5f7074352a
commit
f4ed6956b3
7 changed files with 226 additions and 84 deletions
17
Makefile
17
Makefile
|
@ -23,7 +23,7 @@
|
|||
|
||||
CXX=g++
|
||||
CXXFLAGS:=-std=c++14 -Wno-unused-label -Wno-unknown-pragmas -Wall -D_MAX_IS_TOP_
|
||||
LDFLAGS:=
|
||||
LDFLAGS:=-lmatio
|
||||
|
||||
XILINX_HOME=/opt/Xilinx
|
||||
XILINX_VER=2020.2
|
||||
|
@ -58,9 +58,6 @@ $(TBBIN): $(OBJ) $(CATCHOBJ)
|
|||
$(CATCHOBJ) :
|
||||
$(CXX) -o $@ -c $(SRCDIR)/testbenches/catch.cpp $(CXXFLAGS)
|
||||
|
||||
%.cpp.o : %.cpp
|
||||
$(CXX) -o $@ -c $< $(CXXFLAGS)
|
||||
|
||||
.PHONY: clean clear
|
||||
clean:
|
||||
rm -vf $(OBJ)
|
||||
|
@ -74,7 +71,17 @@ fullclear: clear
|
|||
rm -vf $(CATCHOBJ)
|
||||
|
||||
testbench: $(TBBIN)
|
||||
cd $(BINDIR); ../$(TBBIN)
|
||||
cd $(BINDIR); ./tb.out
|
||||
|
||||
legacy-testbench: $(BINDIR)/tb_legacy.out
|
||||
cd $(BINDIR); ./tb_legacy.out
|
||||
|
||||
$(BINDIR)/tb_legacy.out: $(SRCDIR)/modules/max.cpp.o $(SRCDIR)/testbenches/max_tb.cpp.o
|
||||
$(CXX) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
|
||||
%.cpp.o : %.cpp
|
||||
$(CXX) -o $@ -c $< $(CXXFLAGS)
|
||||
|
||||
.PHONY: %.compdb_entry
|
||||
%.compdb_entry: %.cpp
|
||||
|
|
BIN
data/input.mat
Normal file
BIN
data/input.mat
Normal file
Binary file not shown.
|
@ -22,15 +22,16 @@
|
|||
############################################################
|
||||
|
||||
open_project -reset max_template
|
||||
set_top do_max_64
|
||||
set_top do_max_redx_64
|
||||
add_files ../sources/modules/max.hpp
|
||||
add_files ../sources/modules/max.cpp -cflags "--std=c++14 -Wno-unknown-pragmas -D_MAX_IS_TOP_"
|
||||
add_files -tb ../sources/testbenches/max_tb.cpp -cflags "--std=c++14 -Wno-unknown-pragmas -D_MAX_IS_TOP_"
|
||||
add_files -tb ../sources/testbenches/catch.cpp -cflags "--std=c++14 -Wno-unknown-pragmas -D_MAX_IS_TOP_"
|
||||
add_files -tb ../sources/testbenches/max_catch_tb.cpp -cflags "--std=c++14 -Wno-unknown-pragmas -D_MAX_IS_TOP_"
|
||||
open_solution -reset "solution" -flow_target vivado
|
||||
set_part {xczu7ev-ffvf1517-3-e}
|
||||
create_clock -period 10 -name default
|
||||
config_export -format ip_catalog -rtl verilog
|
||||
set_directive_top -name do_max_64 "do_max_64"
|
||||
set_directive_top -name do_max_redx_64 "do_max_redx_64"
|
||||
csim_design -O
|
||||
csynth_design
|
||||
cosim_design
|
||||
|
|
|
@ -24,29 +24,18 @@
|
|||
|
||||
#ifdef _MAX_IS_TOP_
|
||||
|
||||
#define IS_EVEN(N) (((N >> 1) << 1) == N)
|
||||
uint16_t do_max_redx_64(const uint16_t in_array[64]) {
|
||||
|
||||
// uint8_t do_max_63(const uint8_t in_array[63]) {
|
||||
// #pragma HLS interface ap_memory port=in_array
|
||||
//#pragma HLS interface ap_memory port = in_array
|
||||
|
||||
// uint8_t load_array[63];
|
||||
// #pragma HLS array_partition variable=load_array complete
|
||||
uint16_t load_array[64];
|
||||
|
||||
// for (uint8_t u = 0; u < 63; u++){
|
||||
// #pragma HLS unroll
|
||||
// load_array[u] = in_array[u];
|
||||
// }
|
||||
|
||||
// return max_template<63>::process(load_array);
|
||||
// }
|
||||
#pragma HLS array_partition variable = in_array complete
|
||||
#pragma HLS array_partition variable = load_array complete
|
||||
|
||||
uint8_t do_max_64(const uint8_t in_array[64]) {
|
||||
#pragma HLS interface ap_memory port=in_array
|
||||
for (uint16_t u = 0; u < 64; u++) {
|
||||
|
||||
uint8_t load_array[64];
|
||||
#pragma HLS array_partition variable=load_array complete
|
||||
|
||||
for (uint8_t u = 0; u < 64; u++){
|
||||
#pragma HLS unroll
|
||||
load_array[u] = in_array[u];
|
||||
}
|
||||
|
@ -54,32 +43,123 @@ uint8_t do_max_64(const uint8_t in_array[64]) {
|
|||
return max_pow2<64>::process(load_array);
|
||||
}
|
||||
|
||||
// float do_max_63f(const float in_array[63]) {
|
||||
// #pragma HLS interface ap_memory port=in_array
|
||||
uint16_t do_max_tail_64(const uint16_t in_array[64]) {
|
||||
|
||||
// float load_array[63];
|
||||
// #pragma HLS array_partition variable=load_array complete
|
||||
#pragma HLS interface ap_memory port = in_array
|
||||
|
||||
// for (uint8_t u = 0; u < 63; u++){
|
||||
// #pragma HLS unroll
|
||||
// load_array[u] = in_array[u];
|
||||
// }
|
||||
uint16_t load_array[64];
|
||||
|
||||
// return max_template<63>::process(load_array);
|
||||
// }
|
||||
#pragma HLS array_partition variable = load_array complete
|
||||
|
||||
// float do_max_64f(const float in_array[64]) {
|
||||
// #pragma HLS interface ap_memory port=in_array
|
||||
for (uint16_t u = 0; u < 64; u++) {
|
||||
|
||||
// float load_array[64];
|
||||
// #pragma HLS array_partition variable=load_array complete
|
||||
#pragma HLS unroll
|
||||
load_array[u] = in_array[u];
|
||||
}
|
||||
|
||||
// for (uint8_t u = 0; u < 64; u++){
|
||||
// #pragma HLS unroll
|
||||
// load_array[u] = in_array[u];
|
||||
// }
|
||||
return max_template<64, TAILED>::process(load_array);
|
||||
}
|
||||
|
||||
// return max_pow2<64>::process(load_array);
|
||||
// }
|
||||
uint16_t do_max_head_64(const uint16_t in_array[64]) {
|
||||
|
||||
#pragma HLS interface ap_memory port = in_array
|
||||
|
||||
uint16_t load_array[64];
|
||||
|
||||
#pragma HLS array_partition variable = load_array complete
|
||||
|
||||
for (uint16_t u = 0; u < 64; u++) {
|
||||
|
||||
#pragma HLS unroll
|
||||
load_array[u] = in_array[u];
|
||||
}
|
||||
|
||||
return max_template<64, HEADED>::process(load_array);
|
||||
}
|
||||
|
||||
uint16_t do_max_loop_64(const uint16_t in_array[64]) {
|
||||
|
||||
#pragma HLS interface ap_memory port = in_array
|
||||
|
||||
uint16_t load_array[64];
|
||||
|
||||
#pragma HLS array_partition variable = load_array complete
|
||||
|
||||
for (uint16_t u = 0; u < 64; u++) {
|
||||
|
||||
#pragma HLS unroll
|
||||
load_array[u] = in_array[u];
|
||||
}
|
||||
|
||||
return max_template<64, LOOPED>::process(load_array);
|
||||
}
|
||||
|
||||
uint16_t do_max_redx_127(const uint16_t in_array[127]) {
|
||||
|
||||
#pragma HLS interface ap_memory port = in_array
|
||||
|
||||
uint16_t load_array[127];
|
||||
|
||||
#pragma HLS array_partition variable = load_array complete
|
||||
|
||||
for (uint16_t u = 0; u < 127; u++) {
|
||||
|
||||
#pragma HLS unroll
|
||||
load_array[u] = in_array[u];
|
||||
}
|
||||
|
||||
return max_template<127>::process(load_array);
|
||||
}
|
||||
|
||||
uint16_t do_max_tail_127(const uint16_t in_array[127]) {
|
||||
|
||||
#pragma HLS interface ap_memory port = in_array
|
||||
|
||||
uint16_t load_array[127];
|
||||
|
||||
#pragma HLS array_partition variable = load_array complete
|
||||
|
||||
for (uint16_t u = 0; u < 127; u++) {
|
||||
|
||||
#pragma HLS unroll
|
||||
load_array[u] = in_array[u];
|
||||
}
|
||||
|
||||
return max_template<127, TAILED>::process(load_array);
|
||||
}
|
||||
|
||||
uint16_t do_max_head_127(const uint16_t in_array[127]) {
|
||||
|
||||
#pragma HLS interface ap_memory port = in_array
|
||||
|
||||
uint16_t load_array[127];
|
||||
|
||||
#pragma HLS array_partition variable = load_array complete
|
||||
|
||||
for (uint16_t u = 0; u < 127; u++) {
|
||||
|
||||
#pragma HLS unroll
|
||||
load_array[u] = in_array[u];
|
||||
}
|
||||
|
||||
return max_template<127, HEADED>::process(load_array);
|
||||
}
|
||||
|
||||
uint16_t do_max_loop_127(const uint16_t in_array[127]) {
|
||||
|
||||
#pragma HLS interface ap_memory port = in_array
|
||||
|
||||
uint16_t load_array[127];
|
||||
|
||||
#pragma HLS array_partition variable = load_array complete
|
||||
|
||||
for (uint16_t u = 0; u < 127; u++) {
|
||||
|
||||
#pragma HLS unroll
|
||||
load_array[u] = in_array[u];
|
||||
}
|
||||
|
||||
return max_template<127, LOOPED>::process(load_array);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,14 +28,18 @@
|
|||
|
||||
#ifdef _MAX_IS_TOP_
|
||||
|
||||
// uint8_t do_max_63(const uint8_t in_array[63]);
|
||||
uint8_t do_max_64(const uint8_t in_array[64]);
|
||||
// float do_max_63f(const float in_array[63]);
|
||||
// float do_max_64f(const float in_array[64]);
|
||||
uint16_t do_max_redx_64(const uint16_t in_array[64]);
|
||||
uint16_t do_max_tail_64(const uint16_t in_array[64]);
|
||||
uint16_t do_max_head_64(const uint16_t in_array[64]);
|
||||
uint16_t do_max_loop_64(const uint16_t in_array[64]);
|
||||
uint16_t do_max_redx_127(const uint16_t in_array[64]);
|
||||
uint16_t do_max_tail_127(const uint16_t in_array[64]);
|
||||
uint16_t do_max_head_127(const uint16_t in_array[64]);
|
||||
uint16_t do_max_loop_127(const uint16_t in_array[64]);
|
||||
|
||||
#endif
|
||||
|
||||
template <uint8_t N>
|
||||
template <unsigned N>
|
||||
struct max_pow2 {
|
||||
template <typename T>
|
||||
static T process(const T values[N]) {
|
||||
|
@ -101,7 +105,6 @@ public:
|
|||
static T process(const T values[N]);
|
||||
};
|
||||
|
||||
|
||||
/* REDUCED when N is odd */
|
||||
|
||||
template <unsigned N>
|
||||
|
@ -154,9 +157,8 @@ template <typename T>
|
|||
T max_reduced<N, true>::process(const T values[N]) {
|
||||
static_assert(N > 2, "N cannot be less than 3!");
|
||||
T half_values[half];
|
||||
#pragma HLS array_partition variable = half_values complete
|
||||
loop_redx_max:
|
||||
for (uint8_t i = 0; i < half; i++) {
|
||||
#pragma HLS unroll
|
||||
const uint8_t j = i << 1;
|
||||
const uint8_t jp1 = j + 1;
|
||||
half_values[i] = (values[j] < values[jp1] ? values[jp1] : values[j]);
|
||||
|
@ -169,7 +171,7 @@ template <typename T>
|
|||
T max_reduced<N, false>::process(const T values[N]) {
|
||||
static_assert(N > 3, "N cannot be less than 3!");
|
||||
T half_values[halfp1];
|
||||
#pragma HLS array_partition variable = half_values complete
|
||||
#pragma HLS array_partition variable=half_values complete
|
||||
for (uint8_t i = 0; i < half; i++) {
|
||||
#pragma HLS unroll
|
||||
const uint8_t j = i << 1;
|
||||
|
@ -180,12 +182,11 @@ T max_reduced<N, false>::process(const T values[N]) {
|
|||
return max_reduced<halfp1, IS_EVEN(halfp1)>::process(half_values);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief User friendly max template
|
||||
*
|
||||
* @tparam N Input Size
|
||||
* @tparam Ver Schedule wanted. Default: REDUCED.
|
||||
* @tparam Ver Schedule wanted. Default: REDUCED
|
||||
*/
|
||||
template <unsigned N, max_type_t Ver = REDUCED>
|
||||
class max_template : public max_reduced<N, IS_EVEN(N)> {
|
||||
|
|
|
@ -24,31 +24,62 @@
|
|||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <matio.h>
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
using std::max_element;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
TEST_CASE("Factorials are computed", "[factorial]") {
|
||||
srand(time(nullptr));
|
||||
string in_file("../data/input.mat");
|
||||
|
||||
vector<uint8_t> to_be_maxed64(64 * 8, 0);
|
||||
for (auto && it : to_be_maxed64) {
|
||||
it = uint8_t(floor(float(rand()) / float(RAND_MAX) * 256.f));
|
||||
}
|
||||
mat_t * mfile = Mat_Open(in_file.c_str(), MAT_ACC_RDONLY);
|
||||
REQUIRE(bool(mfile));
|
||||
|
||||
for (unsigned u = 0; u < to_be_maxed64.size() - 64; u++) {
|
||||
const uint8_t * local_beg = to_be_maxed64.data() + u;
|
||||
const uint8_t * local_end = local_beg + 64;
|
||||
|
||||
const uint8_t max64_value = do_max_64(local_beg);
|
||||
matvar_t * pdata = Mat_VarRead(mfile, "data");
|
||||
REQUIRE(bool(pdata));
|
||||
|
||||
const uint8_t max_64_test = *max_element(local_beg, local_end);
|
||||
uint16_t * data = (uint16_t *) pdata->data;
|
||||
|
||||
REQUIRE(max_64_test == max64_value);
|
||||
vector<uint16_t> in_data(data, data + pdata->dims[1]);
|
||||
|
||||
Mat_VarFree(pdata);
|
||||
Mat_Close(mfile);
|
||||
|
||||
for (unsigned u = 0; u < in_data.size() - 127; u+=64) {
|
||||
const uint16_t * local_beg = in_data.data() + u;
|
||||
const uint16_t * local_end_64 = local_beg + 64;
|
||||
const uint16_t * local_end_127 = local_beg + 127;
|
||||
|
||||
const uint16_t max64_redx = do_max_redx_64(local_beg);
|
||||
const uint16_t max64_tail = do_max_tail_64(local_beg);
|
||||
const uint16_t max64_head = do_max_head_64(local_beg);
|
||||
const uint16_t max64_loop = do_max_loop_64(local_beg);
|
||||
|
||||
const uint16_t max127_redx = do_max_redx_127(local_beg);
|
||||
const uint16_t max127_tail = do_max_tail_127(local_beg);
|
||||
const uint16_t max127_head = do_max_head_127(local_beg);
|
||||
const uint16_t max127_loop = do_max_loop_127(local_beg);
|
||||
|
||||
const uint16_t max_64_test = *max_element(local_beg, local_end_64);
|
||||
const uint16_t max_127_test = *max_element(local_beg, local_end_127);
|
||||
|
||||
REQUIRE(max_64_test == max64_redx);
|
||||
REQUIRE(max_64_test == max64_tail);
|
||||
REQUIRE(max_64_test == max64_head);
|
||||
REQUIRE(max_64_test == max64_loop);
|
||||
REQUIRE(max_127_test == max127_redx);
|
||||
REQUIRE(max_127_test == max127_tail);
|
||||
REQUIRE(max_127_test == max127_head);
|
||||
REQUIRE(max_127_test == max127_loop);
|
||||
}
|
||||
|
||||
// cout << (retval == 0 ? "Test passed. " : "Test failed. ") << endl;
|
||||
|
|
|
@ -24,19 +24,40 @@
|
|||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <matio.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int, char **) {
|
||||
srand(time(nullptr));
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
vector<uint8_t> to_be_maxed64(64 * 8, 0);
|
||||
for (auto && it : to_be_maxed64) {
|
||||
it = uint8_t(floor(float(rand()) / float(RAND_MAX) * 256.f));
|
||||
string in_file("../data/input.mat");
|
||||
|
||||
if (argc > 1) {
|
||||
in_file = string(argv[1]);
|
||||
}
|
||||
|
||||
mat_t * mfile = Mat_Open(in_file.c_str(), MAT_ACC_RDONLY);
|
||||
if (!bool(mfile)) {
|
||||
cerr << "Error while opening " << in_file << "." << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
matvar_t * pdata = Mat_VarRead(mfile, "data");
|
||||
if (!bool(pdata)) {
|
||||
cerr << "Error while opening " << in_file << "." << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
uint16_t * data = (uint16_t *) pdata->data;
|
||||
|
||||
vector<uint16_t> in_data(data, data + pdata->dims[1]);
|
||||
|
||||
Mat_VarFree(pdata);
|
||||
Mat_Close(mfile);
|
||||
|
||||
// vector<uint8_t> to_be_maxed63(63, 0);
|
||||
// for (auto && it : to_be_maxed63) {
|
||||
// it = uint8_t(floor(float(rand()) / float(RAND_MAX) * 256.f));
|
||||
|
@ -53,11 +74,11 @@ int main(int, char **) {
|
|||
// }
|
||||
|
||||
int retval = 0;
|
||||
for (unsigned u = 0; u < to_be_maxed64.size() - 64; u++) {
|
||||
const uint8_t * local_beg = to_be_maxed64.data() + u;
|
||||
const uint8_t * local_end = local_beg + 64;
|
||||
for (unsigned u = 0; u < in_data.size(); u += 64) {
|
||||
const uint16_t * local_beg = in_data.data() + u;
|
||||
const uint16_t * local_end = local_beg + 64;
|
||||
|
||||
const uint8_t max64_value = do_max_64(local_beg);
|
||||
const uint16_t max64_value = do_max_redx_64(local_beg);
|
||||
// const uint8_t max63_value = do_max_63(to_be_maxed63.data());
|
||||
// const float max64f_value = do_max_64f(to_be_maxed64f.data());
|
||||
// const float max63f_value = do_max_63f(to_be_maxed63f.data());
|
||||
|
@ -65,12 +86,13 @@ int main(int, char **) {
|
|||
// cout << unsigned(max64_value) << " " << unsigned(max63_value) << endl;
|
||||
// cout << float(max64f_value) << " " << float(max63f_value) << endl;
|
||||
|
||||
const uint8_t max_64_test = *max_element(local_beg, local_end);
|
||||
const uint16_t max_64_test = *max_element(local_beg, local_end);
|
||||
// const uint8_t max_63_test = *max_element(to_be_maxed63.begin(), to_be_maxed63.end());
|
||||
// const float max_64f_test = *max_element(to_be_maxed64f.begin(), to_be_maxed64f.end());
|
||||
// const float max_63f_test = *max_element(to_be_maxed63f.begin(), to_be_maxed63f.end());
|
||||
|
||||
retval += (max_64_test == max64_value ? 0 : 1);
|
||||
// cout << max_64_test << " == " << max64_value << endl;
|
||||
// retval += (max_63_test == max63_value ? 0 : 1);
|
||||
// retval += (max_64f_test == max64f_value ? 0 : 1);
|
||||
// retval += (max_63f_test == max63f_value ? 0 : 1);
|
||||
|
|
Loading…
Reference in a new issue