Use catch as testbench.

- Still work in progress
- Add tests for other scheduling flavor
This commit is contained in:
DrasLorus 2021-08-03 11:00:54 +02:00
parent 5f7074352a
commit f4ed6956b3
Signed by: moniere
GPG key ID: 188DD5B072181C0F
7 changed files with 226 additions and 84 deletions

View file

@ -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

Binary file not shown.

View file

@ -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

View file

@ -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
// 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);
// }
uint8_t do_max_64(const uint8_t in_array[64]) {
#pragma HLS interface ap_memory port=in_array
uint8_t load_array[64];
#pragma HLS array_partition variable = in_array complete
#pragma HLS array_partition variable = load_array complete
for (uint8_t u = 0; u < 64; u++){
for (uint16_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

View file

@ -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]);
@ -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)> {

View file

@ -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;

View file

@ -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);