mirror of
https://github.com/DrasLorus/CORDIC_Rotate_APFX.git
synced 2024-11-24 21:53:15 +01:00
Correct the name and improve widely
- Fix the MC (Monte-Carlo) to the proper algoritm name, ML (maximum likelyhood) and remove HalfPi since the use of divider allow to theoretically support any pi / 2^k, k an integer. In reality, a too low rotation would require more stages than 7 but it is for futur improvements. - Make use of `divider` template to provide rotation grain finer than pi / 2. Validated (unit-tested) with pi / 4 with the same margins than pi / 2 (2% of error with floating scaling, 3% with fixed scaling). - Fix rom size which now use N_STAGES+1 bits instead of 8 regardless of N_STAGES. Simplify the cordic method implementation, which unexpectedly (and fortunately) improved its performance.
This commit is contained in:
parent
08c18e63a0
commit
f0035238bf
15 changed files with 151 additions and 227 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -7,6 +7,7 @@ compile_commands.json
|
|||
*octave-workspace
|
||||
.vscode
|
||||
|
||||
RomGenerators/sources/main_generator_??*_*.cpp
|
||||
sources/CCordicRotateRom/CCordicRotateRom_*.?pp
|
||||
sources/CordicRoms/cordic_rom_*.?pp
|
||||
sources/tb/cordic_rom_tb_??*_*.?pp
|
|
@ -96,10 +96,10 @@ endif ()
|
|||
|
||||
set (
|
||||
ROM_TYPE
|
||||
"mc"
|
||||
CACHE STRING "RomGenerator to use, either 'mc' or 'cst'."
|
||||
"ml"
|
||||
CACHE STRING "RomGenerator to use, either 'ml' or 'cst'."
|
||||
)
|
||||
set_property(CACHE ROM_TYPE PROPERTY STRINGS "mc" "cst")
|
||||
set_property(CACHE ROM_TYPE PROPERTY STRINGS "ml" "cst")
|
||||
|
||||
set (
|
||||
CORDIC_W
|
||||
|
@ -116,12 +116,17 @@ set (
|
|||
"64"
|
||||
CACHE STRING "number of rotation divisions."
|
||||
)
|
||||
set (
|
||||
CORDIC_DIVIDER
|
||||
"2"
|
||||
CACHE STRING "rotation denominator."
|
||||
)
|
||||
|
||||
add_subdirectory (RomGenerators)
|
||||
|
||||
set (ROM_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/sources/CordicRoms)
|
||||
string (
|
||||
CONFIGURE ${ROM_DIRECTORY}/cordic_rom_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}.hpp
|
||||
CONFIGURE ${ROM_DIRECTORY}/cordic_rom_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}_${CORDIC_DIVIDER}.hpp
|
||||
ROM_HEADER
|
||||
)
|
||||
add_custom_command (
|
||||
|
@ -130,8 +135,8 @@ add_custom_command (
|
|||
WORKING_DIRECTORY ${ROM_DIRECTORY}
|
||||
)
|
||||
|
||||
set (CORDIC_ROM_HEADER CCordicRotateRom_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}.hpp)
|
||||
set (CORDIC_ROM_SOURCE CCordicRotateRom_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}.cpp)
|
||||
set (CORDIC_ROM_HEADER CCordicRotateRom_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}_${CORDIC_DIVIDER}.hpp)
|
||||
set (CORDIC_ROM_SOURCE CCordicRotateRom_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}_${CORDIC_DIVIDER}.cpp)
|
||||
configure_file (
|
||||
sources/CCordicRotateRom/CCordicRotateRom.hpp.in
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/CCordicRotateRom/${CORDIC_ROM_HEADER} @ONLY
|
||||
|
@ -167,7 +172,7 @@ if (ENABLE_TESTING)
|
|||
|
||||
string (
|
||||
CONFIGURE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/tb/cordic_rom_tb_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sources/tb/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)
|
||||
|
@ -191,10 +196,10 @@ file (GLOB ALL_CORDIC_ROM_HEADERS sources/CCordicRotateRom/CCordicRotateRom_*.hp
|
|||
add_custom_target (
|
||||
remove_byproducts
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "-- Deleting generated sources files and headers"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${TB_SOURCE} ${ALL_ROM_TB_SOURCES}
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${CORDIC_ROM_SOURCE} ${ALL_CORDIC_ROM_SOURCES}
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${ALL_ROM_HEADERS}
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${ALL_CORDIC_ROM_HEADERS}
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${TB_SOURCE} ${ALL_ROM_TB_SOURCES}
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${CORDIC_ROM_SOURCE} ${ALL_CORDIC_ROM_SOURCES}
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${ALL_ROM_HEADERS}
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f ${ALL_CORDIC_ROM_HEADERS}
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "-- Files deleted."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"-- WARNING: You must re-run the cmake-configure step for the next build to succeed."
|
||||
|
|
|
@ -34,7 +34,7 @@ project (
|
|||
)
|
||||
|
||||
add_library (
|
||||
romgen sources/RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.cpp
|
||||
romgen sources/RomGeneratorML/RomGeneratorML.cpp
|
||||
sources/RomGeneratorConst/RomGeneratorConst.cpp
|
||||
)
|
||||
target_include_directories (romgen PUBLIC sources)
|
||||
|
@ -50,8 +50,8 @@ target_link_libraries (rom_generator_legacy PUBLIC romgen)
|
|||
|
||||
set (
|
||||
ROM_TYPE
|
||||
"mc"
|
||||
CACHE STRING "RomGenerator to use, either 'mc' or 'const'."
|
||||
"ml"
|
||||
CACHE STRING "RomGenerator to use, either 'ml' or 'const'."
|
||||
)
|
||||
set (
|
||||
CORDIC_W
|
||||
|
@ -68,9 +68,16 @@ set (
|
|||
"64"
|
||||
CACHE STRING "number of rotation divisions."
|
||||
)
|
||||
|
||||
configure_file (
|
||||
sources/main_generator.cpp.in ${CMAKE_CURRENT_SOURCE_DIR}/sources/main_generator.cpp @ONLY
|
||||
set (
|
||||
CORDIC_DIVIDER
|
||||
"2"
|
||||
CACHE STRING "Rotation denominator."
|
||||
)
|
||||
add_executable (rom_generator sources/main_generator.cpp)
|
||||
|
||||
set (current_generator_source ${CMAKE_CURRENT_SOURCE_DIR}/sources/main_generator_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}_${CORDIC_DIVIDER}.cpp)
|
||||
configure_file (
|
||||
sources/main_generator.cpp.in
|
||||
${current_generator_source} @ONLY
|
||||
)
|
||||
add_executable (rom_generator ${current_generator_source})
|
||||
target_link_libraries (rom_generator PUBLIC romgen)
|
||||
|
|
|
@ -33,6 +33,7 @@ class CRomGeneratorConst {
|
|||
static_assert(In_W > 0, "Inputs can't be on zero bits.");
|
||||
static_assert(NStages < 8, "7 stages of CORDIC is the maximum supported.");
|
||||
static_assert(NStages > 1, "2 stages of CORDIC is the minimum.");
|
||||
static_assert(((divider - 1) & divider) == 0, "divider must be a power of 2.");
|
||||
|
||||
public:
|
||||
static constexpr double pi = 3.14159265358979323846;
|
||||
|
@ -59,7 +60,7 @@ private:
|
|||
double B = 0;
|
||||
|
||||
uint8_t R = 0;
|
||||
const uint8_t sig_mask = 0x80;
|
||||
const uint8_t sig_mask = 0x01;
|
||||
|
||||
double beta = rot_in;
|
||||
|
||||
|
@ -88,7 +89,7 @@ private:
|
|||
#if 0
|
||||
printf("Step %d - %03u : %02x : %8lf\n", u, R, R, beta);
|
||||
#endif
|
||||
const uint8_t mask = (1U << (7 - u));
|
||||
const uint8_t mask = (1U << u);
|
||||
const uint8_t nmask = ~mask;
|
||||
|
||||
assert((mask & nmask) == 0x00);
|
||||
|
@ -123,7 +124,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq>
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq, unsigned divider = 2>
|
||||
void generate_rom_header_cst(const char * filename) {
|
||||
constexpr CRomGeneratorConst<In_W, NStages, Tq> rom {};
|
||||
|
||||
|
@ -134,10 +135,10 @@ void generate_rom_header_cst(const char * filename) {
|
|||
}
|
||||
|
||||
char upper_file_def[64];
|
||||
snprintf(upper_file_def, 64, "CORDIC_ROMS_CST_%u_%u_%u", In_W, NStages, Tq);
|
||||
snprintf(upper_file_def, 64, "CORDIC_ROMS_CST_%u_%u_%u_%u", In_W, NStages, Tq, divider);
|
||||
|
||||
char rom_name[64];
|
||||
snprintf(rom_name, 64, "cst_%u_%u_%u", In_W, NStages, Tq);
|
||||
snprintf(rom_name, 64, "cst_%u_%u_%u_%u", In_W, NStages, Tq, divider);
|
||||
|
||||
fprintf(rom_file, "#ifndef %s\n#define %s\n\n", upper_file_def, upper_file_def);
|
||||
fprintf(rom_file, "#include <cstdint>\n\n");
|
||||
|
@ -156,9 +157,9 @@ void generate_rom_header_cst(const char * filename) {
|
|||
fprintf(rom_file, "#endif // %s\n\n", upper_file_def);
|
||||
}
|
||||
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq>
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq, unsigned divider = 2>
|
||||
void generate_rom_header_cst_raw(const char * filename = "rom_cordic.txt") {
|
||||
constexpr CRomGeneratorConst<In_W, NStages, Tq> rom {};
|
||||
constexpr CRomGeneratorConst<In_W, NStages, Tq, divider> rom {};
|
||||
|
||||
FILE * rom_file = fopen(filename, "w");
|
||||
if (!bool(rom_file)) {
|
||||
|
|
|
@ -17,4 +17,4 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "RomGeneratorMCHalfPi.hpp"
|
||||
#include "RomGeneratorML.hpp"
|
|
@ -17,43 +17,44 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef _ROM_GENERATOR_MC_HALF_PI
|
||||
#define _ROM_GENERATOR_MC_HALF_PI
|
||||
#ifndef _ROM_GENERATOR_ML
|
||||
#define _ROM_GENERATOR_ML
|
||||
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <complex>
|
||||
#include <cstdint>
|
||||
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq>
|
||||
class CRomGeneratorMCHalfPi {
|
||||
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.");
|
||||
static_assert(NStages < 8, "7 stages of CORDIC is the maximum supported.");
|
||||
static_assert(NStages > 1, "2 stages of CORDIC is the minimum.");
|
||||
static_assert(NStages > 1, "2 stages of CORDIC is the minimum.");
|
||||
static_assert(((divider - 1) & divider) == 0, "divider must be a power of 2.");
|
||||
|
||||
public:
|
||||
static constexpr double rotation = M_PI_2;
|
||||
static constexpr double rotation = M_PI / divider;
|
||||
static constexpr double q = Tq;
|
||||
static constexpr uint32_t max_length = 4 * Tq; // 2pi / (pi / 2) * q
|
||||
static constexpr int64_t scale_factor = int64_t(1U << (In_W - 1)); // 2pi / (pi / 2) * q
|
||||
static constexpr uint32_t max_length = 2 * divider * Tq; // 2pi / (pi / divider) * q
|
||||
static constexpr int64_t scale_factor = int64_t(1U << (In_W - 1));
|
||||
|
||||
private:
|
||||
constexpr std::complex<int64_t> cordic_MC(const std::complex<int64_t> & x_in,
|
||||
constexpr std::complex<int64_t> cordic_ML(const std::complex<int64_t> & x_in,
|
||||
uint8_t counter) {
|
||||
|
||||
int64_t A = x_in.real();
|
||||
int64_t B = x_in.imag();
|
||||
|
||||
const uint8_t R = counter;
|
||||
uint8_t mask = 0x80;
|
||||
uint8_t mask = 0x01;
|
||||
if ((R & mask) == mask) {
|
||||
A = -A;
|
||||
B = -B;
|
||||
}
|
||||
|
||||
for (uint16_t u = 1; u < NStages + 1; u++) {
|
||||
mask = mask >> 1;
|
||||
mask = mask << 1;
|
||||
|
||||
const int64_t Ri = (R & mask) == mask ? 1 : -1;
|
||||
|
||||
|
@ -68,7 +69,7 @@ private:
|
|||
public:
|
||||
uint8_t rom[max_length];
|
||||
|
||||
CRomGeneratorMCHalfPi() {
|
||||
CRomGeneratorML() {
|
||||
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)));
|
||||
|
@ -80,7 +81,7 @@ public:
|
|||
|
||||
std::complex<double> res;
|
||||
for (uint32_t v = 0; v < max_length; v++) {
|
||||
const std::complex<int64_t> res_int = cordic_MC(x, v);
|
||||
const std::complex<int64_t> res_int = cordic_ML(x, v);
|
||||
|
||||
const std::complex<double> res_dbl(double(res_int.real()) / double(scale_factor - 1),
|
||||
double(res_int.imag()) / double(scale_factor - 1));
|
||||
|
@ -98,9 +99,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq>
|
||||
void generate_rom_header_mc(const char * filename) {
|
||||
const CRomGeneratorMCHalfPi<In_W, NStages, Tq> rom;
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq, unsigned divider = 2>
|
||||
void generate_rom_header_ml(const char * filename) {
|
||||
const CRomGeneratorML<In_W, NStages, Tq, divider> rom;
|
||||
|
||||
FILE * rom_file = fopen(filename, "w");
|
||||
if (!bool(rom_file)) {
|
||||
|
@ -109,10 +110,10 @@ void generate_rom_header_mc(const char * filename) {
|
|||
}
|
||||
|
||||
char upper_file_def[64];
|
||||
snprintf(upper_file_def, 64, "CORDIC_ROMS_MC_%u_%u_%u", In_W, NStages, Tq);
|
||||
snprintf(upper_file_def, 64, "CORDIC_ROMS_ML_%u_%u_%u_%u", In_W, NStages, Tq, divider);
|
||||
|
||||
char rom_name[64];
|
||||
snprintf(rom_name, 64, "mc_%u_%u_%u", In_W, NStages, Tq);
|
||||
snprintf(rom_name, 64, "ml_%u_%u_%u_%u", In_W, NStages, Tq, divider);
|
||||
|
||||
fprintf(rom_file, "#ifndef %s\n#define %s\n\n", upper_file_def, upper_file_def);
|
||||
fprintf(rom_file, "#include <cstdint>\n\n");
|
||||
|
@ -131,9 +132,9 @@ void generate_rom_header_mc(const char * filename) {
|
|||
fprintf(rom_file, "#endif // %s\n\n", upper_file_def);
|
||||
}
|
||||
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq>
|
||||
void generate_rom_header_mc_raw(const char * filename) {
|
||||
const CRomGeneratorMCHalfPi<In_W, NStages, Tq> rom;
|
||||
template <unsigned In_W, unsigned NStages, unsigned Tq, unsigned divider = 2>
|
||||
void generate_rom_header_ml_raw(const char * filename) {
|
||||
const CRomGeneratorML<In_W, NStages, Tq, divider> rom;
|
||||
|
||||
FILE * rom_file = fopen(filename, "w");
|
||||
if (!bool(rom_file)) {
|
||||
|
@ -145,7 +146,6 @@ void generate_rom_header_mc_raw(const char * filename) {
|
|||
fprintf(rom_file, "%03d\n", uint16_t(rom.rom[u]));
|
||||
}
|
||||
fprintf(rom_file, "%03d\n\n", uint16_t(rom.rom[rom.max_length - 1]));
|
||||
|
||||
}
|
||||
|
||||
#endif // _ROM_GENERATOR_MC_HALF_PI
|
||||
#endif // _ROM_GENERATOR_ML
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* 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 "RomGeneratorConst/RomGeneratorConst.hpp"
|
||||
#include "RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int, char **) {
|
||||
|
||||
const char filename[] = "cordic_rom_mc_16_6_64.hpp";
|
||||
|
||||
generate_rom_header_mc<16, 6, 64>(filename);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "RomGeneratorConst/RomGeneratorConst.hpp"
|
||||
#include "RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.hpp"
|
||||
#include "RomGeneratorML/RomGeneratorML.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
@ -28,9 +28,9 @@ using namespace std;
|
|||
|
||||
int main(int, char **) {
|
||||
|
||||
const char filename[] = "cordic_rom_@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@.hpp";
|
||||
const char filename[] = "cordic_rom_@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@.hpp";
|
||||
|
||||
generate_rom_header_@ROM_TYPE@<@CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@>(filename);
|
||||
generate_rom_header_@ROM_TYPE@<@CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@, @CORDIC_DIVIDER@>(filename);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "RomGeneratorConst/RomGeneratorConst.hpp"
|
||||
#include "RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.hpp"
|
||||
#include "RomGeneratorML/RomGeneratorML.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
@ -56,7 +56,7 @@ constexpr complex<int64_t> cordic(complex<int64_t> x_in,
|
|||
|
||||
template <unsigned NStages>
|
||||
void checkMC() {
|
||||
const CRomGeneratorMCHalfPi<16, NStages, 64> rom;
|
||||
const CRomGeneratorML<16, NStages, 64> rom;
|
||||
|
||||
string fn = "result_MC_W16_S" + to_string(NStages) + "_Q64.dat";
|
||||
ofstream res_file(fn);
|
||||
|
@ -83,28 +83,28 @@ void checkConst() {
|
|||
int main(int argc, char * argv[]) {
|
||||
|
||||
uint8_t stages;
|
||||
bool use_mc;
|
||||
bool use_ml;
|
||||
bool use_txt;
|
||||
|
||||
switch (argc) {
|
||||
case 1:
|
||||
stages = 6;
|
||||
use_mc = false;
|
||||
use_ml = false;
|
||||
use_txt = false;
|
||||
break;
|
||||
case 2:
|
||||
stages = stoi(string(argv[1]));
|
||||
use_mc = false;
|
||||
use_ml = false;
|
||||
use_txt = false;
|
||||
break;
|
||||
case 3:
|
||||
stages = stoi(string(argv[1]));
|
||||
use_mc = stoi(string(argv[2])) > 0;
|
||||
use_ml = stoi(string(argv[2])) > 0;
|
||||
use_txt = false;
|
||||
break;
|
||||
case 4:
|
||||
stages = stoi(string(argv[1]));
|
||||
use_mc = stoi(string(argv[2])) > 0;
|
||||
use_ml = stoi(string(argv[2])) > 0;
|
||||
use_txt = stoi(string(argv[3])) > 0;
|
||||
break;
|
||||
default:
|
||||
|
@ -112,30 +112,30 @@ int main(int argc, char * argv[]) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (use_txt) {
|
||||
if (use_mc) {
|
||||
if (use_ml) {
|
||||
switch (stages) {
|
||||
case 2:
|
||||
generate_rom_header_mc_raw<16, 2, 64>("rom_cordic_mc_W16_S2_Q64.txt");
|
||||
generate_rom_header_ml_raw<16, 2, 64>("rom_cordic_ml_W16_S2_Q64.txt");
|
||||
checkMC<2>();
|
||||
break;
|
||||
case 3:
|
||||
generate_rom_header_mc_raw<16, 3, 64>("rom_cordic_mc_W16_S3_Q64.txt");
|
||||
generate_rom_header_ml_raw<16, 3, 64>("rom_cordic_ml_W16_S3_Q64.txt");
|
||||
checkMC<3>();
|
||||
break;
|
||||
case 4:
|
||||
generate_rom_header_mc_raw<16, 4, 64>("rom_cordic_mc_W16_S4_Q64.txt");
|
||||
generate_rom_header_ml_raw<16, 4, 64>("rom_cordic_ml_W16_S4_Q64.txt");
|
||||
checkMC<4>();
|
||||
break;
|
||||
case 5:
|
||||
generate_rom_header_mc_raw<16, 5, 64>("rom_cordic_mc_W16_S5_Q64.txt");
|
||||
generate_rom_header_ml_raw<16, 5, 64>("rom_cordic_ml_W16_S5_Q64.txt");
|
||||
checkMC<5>();
|
||||
break;
|
||||
case 6:
|
||||
generate_rom_header_mc_raw<16, 6, 64>("rom_cordic_mc_W16_S6_Q64.txt");
|
||||
generate_rom_header_ml_raw<16, 6, 64>("rom_cordic_ml_W16_S6_Q64.txt");
|
||||
checkMC<6>();
|
||||
break;
|
||||
case 7:
|
||||
generate_rom_header_mc_raw<16, 7, 64>("rom_cordic_mc_W16_S7_Q64.txt");
|
||||
generate_rom_header_ml_raw<16, 7, 64>("rom_cordic_ml_W16_S7_Q64.txt");
|
||||
checkMC<7>();
|
||||
break;
|
||||
default:
|
||||
|
@ -175,30 +175,30 @@ int main(int argc, char * argv[]) {
|
|||
}
|
||||
} else {
|
||||
|
||||
if (use_mc) {
|
||||
if (use_ml) {
|
||||
switch (stages) {
|
||||
case 2:
|
||||
generate_rom_header_mc<16, 2, 64>("rom_cordic_mc_W16_S2_Q64.hpp");
|
||||
generate_rom_header_ml<16, 2, 64>("rom_cordic_ml_W16_S2_Q64.hpp");
|
||||
checkMC<2>();
|
||||
break;
|
||||
case 3:
|
||||
generate_rom_header_mc<16, 3, 64>("rom_cordic_mc_W16_S3_Q64.hpp");
|
||||
generate_rom_header_ml<16, 3, 64>("rom_cordic_ml_W16_S3_Q64.hpp");
|
||||
checkMC<3>();
|
||||
break;
|
||||
case 4:
|
||||
generate_rom_header_mc<16, 4, 64>("rom_cordic_mc_W16_S4_Q64.hpp");
|
||||
generate_rom_header_ml<16, 4, 64>("rom_cordic_ml_W16_S4_Q64.hpp");
|
||||
checkMC<4>();
|
||||
break;
|
||||
case 5:
|
||||
generate_rom_header_mc<16, 5, 64>("rom_cordic_mc_W16_S5_Q64.hpp");
|
||||
generate_rom_header_ml<16, 5, 64>("rom_cordic_ml_W16_S5_Q64.hpp");
|
||||
checkMC<5>();
|
||||
break;
|
||||
case 6:
|
||||
generate_rom_header_mc<16, 6, 64>("rom_cordic_mc_W16_S6_Q64.hpp");
|
||||
generate_rom_header_ml<16, 6, 64>("rom_cordic_ml_W16_S6_Q64.hpp");
|
||||
checkMC<6>();
|
||||
break;
|
||||
case 7:
|
||||
generate_rom_header_mc<16, 7, 64>("rom_cordic_mc_W16_S7_Q64.hpp");
|
||||
generate_rom_header_ml<16, 7, 64>("rom_cordic_ml_W16_S7_Q64.hpp");
|
||||
checkMC<7>();
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef C_CORDIC_ROTATE_ROM_HALF_PI_HPP
|
||||
#define C_CORDIC_ROTATE_ROM_HALF_PI_HPP
|
||||
#ifndef C_CORDIC_ROTATE_CONSTEXPR_HPP
|
||||
#define C_CORDIC_ROTATE_CONSTEXPR_HPP
|
||||
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
|
@ -37,6 +37,7 @@ class CCordicRotateConstexpr {
|
|||
static_assert(TIn_W > 0, "Inputs can't be on zero bits.");
|
||||
static_assert(Tnb_stages < 8, "7 stages of CORDIC is the maximum supported.");
|
||||
static_assert(Tnb_stages > 1, "2 stages of CORDIC is the minimum.");
|
||||
static_assert(((divider - 1) & divider) == 0, "divider must be a power of 2.");
|
||||
|
||||
public:
|
||||
// ``` GNU Octave
|
||||
|
@ -57,6 +58,8 @@ public:
|
|||
static constexpr uint64_t in_scale_factor = uint64_t(1U << (In_W - In_I));
|
||||
static constexpr uint64_t out_scale_factor = uint64_t(1U << (Out_W - Out_I));
|
||||
|
||||
static constexpr double rotation = CRomGeneratorConst<TIn_W, Tnb_stages, Tq, divider>::rotation;
|
||||
|
||||
static constexpr int64_t scale_cordic(int64_t in) {
|
||||
return in * kn_i / 8U;
|
||||
}
|
||||
|
@ -68,14 +71,14 @@ public:
|
|||
int64_t B = x_in.imag();
|
||||
|
||||
const uint8_t R = rom_cordic.rom[counter];
|
||||
uint8_t mask = 0x80;
|
||||
uint8_t mask = 0x01;
|
||||
if ((R & mask) == mask) {
|
||||
A = -A;
|
||||
B = -B;
|
||||
}
|
||||
|
||||
for (uint8_t u = 1; u < nb_stages + 1; u++) {
|
||||
mask = mask >> 1;
|
||||
mask = mask << 1;
|
||||
|
||||
const int64_t Ri = (R & mask) == mask ? 1 : -1;
|
||||
|
||||
|
@ -103,24 +106,23 @@ public:
|
|||
|
||||
#endif
|
||||
|
||||
template <unsigned ap_W>
|
||||
static ap_int<ap_W> scale_cordic(const ap_int<ap_W> & in) {
|
||||
const ap_int<ap_W + 3> tmp = in * ap_uint<3>(kn_i);
|
||||
return ap_int<ap_W>(tmp >> 3);
|
||||
static ap_int<Out_W> scale_cordic(const ap_int<Out_W> & in) {
|
||||
const ap_int<Out_W + 3> tmp = in * ap_uint<3>(kn_i);
|
||||
return ap_int<Out_W>(tmp >> 3);
|
||||
}
|
||||
|
||||
static void cordic(const ap_int<In_W> & re_in, const ap_int<In_W> & im_in,
|
||||
const ap_uint<8> & counter,
|
||||
ap_int<Out_W> & re_out, ap_int<Out_W> & im_out) {
|
||||
|
||||
const ap_uint<nb_stages + 1> R = (rom_cordic.rom[counter] >> (7 - nb_stages));
|
||||
const ap_uint<nb_stages + 1> R = rom_cordic.rom[counter];
|
||||
|
||||
ap_int<Out_W> A = bool(R[nb_stages]) ? ap_int<In_W>(-re_in) : re_in;
|
||||
ap_int<Out_W> B = bool(R[nb_stages]) ? ap_int<In_W>(-im_in) : im_in;
|
||||
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;
|
||||
|
||||
for (uint8_t u = 1; u < nb_stages + 1; u++) { // nb_stages stages
|
||||
|
||||
const bool Ri = bool(R[nb_stages - u]);
|
||||
const bool Ri = bool(R[u]);
|
||||
|
||||
// Results in (X / 2^(u - 1)), meaning only the
|
||||
// Out_W - u LSBs are meaninfull in shifted_X
|
||||
|
@ -194,4 +196,4 @@ inline void CCordicRotateConstexpr<16, 4, 6, 64>::cordic(
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif // C_CORDIC_ROTATE_ROM_HALF_PI_HPP
|
||||
#endif // C_CORDIC_ROTATE_CONSTEXPR_HPP
|
|
@ -1 +1 @@
|
|||
#include "CCordicRotateRom/CCordicRotateRom_@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@.hpp"
|
||||
#include "CCordicRotateRom/CCordicRotateRom_@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@.hpp"
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef C_CORDIC_ROTATE_ROM_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@
|
||||
#define C_CORDIC_ROTATE_ROM_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@
|
||||
#ifndef C_CORDIC_ROTATE_ROM_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@
|
||||
#define C_CORDIC_ROTATE_ROM_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@
|
||||
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
|
@ -31,7 +31,7 @@
|
|||
#include <ap_int.h>
|
||||
|
||||
#include "CCordicRotateRomTemplate.hpp"
|
||||
#include "CordicRoms/cordic_rom_@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@.hpp"
|
||||
#include "CordicRoms/cordic_rom_@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@.hpp"
|
||||
|
||||
#ifndef KN_STATIC_TABLE_DEFINED
|
||||
#define KN_STATIC_TABLE_DEFINED 1
|
||||
|
@ -44,10 +44,11 @@ static constexpr double kn_values[7] = {
|
|||
#endif // KN_STATIC_TABLE_DEFINED
|
||||
|
||||
template <unsigned TIn_I>
|
||||
class CCordicRotateRom<TIn_I, @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@> {
|
||||
class CCordicRotateRom<TIn_I, @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@, @CORDIC_DIVIDER@> {
|
||||
static_assert(@CORDIC_W@ > 0, "Inputs can't be on zero bits.");
|
||||
static_assert(@CORDIC_STAGES@ < 8, "7 stages of CORDIC is the maximum supported.");
|
||||
static_assert(@CORDIC_STAGES@ > 1, "2 stages of CORDIC is the minimum.");
|
||||
static_assert(((@CORDIC_DIVIDER@ - 1) & @CORDIC_DIVIDER@) == 0, "divider must be a power of 2.");
|
||||
|
||||
public:
|
||||
static constexpr unsigned In_W = @CORDIC_W@;
|
||||
|
@ -61,6 +62,8 @@ public:
|
|||
static constexpr uint64_t in_scale_factor = uint64_t(1U << (In_W - In_I));
|
||||
static constexpr uint64_t out_scale_factor = uint64_t(1U << (Out_W - Out_I));
|
||||
|
||||
static constexpr double rotation = M_PI / @CORDIC_DIVIDER@;
|
||||
|
||||
static constexpr int64_t scale_cordic(int64_t in) {
|
||||
return in * kn_i / 8U;
|
||||
}
|
||||
|
@ -71,15 +74,15 @@ public:
|
|||
int64_t A = x_in.real();
|
||||
int64_t B = x_in.imag();
|
||||
|
||||
const uint8_t R = cordic_roms::@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@[counter];
|
||||
uint8_t mask = 0x80;
|
||||
const uint8_t R = cordic_roms::@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@[counter];
|
||||
uint8_t mask = 0x01;
|
||||
if ((R & mask) == mask) {
|
||||
A = -A;
|
||||
B = -B;
|
||||
}
|
||||
|
||||
for (uint8_t u = 1; u < nb_stages + 1; u++) {
|
||||
mask = mask >> 1;
|
||||
mask = mask << 1;
|
||||
|
||||
const int64_t Ri = (R & mask) == mask ? 1 : -1;
|
||||
|
||||
|
@ -107,24 +110,23 @@ public:
|
|||
|
||||
#endif
|
||||
|
||||
template <unsigned ap_W>
|
||||
static ap_int<ap_W> scale_cordic(const ap_int<ap_W> & in) {
|
||||
const ap_int<ap_W + 3> tmp = in * ap_uint<3>(kn_i);
|
||||
return ap_int<ap_W>(tmp >> 3);
|
||||
static ap_int<Out_W> scale_cordic(const ap_int<Out_W> & in) {
|
||||
const ap_int<Out_W + 3> tmp = in * ap_uint<3>(kn_i);
|
||||
return ap_int<Out_W>(tmp >> 3);
|
||||
}
|
||||
|
||||
static void cordic(const ap_int<In_W> & re_in, const ap_int<In_W> & im_in,
|
||||
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@[counter] >> (7 - nb_stages));
|
||||
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[nb_stages]) ? ap_int<In_W>(-re_in) : re_in;
|
||||
ap_int<Out_W> B = bool(R[nb_stages]) ? ap_int<In_W>(-im_in) : im_in;
|
||||
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;
|
||||
|
||||
for (uint8_t u = 1; u < nb_stages + 1; u++) { // nb_stages stages
|
||||
|
||||
const bool Ri = bool(R[nb_stages - u]);
|
||||
const bool Ri = bool(R[u]);
|
||||
|
||||
// Results in (X / 2^(u - 1)), meaning only the
|
||||
// Out_W - u LSBs are meaninfull in shifted_X
|
||||
|
@ -155,4 +157,4 @@ public:
|
|||
constexpr CCordicRotateRom() = default;
|
||||
};
|
||||
|
||||
#endif // C_CORDIC_ROTATE_ROM_W_STAGES_Q
|
||||
#endif // C_CORDIC_ROTATE_ROM_W_STAGES_Q_DIVIDER
|
||||
|
|
|
@ -21,15 +21,16 @@
|
|||
#define C_CORDIC_ROTATE_ROM_TEMPLATE
|
||||
|
||||
enum rom_types {
|
||||
mc,
|
||||
ml,
|
||||
cst
|
||||
};
|
||||
|
||||
template <unsigned TIn_I, rom_types type, unsigned TIn_W, unsigned Tnb_stages, unsigned Tq>
|
||||
template <unsigned TIn_I, rom_types type, unsigned TIn_W, unsigned Tnb_stages, unsigned Tq, unsigned divider = 2>
|
||||
class CCordicRotateRom {
|
||||
static_assert(TIn_W > 0, "Inputs can't be on zero bits.");
|
||||
static_assert(Tnb_stages < 8, "7 stages of CORDIC is the maximum supported.");
|
||||
static_assert(Tnb_stages > 1, "2 stages of CORDIC is the minimum.");
|
||||
static_assert(((divider - 1) & divider) == 0, "divider must be a power of 2.");
|
||||
};
|
||||
|
||||
#endif // C_CORDIC_ROTATE_ROM_TEMPLATE
|
|
@ -17,7 +17,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "CCordicRotateRom/CCordicRotateRom_@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@.hpp"
|
||||
#include "CCordicRotateRom/CCordicRotateRom_@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
|
@ -28,14 +28,13 @@ using namespace std;
|
|||
using Catch::Matchers::Floating::WithinAbsMatcher;
|
||||
|
||||
|
||||
typedef CCordicRotateRom<4, @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@> cordic_rom;
|
||||
typedef CCordicRotateRom<4, @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@, @CORDIC_DIVIDER@> cordic_rom;
|
||||
|
||||
TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@) works with C-Types", "[CORDIC]") {
|
||||
SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@") {
|
||||
TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@, @CORDIC_DIVIDER@) works with C-Types", "[CORDIC]") {
|
||||
SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@ - div:@CORDIC_DIVIDER@") {
|
||||
static constexpr cordic_rom cordic {};
|
||||
|
||||
string input_fn = "../data/input.dat"; // _8_14_4_17_5_19_7_12
|
||||
string output_fn = "../data/output.dat"; // _8_14_4_17_5_19_7_12
|
||||
string input_fn = "../data/input.dat";
|
||||
|
||||
constexpr unsigned n_lines = 100000;
|
||||
|
||||
|
@ -44,8 +43,6 @@ TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDI
|
|||
|
||||
complex<double> results[n_lines];
|
||||
|
||||
// ofstream FILE;
|
||||
|
||||
ifstream INPUT(input_fn);
|
||||
|
||||
// Init test vector
|
||||
|
@ -56,7 +53,7 @@ TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDI
|
|||
const complex<double> c {a, b};
|
||||
values_in[i] = c;
|
||||
|
||||
constexpr double rotation = M_PI / 2;
|
||||
constexpr double rotation = cordic_rom::rotation;
|
||||
constexpr double q = cordic_rom::q;
|
||||
|
||||
const complex<double> e = exp(complex<double>(0., rotation / q * (i & 255)));
|
||||
|
@ -65,44 +62,30 @@ TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDI
|
|||
|
||||
INPUT.close();
|
||||
|
||||
// Save the results to a file
|
||||
// FILE.open("results.dat");
|
||||
|
||||
constexpr double abs_margin = double(1 << cordic.Out_I) * 2. / 100.;
|
||||
|
||||
// Executing the encoder
|
||||
// Executing the CORDIC
|
||||
for (unsigned iter = 0; iter < n_lines; iter++) {
|
||||
// Execute
|
||||
|
||||
values_out[iter] = cordic_rom::cordic(values_in[iter], (iter & 255));
|
||||
|
||||
// Display the results
|
||||
// cout << "Series " << iter;
|
||||
// cout << " Outcome: ";
|
||||
|
||||
// FILE << values_out[iter].real() << " " << values_out[iter].imag() << " " << results[iter].real() << " " << results[iter].imag() << endl;
|
||||
|
||||
REQUIRE_THAT(values_out[iter].real(), WithinAbsMatcher(results[iter].real(), abs_margin));
|
||||
REQUIRE_THAT(values_out[iter].imag(), WithinAbsMatcher(results[iter].imag(), abs_margin));
|
||||
}
|
||||
// FILE.close();
|
||||
|
||||
// Compare the results file with the golden results
|
||||
// int retval = 0;
|
||||
// Return 0 if the test passed
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@) works with AP-Types", "[CORDIC]") {
|
||||
TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@, @CORDIC_DIVIDER@) works with AP-Types", "[CORDIC]") {
|
||||
constexpr unsigned n_lines = 100000;
|
||||
|
||||
SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@") {
|
||||
SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@ - div:@CORDIC_DIVIDER@") {
|
||||
|
||||
static constexpr cordic_rom cordic {};
|
||||
|
||||
string input_fn = "../data/input.dat";
|
||||
|
||||
constexpr double rotation = M_PI / 2;
|
||||
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
|
||||
|
||||
|
@ -117,8 +100,6 @@ TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDI
|
|||
double results_re[n_lines];
|
||||
double results_im[n_lines];
|
||||
|
||||
// ofstream out_stream;
|
||||
|
||||
ifstream INPUT(input_fn);
|
||||
|
||||
// Init test vector
|
||||
|
@ -137,48 +118,29 @@ TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDI
|
|||
|
||||
INPUT.close();
|
||||
|
||||
// Save the results to a file
|
||||
// out_stream.open("results_ap.dat");
|
||||
// FILE * romf = fopen("rom.dat", "w");
|
||||
|
||||
constexpr double abs_margin = double(1 << cordic.Out_I) * 2. / 100.;
|
||||
|
||||
// Executing the encoder
|
||||
// Executing the CORDIC
|
||||
for (unsigned iter = 0; iter < n_lines; iter++) {
|
||||
// Execute
|
||||
const uint8_t counter = uint8_t(iter & cnt_mask);
|
||||
|
||||
// if (iter < cnt_mask + 1)
|
||||
// fprintf(romf, "%03d\n", (uint16_t) cordic.rom_cordic.rom[counter]);
|
||||
|
||||
cordic_rom::cordic(
|
||||
values_re_in[iter], values_im_in[iter],
|
||||
counter,
|
||||
values_re_out[iter], values_im_out[iter]);
|
||||
|
||||
// Display the results
|
||||
// cout << "Series " << iter;
|
||||
// cout << " Outcome: ";
|
||||
|
||||
// out_stream << values_re_out[iter].to_int64() << " " << values_im_out[iter].to_int64() << " " << results_re[iter] << " " << results_im[iter] << endl;
|
||||
|
||||
REQUIRE_THAT(values_re_out[iter].to_double() * 5. / 8. / cordic_rom::out_scale_factor, WithinAbsMatcher(results_re[iter], abs_margin));
|
||||
REQUIRE_THAT(values_im_out[iter].to_double() * 5. / 8. / cordic_rom::out_scale_factor, WithinAbsMatcher(results_im[iter], abs_margin));
|
||||
}
|
||||
// out_stream.close();
|
||||
// fclose(romf);
|
||||
|
||||
// Compare the results file with the golden results
|
||||
// int retval = 0;
|
||||
// Return 0 if the test passed
|
||||
}
|
||||
|
||||
SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@ - internal scaling") {
|
||||
SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@ - div:@CORDIC_DIVIDER@ - internal scaling") {
|
||||
static constexpr cordic_rom cordic {};
|
||||
|
||||
string input_fn = "../data/input.dat";
|
||||
|
||||
constexpr double rotation = M_PI / 2;
|
||||
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
|
||||
|
||||
|
@ -193,8 +155,6 @@ TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDI
|
|||
double results_re[n_lines];
|
||||
double results_im[n_lines];
|
||||
|
||||
ofstream out_stream;
|
||||
|
||||
ifstream INPUT(input_fn);
|
||||
|
||||
// Init test vector
|
||||
|
@ -213,49 +173,30 @@ TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDI
|
|||
|
||||
INPUT.close();
|
||||
|
||||
// Save the results to a file
|
||||
// out_stream.open("results_ap.dat");
|
||||
// FILE * romf = fopen("rom.dat", "w");
|
||||
|
||||
constexpr double abs_margin = double(1 << cordic.Out_I) * 2. / 100.;
|
||||
|
||||
// Executing the encoder
|
||||
// Executing the CORDIC
|
||||
for (unsigned iter = 0; iter < n_lines; iter++) {
|
||||
// Execute
|
||||
const uint8_t counter = uint8_t(iter & cnt_mask);
|
||||
|
||||
// if (iter < cnt_mask + 1)
|
||||
// fprintf(romf, "%03d\n", (uint16_t) cordic.rom_cordic.rom[counter]);
|
||||
|
||||
cordic_rom::cordic(
|
||||
values_re_in[iter], values_im_in[iter],
|
||||
counter,
|
||||
values_re_out[iter], values_im_out[iter]);
|
||||
|
||||
// Display the results
|
||||
// cout << "Series " << iter;
|
||||
// cout << " Outcome: ";
|
||||
|
||||
// out_stream << values_re_out[iter].to_int64() << " " << values_im_out[iter].to_int64() << " " << results_re[iter] << " " << results_im[iter] << endl;
|
||||
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic<Out_W>(values_re_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic(values_re_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
WithinAbsMatcher(results_re[iter],
|
||||
abs_margin));
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic<Out_W>(values_im_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic(values_im_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
WithinAbsMatcher(results_im[iter],
|
||||
abs_margin));
|
||||
}
|
||||
// out_stream.close();
|
||||
// fclose(romf);
|
||||
|
||||
// Compare the results file with the golden results
|
||||
// int retval = 0;
|
||||
// Return 0 if the test passed
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@) constexpr are evaluated during compilation.", "[CORDIC]") {
|
||||
SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@ - C-Types") {
|
||||
TEST_CASE("ROM-based Cordic (TPL @ROM_TYPE@, @CORDIC_W@, @CORDIC_STAGES@, @CORDIC_Q@, @CORDIC_DIVIDER@) constexpr are evaluated during compilation.", "[CORDIC]") {
|
||||
SECTION("W:@CORDIC_W@ - I:4 - Stages:@CORDIC_STAGES@ - q:@CORDIC_Q@ - div:@CORDIC_DIVIDER@ - C-Types") {
|
||||
|
||||
constexpr complex<int64_t> value_in = (1U << 12) * 97;
|
||||
constexpr uint8_t angle = 169;
|
||||
|
|
|
@ -167,7 +167,7 @@ TEST_CASE("ROM-based Cordic works with AP-Types", "[CORDIC]") {
|
|||
|
||||
string input_fn = "../data/input.dat";
|
||||
|
||||
constexpr double rotation = cordic_rom::rom_cordic.rotation;
|
||||
constexpr double rotation = cordic_rom::rotation;
|
||||
constexpr double q = cordic_rom::rom_cordic.q;
|
||||
constexpr uint64_t cnt_mask = 0xFF; // Value dependant of the way the ROM is initialized
|
||||
|
||||
|
@ -244,7 +244,7 @@ TEST_CASE("ROM-based Cordic works with AP-Types", "[CORDIC]") {
|
|||
|
||||
string input_fn = "../data/input.dat";
|
||||
|
||||
constexpr double rotation = cordic_rom::rom_cordic.rotation;
|
||||
constexpr double rotation = cordic_rom::rotation;
|
||||
constexpr double q = cordic_rom::rom_cordic.q;
|
||||
constexpr uint64_t cnt_mask = 0xFF; // Value dependant of the way the ROM is initialized
|
||||
|
||||
|
@ -304,10 +304,10 @@ TEST_CASE("ROM-based Cordic works with AP-Types", "[CORDIC]") {
|
|||
|
||||
// out_stream << values_re_out[iter].to_int64() << " " << values_im_out[iter].to_int64() << " " << results_re[iter] << " " << results_im[iter] << endl;
|
||||
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic<Out_W>(values_re_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic(values_re_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
WithinAbsMatcher(results_re[iter],
|
||||
abs_margin));
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic<Out_W>(values_im_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic(values_im_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
WithinAbsMatcher(results_im[iter],
|
||||
abs_margin));
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ TEST_CASE("ROM-based Cordic works with AP-Types", "[CORDIC]") {
|
|||
|
||||
string input_fn = "../data/input.dat";
|
||||
|
||||
constexpr double rotation = cordic_rom::rom_cordic.rotation;
|
||||
constexpr double rotation = cordic_rom::rotation;
|
||||
constexpr double q = cordic_rom::rom_cordic.q;
|
||||
constexpr uint64_t cnt_mask = 0xFF; // Value dependant of the way the ROM is initialized
|
||||
|
||||
|
@ -403,7 +403,7 @@ TEST_CASE("ROM-based Cordic works with AP-Types", "[CORDIC]") {
|
|||
|
||||
string input_fn = "../data/input.dat";
|
||||
|
||||
constexpr double rotation = cordic_rom::rom_cordic.rotation;
|
||||
constexpr double rotation = cordic_rom::rotation;
|
||||
constexpr double q = cordic_rom::rom_cordic.q;
|
||||
constexpr uint64_t cnt_mask = 0xFF; // Value dependant of the way the ROM is initialized
|
||||
|
||||
|
@ -461,14 +461,14 @@ TEST_CASE("ROM-based Cordic works with AP-Types", "[CORDIC]") {
|
|||
// cout << "Series " << iter;
|
||||
// cout << " Outcome: ";
|
||||
|
||||
// out_stream << cordic_rom::scale_cordic<Out_W>(values_re_out[iter]).to_double() / cordic_rom::out_scale_factor << " "
|
||||
// << cordic_rom::scale_cordic<Out_W>(values_im_out[iter]).to_double() / cordic_rom::out_scale_factor << " "
|
||||
// out_stream << cordic_rom::scale_cordic(values_re_out[iter]).to_double() / cordic_rom::out_scale_factor << " "
|
||||
// << cordic_rom::scale_cordic(values_im_out[iter]).to_double() / cordic_rom::out_scale_factor << " "
|
||||
// << results_re[iter] << " "
|
||||
// << results_im[iter] << endl;
|
||||
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic<Out_W>(values_re_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic(values_re_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
WithinAbsMatcher(results_re[iter], abs_margin));
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic<Out_W>(values_im_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
REQUIRE_THAT(cordic_rom::scale_cordic(values_im_out[iter]).to_double() / cordic_rom::out_scale_factor,
|
||||
WithinAbsMatcher(results_im[iter], abs_margin));
|
||||
}
|
||||
// out_stream.close();
|
||||
|
|
Loading…
Reference in a new issue