mirror of
https://github.com/DrasLorus/CORDIC_Rotate_APFX.git
synced 2024-11-12 16:13:17 +01:00
initial commit
This commit is contained in:
commit
fcffa1cb7c
4 changed files with 284 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
.cache
|
||||
|
||||
build
|
||||
lib
|
||||
bin
|
||||
compile_commands.json
|
||||
*octave-workspace
|
64
CMakeLists.txt
Normal file
64
CMakeLists.txt
Normal file
|
@ -0,0 +1,64 @@
|
|||
cmake_minimum_required (VERSION 3.16.0 FATAL_ERROR)
|
||||
# setting this is required
|
||||
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib)
|
||||
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib)
|
||||
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../bin)
|
||||
|
||||
set (CMAKE_EXPORT_COMPILE_COMMANDS true)
|
||||
|
||||
project (
|
||||
CordicRotate
|
||||
LANGUAGES CXX
|
||||
VERSION 0.1
|
||||
)
|
||||
|
||||
option (EXPORT_COMMANDS "Export compile commands, for use with clangd for example." ON)
|
||||
if (EXPORT_COMMANDS)
|
||||
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
endif ()
|
||||
|
||||
|
||||
option (ENABLE_XILINX "use Xilinx provided and proprietary headers." ON)
|
||||
if (ENABLE_XILINX)
|
||||
set (
|
||||
XILINX_HOME
|
||||
/opt/Xilinx
|
||||
CACHE PATH "path to Xilinx root folder."
|
||||
)
|
||||
set (
|
||||
XILINX_VER
|
||||
"2020.2"
|
||||
CACHE STRING "Xilinx software version to use." FORCE
|
||||
)
|
||||
|
||||
if (XILINX_VER VERSION_GREATER_EQUAL "2020.1")
|
||||
set (AP_INCLUDE_DIR ${XILINX_HOME}/Vitis_HLS/${XILINX_VER}/include)
|
||||
else ()
|
||||
set (AP_INCLUDE_DIR ${XILINX_HOME}/Vivado/${XILINX_VER}/include)
|
||||
endif ()
|
||||
message (STATUS "AP headers must lie under ${AP_INCLUDE_DIR}")
|
||||
else ()
|
||||
set (
|
||||
HLS_AP_T_DIR
|
||||
${CMAKE_SOURCE_DIR}/../../Utilities/C++/hls_ap_types
|
||||
CACHE PATH "path to a clone of HLS_arbitrary_Precision_Types."
|
||||
)
|
||||
set (AP_INCLUDE_DIR ${HLS_AP_T_DIR}/include)
|
||||
endif ()
|
||||
|
||||
if ((NOT EXISTS ${AP_INCLUDE_DIR}/ap_int.h) OR (NOT EXISTS
|
||||
${AP_INCLUDE_DIR}/ap_fixed.h)
|
||||
)
|
||||
message (
|
||||
FATAL_ERROR
|
||||
"Arbitrary precision headers not found in ${AP_INCLUDE_DIR}.\n"
|
||||
"Consider disabling the ap_int feature using `-DENABLE_AP_INT=OFF`"
|
||||
" or provide a suitable path to the headers."
|
||||
)
|
||||
endif ()
|
||||
|
||||
add_library (cordic STATIC sources/CCordicRotate/CCordicRotate.cpp)
|
||||
target_include_directories (cordic SYSTEM PUBLIC ${AP_INCLUDE_DIR})
|
||||
|
1
sources/CCordicRotate/CCordicRotate.cpp
Normal file
1
sources/CCordicRotate/CCordicRotate.cpp
Normal file
|
@ -0,0 +1 @@
|
|||
#include "CCordicRotate.hpp"
|
212
sources/CCordicRotate/CCordicRotate.hpp
Normal file
212
sources/CCordicRotate/CCordicRotate.hpp
Normal file
|
@ -0,0 +1,212 @@
|
|||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <complex>
|
||||
|
||||
#include <ap_fixed.h>
|
||||
#include <ap_int.h>
|
||||
|
||||
static constexpr double atanDbl[28] {
|
||||
0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
|
||||
0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
|
||||
0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
|
||||
0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
|
||||
0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
|
||||
0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
|
||||
0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058};
|
||||
|
||||
template <uint8_t N_STAGES,
|
||||
class T,
|
||||
uint8_t ATAN_I>
|
||||
struct CAtanLUT {
|
||||
static_assert(N_STAGES < 28, "Not enough arctan available.");
|
||||
static_assert(N_STAGES <= ATAN_I, "ATAN_I can't be less than N_STAGES.");
|
||||
static_assert(std::__is_standard_integer<T>(), "Must be a standard C++ integer type.");
|
||||
constexpr CAtanLUT() : table() {
|
||||
for (uint8_t i = 0; i < N_STAGES; ++i) {
|
||||
const double scaled = atanDbl[i] * static_cast<double>(1 << ATAN_I) + 0.5;
|
||||
table[i] = static_cast<T>(scaled);
|
||||
}
|
||||
}
|
||||
T table[N_STAGES];
|
||||
};
|
||||
|
||||
template <uint8_t N_STAGES,
|
||||
uint8_t TH_W,
|
||||
uint8_t TH_I,
|
||||
uint8_t IN_W,
|
||||
uint8_t IN_I,
|
||||
uint8_t OUT_W,
|
||||
uint8_t OUT_I,
|
||||
uint8_t ATAN_I>
|
||||
class CCordicRotate {
|
||||
private:
|
||||
static constexpr auto atanLUT = CAtanLUT<N_STAGES, uint64_t, ATAN_I>();
|
||||
|
||||
public:
|
||||
static void process(
|
||||
const ap_fixed<TH_W, TH_I> & fx_angle,
|
||||
const ap_fixed<IN_W, IN_I> & fx_re_in,
|
||||
const ap_fixed<IN_W, IN_I> & fx_im_in,
|
||||
ap_fixed<OUT_W, OUT_I> & fx_re_out,
|
||||
ap_fixed<OUT_W, OUT_I> & fx_im_out);
|
||||
|
||||
CCordicRotate() {}
|
||||
virtual ~CCordicRotate() {};
|
||||
};
|
||||
|
||||
#define uint2int(sz, in) ((in & (1U << sz)) == (1U << sz) \
|
||||
? static_cast<short>(~in + 1) \
|
||||
: static_cast<short>(in))
|
||||
|
||||
template <>
|
||||
void CCordicRotate<8, 14, 10, 17, 5, 19, 12, 12>::process(
|
||||
const ap_fixed<14, 10> & fx_angle,
|
||||
const ap_fixed<17, 5> & fx_re_in,
|
||||
const ap_fixed<17, 5> & fx_im_in,
|
||||
ap_fixed<19, 12> & fx_re_out,
|
||||
ap_fixed<19, 12> & fx_im_out) {
|
||||
|
||||
constexpr uint64_t sign_mask_14 = 0x2000; // 0bxxx xx10 0000 0000 0000
|
||||
constexpr uint64_t sign_mask_17 = 0x10000; // 0bxx1 0000 0000 0000 0000
|
||||
constexpr uint64_t sign_mask_19 = 0x10000; // 0b100 0000 0000 0000 0000
|
||||
|
||||
const uint16_t angle_bits = fx_angle.bits_to_uint64();
|
||||
|
||||
const short angle = uint2int(14, angle_bits);
|
||||
|
||||
const uint32_t re_in_bits = fx_re_in.bits_to_uint64();
|
||||
const uint32_t im_in_bits = fx_im_in.bits_to_uint64();
|
||||
|
||||
const std::complex<int32_t> value(uint2int(17, re_in_bits), uint2int(17, im_in_bits));
|
||||
|
||||
int b_yn;
|
||||
int xn;
|
||||
int xtmp;
|
||||
int ytmp;
|
||||
short z;
|
||||
bool negate;
|
||||
if (angle > 1608) {
|
||||
if (((angle - 3217) & 8192) != 0) {
|
||||
z = static_cast<short>((angle - 3217) | -8192);
|
||||
} else {
|
||||
z = static_cast<short>((angle - 3217) & 8191);
|
||||
}
|
||||
if (z <= 1608) {
|
||||
negate = true;
|
||||
} else {
|
||||
if (((angle - 6434) & 8192) != 0) {
|
||||
z = static_cast<short>((angle - 6434) | -8192);
|
||||
} else {
|
||||
z = static_cast<short>((angle - 6434) & 8191);
|
||||
}
|
||||
negate = false;
|
||||
}
|
||||
} else if (angle < -1608) {
|
||||
if (((angle + 3217) & 8192) != 0) {
|
||||
z = static_cast<short>((angle + 3217) | -8192);
|
||||
} else {
|
||||
z = static_cast<short>((angle + 3217) & 8191);
|
||||
}
|
||||
if (z >= -1608) {
|
||||
negate = true;
|
||||
} else {
|
||||
if (((angle + 6434) & 8192) != 0) {
|
||||
z = static_cast<short>((angle + 6434) | -8192);
|
||||
} else {
|
||||
z = static_cast<short>((angle + 6434) & 8191);
|
||||
}
|
||||
negate = false;
|
||||
}
|
||||
} else {
|
||||
z = angle;
|
||||
negate = false;
|
||||
}
|
||||
z = static_cast<short>(z << 2);
|
||||
if ((z & 8192) != 0) {
|
||||
z = static_cast<short>(z | -8192);
|
||||
} else {
|
||||
z = static_cast<short>(z & 8191);
|
||||
}
|
||||
xn = value.real();
|
||||
b_yn = value.imag();
|
||||
xtmp = value.real();
|
||||
ytmp = value.imag();
|
||||
for (int idx = 0; idx < 8; idx++) {
|
||||
if (z < 0) {
|
||||
z = static_cast<short>(z + atanLUT.table[idx]);
|
||||
if ((z & 8192) != 0) {
|
||||
z = static_cast<short>(z | -8192);
|
||||
} else {
|
||||
z = static_cast<short>(z & 8191);
|
||||
}
|
||||
ytmp += xn;
|
||||
if ((ytmp & 262144) != 0) {
|
||||
xn = ytmp | -262144;
|
||||
} else {
|
||||
xn = ytmp & 262143;
|
||||
}
|
||||
ytmp = b_yn - xtmp;
|
||||
if ((ytmp & 262144) != 0) {
|
||||
b_yn = ytmp | -262144;
|
||||
} else {
|
||||
b_yn = ytmp & 262143;
|
||||
}
|
||||
} else {
|
||||
z = static_cast<short>(z - atanLUT.table[idx]);
|
||||
if ((z & 8192) != 0) {
|
||||
z = static_cast<short>(z | -8192);
|
||||
} else {
|
||||
z = static_cast<short>(z & 8191);
|
||||
}
|
||||
ytmp = xn - ytmp;
|
||||
if ((ytmp & 262144) != 0) {
|
||||
xn = ytmp | -262144;
|
||||
} else {
|
||||
xn = ytmp & 262143;
|
||||
}
|
||||
ytmp = b_yn + xtmp;
|
||||
if ((ytmp & 262144) != 0) {
|
||||
b_yn = ytmp | -262144;
|
||||
} else {
|
||||
b_yn = ytmp & 262143;
|
||||
}
|
||||
}
|
||||
ytmp = xn >> (idx + 1);
|
||||
if ((ytmp & 262144) != 0) {
|
||||
xtmp = ytmp | -262144;
|
||||
} else {
|
||||
xtmp = ytmp & 262143;
|
||||
}
|
||||
ytmp = b_yn >> (idx + 1);
|
||||
if ((ytmp & 262144) != 0) {
|
||||
ytmp |= -262144;
|
||||
} else {
|
||||
ytmp &= 262143;
|
||||
}
|
||||
}
|
||||
if (negate) {
|
||||
if ((-xn & 262144) != 0) {
|
||||
xn = -xn | -262144;
|
||||
} else {
|
||||
xn = -xn & 262143;
|
||||
}
|
||||
if ((-b_yn & 262144) != 0) {
|
||||
b_yn = -b_yn | -262144;
|
||||
} else {
|
||||
b_yn = -b_yn & 262143;
|
||||
}
|
||||
}
|
||||
|
||||
ap_fixed<19, 7> re, im;
|
||||
re.V = static_cast<uint32_t>((xn * 39797L) >> 16);
|
||||
im.V = static_cast<uint32_t>((b_yn * 39797L) >> 16);
|
||||
|
||||
ap_fx_cpx<19, 7> iterative_factor;
|
||||
iterative_factor.real(re);
|
||||
iterative_factor.imag(im);
|
||||
|
||||
return iterative_factor;
|
||||
}
|
Loading…
Reference in a new issue