mirror of
https://github.com/DrasLorus/CORDIC_Rotate_APFX.git
synced 2024-11-21 20:23:16 +01:00
GNU 4.6 (consequently Xilinx 2019.1) is finally supported
- if GNU version is less than 6.2: * Catch2 is disabled, a custom unit test is used instead, * Constexpr keyword is largely removed and less used (performance loss), * Only ML Cordic/Roms are compiled and tested. - Perfect compilation on g++ v4.6.4, should work on Vivado HLS (g++ v4.6.3).
This commit is contained in:
parent
25255802f1
commit
6afa99d7a1
12 changed files with 355 additions and 69 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -10,4 +10,5 @@ compile_commands.json
|
|||
RomGenerators/sources/main_generator_??*_*.cpp
|
||||
sources/CCordicRotateRom/CCordicRotateRom_*.?pp
|
||||
sources/CordicRoms/cordic_rom_*.?pp
|
||||
sources/tb/cordic_rom_tb_??*_*.?pp
|
||||
sources/tb/catchy/cordic_rom_tb_??*_*.?pp
|
||||
sources/tb/catch_less/cordic_rom_aptypes_tb_??*_*.?pp
|
|
@ -15,10 +15,20 @@
|
|||
# If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
cmake_minimum_required (VERSION 3.16.0 FATAL_ERROR)
|
||||
cmake_minimum_required (VERSION 3.18.0 FATAL_ERROR)
|
||||
# setting this is required
|
||||
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
project (
|
||||
CordicRotate
|
||||
LANGUAGES CXX
|
||||
VERSION 0.1
|
||||
)
|
||||
|
||||
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.2))
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
else ()
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
endif ()
|
||||
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set (CMAKE_CXX_EXTENSIONS OFF)
|
||||
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib)
|
||||
|
@ -27,20 +37,13 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../bin)
|
|||
|
||||
set (CMAKE_EXPORT_COMPILE_COMMANDS true)
|
||||
|
||||
project (
|
||||
CordicRotate
|
||||
LANGUAGES CXX
|
||||
VERSION 0.1
|
||||
)
|
||||
|
||||
# ##################################################################################################
|
||||
# Options
|
||||
# ##################################################################################################
|
||||
|
||||
option (EXPORT_COMMANDS "export compile commands, for use with clangd for example." ON)
|
||||
option (ENABLE_XILINX "use Xilinx provided proprietary headers." OFF)
|
||||
|
||||
option (ENABLE_TESTING "use Catch2 in conjunction with CTest as a test suite." ON)
|
||||
option (ENABLE_TESTING "use Catch2 (if possible) in conjunction with CTest as a test suite." ON)
|
||||
option (ENABLE_SOFTWARE
|
||||
"use C++ standard library types (like std::complex). Unsuitable for synthesis." ON
|
||||
)
|
||||
|
@ -65,7 +68,7 @@ if (ENABLE_XILINX)
|
|||
)
|
||||
set (
|
||||
XILINX_VER
|
||||
"2020.2"
|
||||
"2019.1"
|
||||
CACHE STRING "Xilinx software version to use."
|
||||
)
|
||||
|
||||
|
@ -169,10 +172,15 @@ target_link_libraries (cordic_rom_gen PUBLIC romgen)
|
|||
file (GLOB ALL_CORDIC_ROM_SOURCES sources/CCordicRotateRom/*.cpp)
|
||||
list (REMOVE_ITEM ALL_CORDIC_ROM_SOURCES sources/CCordicRotateRom/${CORDIC_ROM_SOURCE})
|
||||
|
||||
add_library (
|
||||
cordic STATIC sources/CCordicRotateSmart/CCordicRotateSmart.cpp
|
||||
sources/CCordicRotateConstexpr/CCordicRotateConstexpr.cpp ${ALL_CORDIC_ROM_SOURCES}
|
||||
add_library (cordic STATIC ${ALL_CORDIC_ROM_SOURCES})
|
||||
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 6.2
|
||||
)
|
||||
)
|
||||
target_sources (
|
||||
cordic PRIVATE sources/CCordicRotateSmart/CCordicRotateSmart.cpp
|
||||
sources/CCordicRotateConstexpr/CCordicRotateConstexpr.cpp
|
||||
)
|
||||
endif ()
|
||||
target_include_directories (cordic PUBLIC sources)
|
||||
target_include_directories (cordic SYSTEM PUBLIC ${AP_INCLUDE_DIR})
|
||||
target_link_libraries (cordic PUBLIC romgen cordic_rom_gen)
|
||||
|
@ -180,27 +188,63 @@ target_link_libraries (cordic PUBLIC romgen cordic_rom_gen)
|
|||
# ##################################################################################################
|
||||
|
||||
if (ENABLE_TESTING)
|
||||
include (CTest)
|
||||
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.2))
|
||||
string (
|
||||
CONFIGURE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/tb/catch_less/cordic_rom_aptypes_tb_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}_${CORDIC_DIVIDER}.cpp
|
||||
TB_SOURCE
|
||||
)
|
||||
configure_file (sources/tb/catch_less/cordic_rom_aptypes_tb.cpp.in ${TB_SOURCE} @ONLY)
|
||||
|
||||
file (GLOB ALL_ROM_TB_SOURCES sources/tb/catch_less/cordic_rom_aptypes*.cpp)
|
||||
list (REMOVE_ITEM ALL_ROM_TB_SOURCES ${TB_SOURCE})
|
||||
|
||||
get_filename_component (FILE_RADIX ${TB_SOURCE} NAME_WE)
|
||||
add_executable (${FILE_RADIX} ${TB_SOURCE})
|
||||
target_link_libraries (${FILE_RADIX} PRIVATE cordic)
|
||||
|
||||
add_test (
|
||||
NAME ${FILE_RADIX}
|
||||
COMMAND ${FILE_RADIX}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data
|
||||
)
|
||||
|
||||
foreach (TB_FILE ${ALL_ROM_TB_SOURCES})
|
||||
get_filename_component (FILE_RADIX ${TB_FILE} NAME_WE)
|
||||
add_executable (${FILE_RADIX} ${TB_FILE})
|
||||
target_link_libraries (${FILE_RADIX} PRIVATE cordic)
|
||||
|
||||
add_test (
|
||||
NAME ${FILE_RADIX}
|
||||
COMMAND ${FILE_RADIX}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data
|
||||
)
|
||||
endforeach ()
|
||||
|
||||
else ()
|
||||
find_package (Catch2 REQUIRED)
|
||||
|
||||
string (
|
||||
CONFIGURE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/tb/cordic_rom_tb_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}_${CORDIC_DIVIDER}.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/tb/catchy/cordic_rom_tb_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}_${CORDIC_DIVIDER}.cpp
|
||||
TB_SOURCE
|
||||
)
|
||||
configure_file (sources/tb/cordic_rom_tb.cpp.in ${TB_SOURCE} @ONLY)
|
||||
|
||||
add_library (catch_common_${PROJECT_NAME} OBJECT sources/tb/main_catch2.cpp)
|
||||
configure_file (sources/tb/catchy/cordic_rom_tb.cpp.in ${TB_SOURCE} @ONLY)
|
||||
|
||||
add_library (catch_common_${PROJECT_NAME} OBJECT sources/tb/catchy/main_catch2.cpp)
|
||||
target_link_libraries (catch_common_${PROJECT_NAME} PUBLIC Catch2::Catch2)
|
||||
|
||||
file (GLOB ALL_ROM_TB_SOURCES sources/tb/cordic_rom_*.cpp)
|
||||
file (GLOB ALL_ROM_TB_SOURCES sources/tb/catchy/cordic_rom_*.cpp)
|
||||
list (REMOVE_ITEM ALL_ROM_TB_SOURCES ${TB_SOURCE})
|
||||
|
||||
add_executable (cordic_tb sources/tb/cordic_tb.cpp ${TB_SOURCE} ${ALL_ROM_TB_SOURCES})
|
||||
add_executable (cordic_tb sources/tb/catchy/cordic_tb.cpp ${TB_SOURCE} ${ALL_ROM_TB_SOURCES})
|
||||
target_link_libraries (cordic_tb PRIVATE cordic catch_common_${PROJECT_NAME})
|
||||
|
||||
include (CTest)
|
||||
include (Catch)
|
||||
catch_discover_tests (cordic_tb WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
file (GLOB ALL_ROM_HEADERS sources/CordicRoms/cordic_rom_*.hpp)
|
||||
|
|
|
@ -15,10 +15,20 @@
|
|||
# If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
cmake_minimum_required (VERSION 3.16.0 FATAL_ERROR)
|
||||
# setting this is required
|
||||
cmake_minimum_required (VERSION 3.18.0 FATAL_ERROR)
|
||||
# setting this is
|
||||
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
project (
|
||||
CordicRomGenerator
|
||||
LANGUAGES CXX
|
||||
VERSION 0.1
|
||||
)
|
||||
|
||||
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.2))
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
else ()
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
endif ()
|
||||
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set (CMAKE_CXX_EXTENSIONS OFF)
|
||||
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib)
|
||||
|
@ -27,15 +37,14 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../bin)
|
|||
|
||||
set (CMAKE_EXPORT_COMPILE_COMMANDS true)
|
||||
|
||||
project (
|
||||
CordicRomGenerator
|
||||
LANGUAGES CXX
|
||||
VERSION 0.1
|
||||
)
|
||||
set (IS_GNU (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
|
||||
set (IS_GNU_LEGACY ${IS_GNU} AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.2))
|
||||
|
||||
add_library (romgen sources/RomGeneratorML/RomGeneratorML.cpp)
|
||||
if (NOT IS_GNU_LEGACY)
|
||||
target_sources (romgen PUBLIC sources/RomGeneratorConst/RomGeneratorConst.cpp)
|
||||
endif ()
|
||||
|
||||
add_library (
|
||||
romgen sources/RomGeneratorML/RomGeneratorML.cpp sources/RomGeneratorConst/RomGeneratorConst.cpp
|
||||
)
|
||||
target_include_directories (romgen PUBLIC sources)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#ifndef _ROM_GENERATOR_CONST_
|
||||
#define _ROM_GENERATOR_CONST_
|
||||
|
||||
#if __cplusplus >= 201402L || XILINX_MAJOR > 2019
|
||||
|
||||
#include <array>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
|
@ -180,4 +182,5 @@ void generate_rom_header_cst_raw(const char * filename = "rom_cordic.txt") {
|
|||
fprintf(rom_file, "%03d\n\n", uint16_t(rom.rom[rom.max_length - 1]));
|
||||
}
|
||||
|
||||
#endif // STANDARD GUARD
|
||||
#endif // _ROM_GENERATOR_CONST_
|
|
@ -29,6 +29,12 @@
|
|||
|
||||
namespace rcr = rom_cordic_rotate;
|
||||
|
||||
#if __cplusplus >= 201402L || XILINX_MAJOR > 2019
|
||||
#define OWN_CONSTEXPR constexpr
|
||||
#else
|
||||
#define OWN_CONSTEXPR
|
||||
#endif
|
||||
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq, unsigned divider = 2>
|
||||
class CRomGeneratorML {
|
||||
static_assert(In_W > 0, "Inputs can't be on zero bits.");
|
||||
|
@ -38,15 +44,22 @@ class CRomGeneratorML {
|
|||
static_assert(rcr::is_pow_2<divider>(), "divider must be a power of 2.");
|
||||
|
||||
public:
|
||||
#if __cplusplus >= 201402L || XILINX_MAJOR > 2019
|
||||
static constexpr double rotation = rcr::pi / divider;
|
||||
static constexpr double q = Tq;
|
||||
|
||||
static constexpr unsigned max_length = 2 * divider * Tq; // 2pi / (pi / divider) * q
|
||||
static constexpr unsigned addr_length = rcr::needed_bits<max_length - 1>();
|
||||
static constexpr int64_t scale_factor = int64_t(1U << (In_W - 1));
|
||||
|
||||
#else
|
||||
const double rotation;
|
||||
const double q;
|
||||
const unsigned max_length;
|
||||
const unsigned addr_length;
|
||||
const int64_t scale_factor;
|
||||
#endif
|
||||
private:
|
||||
constexpr std::complex<int64_t> cordic_ML(const std::complex<int64_t> & x_in,
|
||||
OWN_CONSTEXPR std::complex<int64_t> cordic_ML(const std::complex<int64_t> & x_in,
|
||||
uint8_t counter) {
|
||||
|
||||
int64_t A = x_in.real();
|
||||
|
@ -73,9 +86,21 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
#if __cplusplus >= 201402L || XILINX_MAJOR > 2019
|
||||
uint8_t rom[max_length];
|
||||
#else
|
||||
uint8_t rom[2 * Tq * divider];
|
||||
#endif
|
||||
|
||||
CRomGeneratorML() {
|
||||
CRomGeneratorML()
|
||||
#if __cplusplus < 201402L
|
||||
: rotation(rcr::pi / divider),
|
||||
q(Tq),
|
||||
max_length(2 * Tq * divider),
|
||||
addr_length(rcr::needed_bits<2 * Tq * divider - 1>()),
|
||||
scale_factor(int64_t(1U << (In_W - 1)))
|
||||
#endif
|
||||
{
|
||||
for (unsigned n = 0; n < max_length; n++) {
|
||||
const double re_x = floor(double(scale_factor - 1) * cos(-rotation / double(q) * double(n)));
|
||||
const double im_x = floor(double(scale_factor - 1) * sin(-rotation / double(q) * double(n)));
|
||||
|
@ -158,4 +183,6 @@ void generate_rom_header_ml_raw(const char * filename) {
|
|||
fprintf(rom_file, "%03d\n\n", uint16_t(rom.rom[rom.max_length - 1]));
|
||||
}
|
||||
|
||||
#undef OWN_CONSTEXPR
|
||||
|
||||
#endif // _ROM_GENERATOR_ML
|
|
@ -36,7 +36,7 @@ constexpr double inv_pi = 1 / pi;
|
|||
constexpr double two_pi = 2 * pi;
|
||||
constexpr double inv_2pi = 0.5 * inv_pi;
|
||||
|
||||
#if XILINX_MAJOR > 2019 || !defined (XILINX_MAJOR)
|
||||
#if __cplusplus >= 201402L || XILINX_MAJOR > 2019
|
||||
|
||||
constexpr uint32_t needed_bits(uint32_t value) {
|
||||
uint32_t result = 0;
|
||||
|
|
|
@ -26,8 +26,15 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
#if __cplusplus >= 201402L || XILINX_MAJOR > 2019
|
||||
#define OWN_CONSTEXPR constexpr
|
||||
#else
|
||||
#define OWN_CONSTEXPR
|
||||
#endif
|
||||
|
||||
template <unsigned NStages>
|
||||
constexpr complex<int64_t> cordic(complex<int64_t> x_in,
|
||||
OWN_CONSTEXPR complex<int64_t> cordic(
|
||||
complex<int64_t> x_in,
|
||||
uint8_t counter,
|
||||
const uint8_t * rom_cordic) {
|
||||
|
||||
|
@ -54,18 +61,7 @@ constexpr complex<int64_t> cordic(complex<int64_t> x_in,
|
|||
return {A, B};
|
||||
}
|
||||
|
||||
template <unsigned NStages>
|
||||
void checkMC() {
|
||||
const CRomGeneratorML<16, NStages, 64> rom;
|
||||
|
||||
string fn = "result_MC_W16_S" + to_string(NStages) + "_Q64.dat";
|
||||
ofstream res_file(fn);
|
||||
|
||||
for (unsigned u = 0; u < rom.max_length; u++) {
|
||||
auto res = cordic<NStages>(4096, u, rom.rom);
|
||||
res_file << double(res.real() * 155) / 1048576. << ", " << double(res.imag() * 155) / 1048576. << endl;
|
||||
}
|
||||
}
|
||||
#if __cplusplus >= 201402L || XILINX_MAJOR > 2019
|
||||
|
||||
template <unsigned NStages>
|
||||
void checkConst() {
|
||||
|
@ -80,6 +76,34 @@ void checkConst() {
|
|||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <unsigned,unsigned,unsigned>
|
||||
void generate_rom_header_cst_raw(const string &) {}
|
||||
|
||||
template <unsigned,unsigned,unsigned>
|
||||
void generate_rom_header_cst(const string &) {}
|
||||
|
||||
template <unsigned>
|
||||
void checkConst() {}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
template <unsigned NStages>
|
||||
void checkMC() {
|
||||
const CRomGeneratorML<16, NStages, 64, 2> rom;
|
||||
|
||||
string fn = "result_MC_W16_S" + to_string(NStages) + "_Q64.dat";
|
||||
ofstream res_file(fn);
|
||||
|
||||
for (unsigned u = 0; u < rom.max_length; u++) {
|
||||
complex<int64_t> res = cordic<NStages>(4096, u, rom.rom);
|
||||
res_file << double(res.real() * 155) / 1048576. << ", " << double(res.imag() * 155) / 1048576. << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
|
||||
uint8_t stages;
|
||||
|
|
|
@ -73,7 +73,7 @@ public:
|
|||
return in * kn_i / 16U;
|
||||
}
|
||||
|
||||
#if !defined(__SYNTHESIS__) && defined(SOFTWARE)
|
||||
#if !defined(__SYNTHESIS__) && defined(SOFTWARE) && __cplusplus >= 201402L
|
||||
static constexpr std::complex<int64_t> cordic(std::complex<int64_t> x_in,
|
||||
uint8_t counter) {
|
||||
|
||||
|
@ -124,7 +124,7 @@ public:
|
|||
const ap_uint<8> & counter,
|
||||
ap_int<Out_W> & re_out, ap_int<Out_W> & im_out) {
|
||||
|
||||
const ap_uint<nb_stages + 1> R = cordic_roms::@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@[counter];
|
||||
const ap_uint<nb_stages + 1> R = *(cordic_roms::@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@ + counter);
|
||||
|
||||
ap_int<Out_W> A = bool(R[0]) ? ap_int<In_W>(-re_in) : re_in;
|
||||
ap_int<Out_W> B = bool(R[0]) ? ap_int<In_W>(-im_in) : im_in;
|
||||
|
|
179
sources/tb/catch_less/cordic_rom_aptypes_tb.cpp.in
Normal file
179
sources/tb/catch_less/cordic_rom_aptypes_tb.cpp.in
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2022 Camille "DrasLorus" Monière.
|
||||
*
|
||||
* This file is part of CORDIC_Rotate_APFX.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "CCordicRotateRom/CCordicRotateRom_@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef CCordicRotateRom<4, @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@, @CORDIC_DIVIDER@> cordic_rom;
|
||||
|
||||
template <unsigned n_lines>
|
||||
int section_1() {
|
||||
// SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@ - div:@CORDIC_DIVIDER@") {}
|
||||
|
||||
int counted_errors = 0;
|
||||
|
||||
static constexpr cordic_rom cordic {};
|
||||
|
||||
string input_fn = "../data/input.dat";
|
||||
|
||||
constexpr double rotation = cordic_rom::rotation;
|
||||
constexpr double q = cordic_rom::q;
|
||||
constexpr uint64_t cnt_mask = 0xFF; // Value dependant of the way the ROM is initialized
|
||||
|
||||
constexpr unsigned Out_W = cordic_rom::Out_W;
|
||||
constexpr unsigned In_W = cordic_rom::In_W;
|
||||
|
||||
ap_int<In_W> values_re_in[n_lines];
|
||||
ap_int<In_W> values_im_in[n_lines];
|
||||
ap_int<Out_W> values_re_out[n_lines];
|
||||
ap_int<Out_W> values_im_out[n_lines];
|
||||
|
||||
double results_re[n_lines];
|
||||
double results_im[n_lines];
|
||||
|
||||
FILE * INPUT = fopen(input_fn.c_str(), "r");
|
||||
|
||||
// Init test vector
|
||||
for (unsigned i = 0; i < n_lines; i++) {
|
||||
double a, b, r;
|
||||
fscanf(INPUT, "%lf,%lf,%lf\n", &a, &b, &r);
|
||||
|
||||
const complex<double> c {a, b};
|
||||
values_re_in[i] = int64_t(a * double(cordic_rom::in_scale_factor));
|
||||
values_im_in[i] = int64_t(b * double(cordic_rom::in_scale_factor));
|
||||
|
||||
const complex<double> e = c * exp(complex<double>(0., rotation / q * (i & cnt_mask)));
|
||||
results_re[i] = e.real();
|
||||
results_im[i] = e.imag();
|
||||
}
|
||||
|
||||
fclose(INPUT);
|
||||
|
||||
constexpr double abs_margin = double(1 << cordic.Out_I) * 2. / 100.;
|
||||
|
||||
// Executing the CORDIC
|
||||
for (unsigned iter = 0; iter < n_lines; iter++) {
|
||||
// Execute
|
||||
const uint8_t counter = uint8_t(iter & cnt_mask);
|
||||
|
||||
cordic_rom::cordic(
|
||||
values_re_in[iter], values_im_in[iter],
|
||||
counter,
|
||||
values_re_out[iter], values_im_out[iter]);
|
||||
|
||||
const double res_re = values_re_out[iter].to_double() * 5. / 8. / cordic_rom::out_scale_factor;
|
||||
const double res_im = values_im_out[iter].to_double() * 5. / 8. / cordic_rom::out_scale_factor;
|
||||
if (abs(res_re - results_re[iter]) > abs_margin) {
|
||||
counted_errors++;
|
||||
}
|
||||
if (abs(res_im - results_im[iter]) > abs_margin) {
|
||||
counted_errors++;
|
||||
}
|
||||
}
|
||||
|
||||
return counted_errors;
|
||||
}
|
||||
|
||||
template <unsigned n_lines>
|
||||
int section_2() {
|
||||
// SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@ - div:@CORDIC_DIVIDER@ - internal scaling")
|
||||
int counted_errors = 0;
|
||||
|
||||
static constexpr cordic_rom cordic {};
|
||||
|
||||
string input_fn = "../data/input.dat";
|
||||
|
||||
constexpr double rotation = cordic_rom::rotation;
|
||||
constexpr double q = cordic_rom::q;
|
||||
constexpr uint64_t cnt_mask = 0xFF; // Value dependant of the way the ROM is initialized
|
||||
|
||||
constexpr unsigned Out_W = cordic_rom::Out_W;
|
||||
constexpr unsigned In_W = cordic_rom::In_W;
|
||||
|
||||
ap_int<In_W> values_re_in[n_lines];
|
||||
ap_int<In_W> values_im_in[n_lines];
|
||||
ap_int<Out_W> values_re_out[n_lines];
|
||||
ap_int<Out_W> values_im_out[n_lines];
|
||||
|
||||
double results_re[n_lines];
|
||||
double results_im[n_lines];
|
||||
|
||||
FILE * INPUT = fopen(input_fn.c_str(), "r");
|
||||
|
||||
// Init test vector
|
||||
for (unsigned i = 0; i < n_lines; i++) {
|
||||
double a, b, r;
|
||||
fscanf(INPUT, "%lf,%lf,%lf\n", &a, &b, &r);
|
||||
|
||||
const complex<double> c {a, b};
|
||||
values_re_in[i] = int64_t(a * double(cordic_rom::in_scale_factor));
|
||||
values_im_in[i] = int64_t(b * double(cordic_rom::in_scale_factor));
|
||||
|
||||
const complex<double> e = c * exp(complex<double>(0., rotation / q * (i & cnt_mask)));
|
||||
results_re[i] = e.real();
|
||||
results_im[i] = e.imag();
|
||||
}
|
||||
|
||||
fclose(INPUT);
|
||||
|
||||
constexpr double abs_margin = double(1 << cordic.Out_I) * 2. / 100.;
|
||||
|
||||
// Executing the CORDIC
|
||||
for (unsigned iter = 0; iter < n_lines; iter++) {
|
||||
// Execute
|
||||
const uint8_t counter = uint8_t(iter & cnt_mask);
|
||||
|
||||
cordic_rom::cordic(
|
||||
values_re_in[iter], values_im_in[iter],
|
||||
counter,
|
||||
values_re_out[iter], values_im_out[iter]);
|
||||
|
||||
const double res_re = cordic_rom::scale_cordic(values_re_out[iter]).to_double() / cordic_rom::out_scale_factor;
|
||||
const double res_im = cordic_rom::scale_cordic(values_im_out[iter]).to_double() / cordic_rom::out_scale_factor;
|
||||
|
||||
if (abs(res_re - results_re[iter]) > abs_margin) {
|
||||
counted_errors++;
|
||||
}
|
||||
if (abs(res_im - results_im[iter]) > abs_margin) {
|
||||
counted_errors++;
|
||||
}
|
||||
}
|
||||
|
||||
return counted_errors;
|
||||
}
|
||||
|
||||
int main(int, char **) {
|
||||
|
||||
int counted_errors = 0;
|
||||
|
||||
const string test_case = "ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@, @CORDIC_DIVIDER@) works with AP-Types";
|
||||
constexpr unsigned n_lines = 100000;
|
||||
|
||||
cout << "Test case: " << test_case << endl;
|
||||
|
||||
counted_errors += section_1<n_lines>();
|
||||
counted_errors += section_2<n_lines>();
|
||||
|
||||
cout << (counted_errors == 0 ? "SUCCESS" : "FAILURE") << "." << endl;
|
||||
|
||||
return counted_errors;
|
||||
}
|
|
@ -63,7 +63,6 @@ TEST_CASE("Adaptive CORDIC work as intended", "[!mayfail][!hide][WIP]") {
|
|||
fclose(INPUT);
|
||||
fclose(RESULTS);
|
||||
|
||||
|
||||
constexpr double abs_margin = double(1 << 6) * 3. / 100.;
|
||||
|
||||
// Save the results to a file
|
Loading…
Reference in a new issue