diff --git a/.gitignore b/.gitignore index 4b38f6f..430a4a8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ lib bin compile_commands.json *octave-workspace +.vscode sources/CCordicRotateRom/CCordicRotateRom_*.?pp sources/CordicRoms/cordic_rom_*.?pp diff --git a/CMakeLists.txt b/CMakeLists.txt index 271f05e..a510a32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,7 @@ else () /usr/include CACHE PATH "location of ap_types include directory." ) + find_file ( AP_FIXED ap_fixed.h HINTS ${AP_TYPES_HINT} @@ -96,8 +97,10 @@ endif () set ( ROM_TYPE "mc" - CACHE STRING "RomGenerator to use, either 'mc' or 'cst'." + CACHE STRING "RomGenerator to use, either 'mc' or 'cst'." ) +set_property(CACHE ROM_TYPE PROPERTY STRINGS "mc" "cst") + set ( CORDIC_W "16" @@ -117,8 +120,9 @@ set ( 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 ROM_HEADER - +string ( + CONFIGURE ${ROM_DIRECTORY}/cordic_rom_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}.hpp + ROM_HEADER ) add_custom_command ( OUTPUT ${ROM_HEADER} @@ -145,39 +149,53 @@ target_include_directories (cordic_rom_gen PUBLIC sources) target_include_directories (cordic_rom_gen SYSTEM PUBLIC ${AP_INCLUDE_DIR}) target_link_libraries (cordic_rom_gen PUBLIC romgen) -file (GLOB ALL_CORDIC_ROM_HEADERS sources/CCordicRotateRom/*.hpp) file (GLOB ALL_CORDIC_ROM_SOURCES sources/CCordicRotateRom/*.cpp) -file (GLOB ALL_ROM_HEADERS sources/CordicRoms/*.hpp) +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} + sources/CCordicRotateConstexpr/CCordicRotateConstexpr.cpp ${ALL_CORDIC_ROM_SOURCES} ) target_include_directories (cordic PUBLIC sources) target_include_directories (cordic SYSTEM PUBLIC ${AP_INCLUDE_DIR}) -target_link_libraries (cordic PUBLIC romgen) +target_link_libraries (cordic PUBLIC romgen cordic_rom_gen) # ################################################################################################## if (ENABLE_TESTING) find_package (Catch2 REQUIRED) - string (CONFIGURE - ${CMAKE_CURRENT_SOURCE_DIR}/sources/tb/cordic_rom_tb_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}.cpp - TB_SOURCE) - configure_file ( - sources/tb/cordic_rom_tb.cpp.in - ${TB_SOURCE} @ONLY + string ( + CONFIGURE + ${CMAKE_CURRENT_SOURCE_DIR}/sources/tb/cordic_rom_tb_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}.cpp + TB_SOURCE ) + configure_file (sources/tb/cordic_rom_tb.cpp.in ${TB_SOURCE} @ONLY) add_library (catch_common OBJECT sources/tb/main_catch2.cpp) target_link_libraries (catch_common PUBLIC Catch2::Catch2) - add_executable (cordic_tb sources/tb/cordic_tb.cpp ${TB_SOURCE}) + file (GLOB ALL_ROM_TB_SOURCES sources/tb/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}) target_link_libraries (cordic_tb PUBLIC cordic catch_common) include (CTest) include (Catch) catch_discover_tests (cordic_tb) endif () + +file (GLOB ALL_ROM_HEADERS sources/CordicRoms/cordic_rom_*.hpp) +file (GLOB ALL_CORDIC_ROM_HEADERS sources/CCordicRotateRom/CCordicRotateRom_*.hpp) +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 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/README.md b/README.md index 1b54db0..a6a2cbf 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,25 @@ A free way to implement a CORDIC-based rotation using HLS, with bit-accurate pre [CORDIC](https://en.wikipedia.org/wiki/CORDIC) (COordinate Rotation DIgital Computer) is an efficient way to implement hardware complex rotations (e.g. `z * exp(jw)`, with `z = x + jy` a complex and `w` a real angle). It is also useful for microcontrollers or microprocessors lacking floating-point units, as such multiplications can consume a noticeable amount of CPU cycles. -This implementation in C++14 (`-std=c++14`) is suitable for hardware simulation and (with the right lib's and a few tweaks) for synthesis. +This implementation in C++14 (`-std=c++14`) is suitable for hardware simulation and (with the right headers and maybe a few tweaks) for synthesis. -This repository mainly hosts `CCordicRotateHalfPiRom`, CORDIC-based rotation units which rely on a ROM. -Currently, It ranges from 2 to 7 stages, and the word length is a template. -It depends on ROM generators, each one producing a ROM table which contains control signals for each CORDIC stage, depending on the input angle. There are generators: +This repository defines two working CORDIC-based rotation units classes, `CCordicRotateRom` and `CCordicRotateConstexpr`, which both rely on a ROM. +They differ by the way the ROM is generated: -- A true `constexpr` one, that is entirely processed by the compiler. -- A Monte-Carlo one, that is evaluated at runtime and can be used to produced ROM-headers, suitable for Autoconf/CMake header generations. +- `CCordicRotateRom` depends on ROM headers generated by the build system (i.e. CMake) using configure files and build-time dependencies, +- `CCordicRotateConstexpr` ROM is completely compiled using C++14 *constexpr* mechanism, which constraint the ROM type but allow cleaner build dependencies. -Only rotations of pi and pi/2 are currently supported, but support for any pi/2^k can be easily added. +Currently, They can have from 2 to 7 stages, and the word length is a template. +ROM tables contain control signals for each CORDIC stage, the input angle being the address. There are two kinds of generators: -`CCordicRotate` is an unfinished template that would implement a *smart* CORDIC, which can work without a ROM. +- A true *constexpr* one, that is entirely processed by the compiler. +- A Monte-Carlo one, that is evaluated at runtime. + +Both can be used to produced ROM headers but only the first one can be used for `CCordicRotateConstexpr`. + +Only rotations of pi and pi/2 are currently supported, but support for any pi/2^k might be added later. + +`CCordicRotateSmart` is an unfinished template that would implement a *"smart"* CORDIC, which would not need a ROM. ## Test suite and dependencies @@ -25,7 +32,7 @@ The [Catch2](https://github.com/catchorg/Catch) test framework has been used in The [GitHub mirror of the repository](https://github.com/DrasLorus/CORDIC_Rotate_APFX) also make use of GitHub Actions and Docker as a CI/CD solution. - Has been tested successfully compiled with: - - GNU GCC 9.4, 10.1, 10.2 and 11.2, + - GNU GCC 6.2 (*Xilinx bundled version*), 6.5, 9.4, 10.1, 10.2 and 11.2, - LLVM Clang 12.0 and 13.0, - Uses Catch v2.13.7, - Depends on Xilinx HLS arbitrary precision types, available as FOSS [here provided by Xilinx](https://github.com/Xilinx/HLS_arbitrary_Precision_Types) or [here patched by myself](https://github.com/DrasLorus/HLS_arbitrary_Precision_Types). Note: Xilinx also provides proprietary versions of those headers, suitable for synthesis and implementation, bundled with their products. diff --git a/sources/CordicRoms/README.md b/sources/CordicRoms/README.md new file mode 100644 index 0000000..06388d0 --- /dev/null +++ b/sources/CordicRoms/README.md @@ -0,0 +1,7 @@ +# CORDIC ROM Headers + +This directory contains build-time generated CORDIC ROM headers. +They are in the form `cordic_rom_${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}.hpp` and contain (besides the usual double-inclusion protection) a table `constexpr uint8_t ${ROM_TYPE}_${CORDIC_W}_${CORDIC_STAGES}_${CORDIC_Q}` under the namespace `cordic_roms`. It is filled with corresponding CORDIC control signals. +This table is generated using its corresponding `rom_generator`, itself built and called by the build system. + +*Note: This directory is usually empty, but will be filled automatically when needed.*