diff --git a/.gitignore b/.gitignore index 430a4a8..a2e344a 100644 --- a/.gitignore +++ b/.gitignore @@ -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 \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a510a32..335bb35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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." diff --git a/RomGenerators/CMakeLists.txt b/RomGenerators/CMakeLists.txt index 3aabd08..d784d47 100644 --- a/RomGenerators/CMakeLists.txt +++ b/RomGenerators/CMakeLists.txt @@ -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) diff --git a/RomGenerators/sources/RomGeneratorConst/RomGeneratorConst.hpp b/RomGenerators/sources/RomGeneratorConst/RomGeneratorConst.hpp index 0e9dd2b..597517f 100644 --- a/RomGenerators/sources/RomGeneratorConst/RomGeneratorConst.hpp +++ b/RomGenerators/sources/RomGeneratorConst/RomGeneratorConst.hpp @@ -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 +template void generate_rom_header_cst(const char * filename) { constexpr CRomGeneratorConst 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 \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 +template void generate_rom_header_cst_raw(const char * filename = "rom_cordic.txt") { - constexpr CRomGeneratorConst rom {}; + constexpr CRomGeneratorConst rom {}; FILE * rom_file = fopen(filename, "w"); if (!bool(rom_file)) { diff --git a/RomGenerators/sources/RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.cpp b/RomGenerators/sources/RomGeneratorML/RomGeneratorML.cpp similarity index 95% rename from RomGenerators/sources/RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.cpp rename to RomGenerators/sources/RomGeneratorML/RomGeneratorML.cpp index d7a88b2..bc0e966 100644 --- a/RomGenerators/sources/RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.cpp +++ b/RomGenerators/sources/RomGeneratorML/RomGeneratorML.cpp @@ -17,4 +17,4 @@ * */ -#include "RomGeneratorMCHalfPi.hpp" +#include "RomGeneratorML.hpp" diff --git a/RomGenerators/sources/RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.hpp b/RomGenerators/sources/RomGeneratorML/RomGeneratorML.hpp similarity index 77% rename from RomGenerators/sources/RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.hpp rename to RomGenerators/sources/RomGeneratorML/RomGeneratorML.hpp index 4c6d3ba..f4f832c 100644 --- a/RomGenerators/sources/RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.hpp +++ b/RomGenerators/sources/RomGeneratorML/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 #include #include #include -template -class CRomGeneratorMCHalfPi { +template +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 cordic_MC(const std::complex & x_in, + constexpr std::complex cordic_ML(const std::complex & 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 res; for (uint32_t v = 0; v < max_length; v++) { - const std::complex res_int = cordic_MC(x, v); + const std::complex res_int = cordic_ML(x, v); const std::complex res_dbl(double(res_int.real()) / double(scale_factor - 1), double(res_int.imag()) / double(scale_factor - 1)); @@ -98,9 +99,9 @@ public: } }; -template -void generate_rom_header_mc(const char * filename) { - const CRomGeneratorMCHalfPi rom; +template +void generate_rom_header_ml(const char * filename) { + const CRomGeneratorML 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 \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 -void generate_rom_header_mc_raw(const char * filename) { - const CRomGeneratorMCHalfPi rom; +template +void generate_rom_header_ml_raw(const char * filename) { + const CRomGeneratorML 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 \ No newline at end of file +#endif // _ROM_GENERATOR_ML \ No newline at end of file diff --git a/RomGenerators/sources/main_generator.cpp b/RomGenerators/sources/main_generator.cpp deleted file mode 100644 index 5a92f0c..0000000 --- a/RomGenerators/sources/main_generator.cpp +++ /dev/null @@ -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 . - * - */ - -#include "RomGeneratorConst/RomGeneratorConst.hpp" -#include "RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.hpp" - -#include -#include -#include - -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; -} diff --git a/RomGenerators/sources/main_generator.cpp.in b/RomGenerators/sources/main_generator.cpp.in index 9129810..4c92729 100644 --- a/RomGenerators/sources/main_generator.cpp.in +++ b/RomGenerators/sources/main_generator.cpp.in @@ -18,7 +18,7 @@ */ #include "RomGeneratorConst/RomGeneratorConst.hpp" -#include "RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.hpp" +#include "RomGeneratorML/RomGeneratorML.hpp" #include #include @@ -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; } diff --git a/RomGenerators/sources/main_legacy.cpp b/RomGenerators/sources/main_legacy.cpp index 0cccada..608cd3b 100644 --- a/RomGenerators/sources/main_legacy.cpp +++ b/RomGenerators/sources/main_legacy.cpp @@ -18,7 +18,7 @@ */ #include "RomGeneratorConst/RomGeneratorConst.hpp" -#include "RomGeneratorMCHalfPi/RomGeneratorMCHalfPi.hpp" +#include "RomGeneratorML/RomGeneratorML.hpp" #include #include @@ -56,7 +56,7 @@ constexpr complex cordic(complex x_in, template 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: diff --git a/sources/CCordicRotateConstexpr/CCordicRotateConstexpr.hpp b/sources/CCordicRotateConstexpr/CCordicRotateConstexpr.hpp index de78fa6..e21f911 100644 --- a/sources/CCordicRotateConstexpr/CCordicRotateConstexpr.hpp +++ b/sources/CCordicRotateConstexpr/CCordicRotateConstexpr.hpp @@ -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 #include @@ -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::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 - static ap_int scale_cordic(const ap_int & in) { - const ap_int tmp = in * ap_uint<3>(kn_i); - return ap_int(tmp >> 3); + static ap_int scale_cordic(const ap_int & in) { + const ap_int tmp = in * ap_uint<3>(kn_i); + return ap_int(tmp >> 3); } static void cordic(const ap_int & re_in, const ap_int & im_in, const ap_uint<8> & counter, ap_int & re_out, ap_int & im_out) { - const ap_uint R = (rom_cordic.rom[counter] >> (7 - nb_stages)); + const ap_uint R = rom_cordic.rom[counter]; - ap_int A = bool(R[nb_stages]) ? ap_int(-re_in) : re_in; - ap_int B = bool(R[nb_stages]) ? ap_int(-im_in) : im_in; + ap_int A = bool(R[0]) ? ap_int(-re_in) : re_in; + ap_int B = bool(R[0]) ? ap_int(-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 \ No newline at end of file +#endif // C_CORDIC_ROTATE_CONSTEXPR_HPP \ No newline at end of file diff --git a/sources/CCordicRotateRom/CCordicRotateRom.cpp.in b/sources/CCordicRotateRom/CCordicRotateRom.cpp.in index 4d961ef..c241f48 100644 --- a/sources/CCordicRotateRom/CCordicRotateRom.cpp.in +++ b/sources/CCordicRotateRom/CCordicRotateRom.cpp.in @@ -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" diff --git a/sources/CCordicRotateRom/CCordicRotateRom.hpp.in b/sources/CCordicRotateRom/CCordicRotateRom.hpp.in index 94fbebc..d7e79d9 100644 --- a/sources/CCordicRotateRom/CCordicRotateRom.hpp.in +++ b/sources/CCordicRotateRom/CCordicRotateRom.hpp.in @@ -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 #include @@ -31,7 +31,7 @@ #include #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 -class CCordicRotateRom { +class CCordicRotateRom { 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 - static ap_int scale_cordic(const ap_int & in) { - const ap_int tmp = in * ap_uint<3>(kn_i); - return ap_int(tmp >> 3); + static ap_int scale_cordic(const ap_int & in) { + const ap_int tmp = in * ap_uint<3>(kn_i); + return ap_int(tmp >> 3); } static void cordic(const ap_int & re_in, const ap_int & im_in, const ap_uint<8> & counter, ap_int & re_out, ap_int & im_out) { - const ap_uint R = (cordic_roms::@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@[counter] >> (7 - nb_stages)); + const ap_uint R = cordic_roms::@ROM_TYPE@_@CORDIC_W@_@CORDIC_STAGES@_@CORDIC_Q@_@CORDIC_DIVIDER@[counter]; - ap_int A = bool(R[nb_stages]) ? ap_int(-re_in) : re_in; - ap_int B = bool(R[nb_stages]) ? ap_int(-im_in) : im_in; + ap_int A = bool(R[0]) ? ap_int(-re_in) : re_in; + ap_int B = bool(R[0]) ? ap_int(-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 diff --git a/sources/CCordicRotateRom/CCordicRotateRomTemplate.hpp b/sources/CCordicRotateRom/CCordicRotateRomTemplate.hpp index 2e25d59..34e2683 100644 --- a/sources/CCordicRotateRom/CCordicRotateRomTemplate.hpp +++ b/sources/CCordicRotateRom/CCordicRotateRomTemplate.hpp @@ -21,15 +21,16 @@ #define C_CORDIC_ROTATE_ROM_TEMPLATE enum rom_types { - mc, + ml, cst }; -template +template 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 \ No newline at end of file diff --git a/sources/tb/cordic_rom_tb.cpp.in b/sources/tb/cordic_rom_tb.cpp.in index 3fe4a37..da8843f 100644 --- a/sources/tb/cordic_rom_tb.cpp.in +++ b/sources/tb/cordic_rom_tb.cpp.in @@ -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 #include @@ -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 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 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 e = exp(complex(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(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(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 value_in = (1U << 12) * 97; constexpr uint8_t angle = 169; diff --git a/sources/tb/cordic_tb.cpp b/sources/tb/cordic_tb.cpp index 9afb750..759fc1b 100644 --- a/sources/tb/cordic_tb.cpp +++ b/sources/tb/cordic_tb.cpp @@ -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(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(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(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 << " " + // 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(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(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();