diff --git a/CMakeLists.txt b/CMakeLists.txt index fc42af4..4461a40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,12 +15,20 @@ project ( VERSION 0.1 ) -option (EXPORT_COMMANDS "Export compile commands, for use with clangd for example." ON) +#################################################################################################### +# Options +#################################################################################################### + +option (EXPORT_COMMANDS "export compile commands, for use with clangd for example." ON) +option (ENABLE_XILINX "use Xilinx provided and proprietary headers." OFF) + +option (ENABLE_TESTING "use Catch2 in conjunction with CTest as a test suite." ON) +#################################################################################################### + if (EXPORT_COMMANDS) - set (CMAKE_EXPORT_COMPILE_COMMANDS ON) + set (CMAKE_EXPORT_COMPILE_COMMANDS ON) endif () -option (ENABLE_XILINX "use Xilinx provided and proprietary headers." ON) if (ENABLE_XILINX) set ( XILINX_HOME @@ -30,7 +38,7 @@ if (ENABLE_XILINX) set ( XILINX_VER "2020.2" - CACHE STRING "Xilinx software version to use." FORCE + CACHE STRING "Xilinx software version to use." ) if (XILINX_VER VERSION_GREATER_EQUAL "2020.1") @@ -40,39 +48,37 @@ if (ENABLE_XILINX) 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) + find_file (AP_FIXED ap_fixed.h PATH_SUFFIXES ap_types hls_ap_types/include REQUIRED) + + get_filename_component (AP_INCLUDE_DIR ${AP_FIXED} DIRECTORY) endif () -if ((NOT EXISTS ${AP_INCLUDE_DIR}/ap_int.h) OR (NOT EXISTS - ${AP_INCLUDE_DIR}/ap_fixed.h) +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" + "Please provide a suitable path to the headers." + ) +endif () + +add_subdirectory (RomGenerators) + +add_library ( + cordic STATIC sources/CCordicRotate/CCordicRotate.cpp + sources/CCordicRotateHalfPiRom/CCordicRotateHalfPiRom.cpp ) - message ( - FATAL_ERROR - "Arbitrary precision headers not found in ${AP_INCLUDE_DIR}.\n" - "Please provide a suitable path to the headers." - ) -endif () - -add_subdirectory(RomGenerators) - -add_library (cordic STATIC sources/CCordicRotate/CCordicRotate.cpp sources/CCordicRotateHalfPiRom/CCordicRotateHalfPiRom.cpp) 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) -find_package(Catch2 REQUIRED) +if (ENABLE_TESTING) + find_package (Catch2 REQUIRED) -add_library (catch_common OBJECT sources/tb/main_catch2.cpp) -target_link_libraries(catch_common PUBLIC Catch2::Catch2) + 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) -target_link_libraries(cordic_tb PUBLIC cordic catch_common) + add_executable (cordic_tb sources/tb/cordic_tb.cpp) + target_link_libraries (cordic_tb PUBLIC cordic catch_common) -include(CTest) -include(Catch) -catch_discover_tests(cordic_tb) + include (CTest) + include (Catch) + catch_discover_tests (cordic_tb) +endif () diff --git a/cmake_format_conf.py b/cmake_format_conf.py new file mode 100644 index 0000000..45a1408 --- /dev/null +++ b/cmake_format_conf.py @@ -0,0 +1,240 @@ +# ---------------------------------- +# Options affecting listfile parsing +# ---------------------------------- +with section("parse"): + + # Specify structure for custom cmake functions + # additional_commands = {'foo': {'flags': ['BAR', 'BAZ'], + # 'kwargs': {'DEPENDS': '*', 'HEADERS': '*', 'SOURCES': '*'}}} + + # Override configurations per-command where available + override_spec = {} + + # Specify variable tags. + vartags = [] + + # Specify property tags. + proptags = [] + +# ----------------------------- +# Options affecting formatting. +# ----------------------------- +with section("format"): + + # Disable formatting entirely, making cmake-format a no-op + disable = False + + # How wide to allow formatted cmake files + line_width = 100 + + # How many spaces to tab for indent + tab_size = 2 + + # If true, lines are indented using tab characters (utf-8 0x09) instead of + # space characters (utf-8 0x20). In cases where the layout would + # require a fractional tab character, the behavior of the fractional + # indentation is governed by + use_tabchars = False + + # If is True, then the value of this variable indicates how + # fractional indentions are handled during whitespace replacement. If set to + # 'use-space', fractional indentation is left as spaces (utf-8 0x20). If set + # to `round-up` fractional indentation is replaced with a single tab character + # (utf-8 0x09) effectively shifting the column to the next tabstop + fractional_tab_policy = 'round-up' + + # If an argument group contains more than this many sub-groups (parg or kwarg + # groups) then force it to a vertical layout. + max_subgroups_hwrap = 2 + + # If a positional argument group contains more than this many arguments, then + # force it to a vertical layout. + max_pargs_hwrap = 3 + + # If a cmdline positional group consumes more than this many lines without + # nesting, then invalidate the layout (and nest) + max_rows_cmdline = 2 + + # If true, separate flow control names from their parentheses with a space + separate_ctrl_name_with_space = True + + # If true, separate function names from parentheses with a space + separate_fn_name_with_space = True + + # If a statement is wrapped to more than one line, than dangle the closing + # parenthesis on its own line. + dangle_parens = True + + # If the trailing parenthesis must be 'dangled' on its on line, then align it + # to this reference: `prefix`: the start of the statement, `prefix-indent`: + # the start of the statement, plus one indentation level, `child`: align to + # the column of the arguments + dangle_align = 'prefix' + + # If the statement spelling length (including space and parenthesis) is + # smaller than this amount, then force reject nested layouts. + min_prefix_chars = 4 + + # If the statement spelling length (including space and parenthesis) is larger + # than the tab width by more than this amount, then force reject un-nested + # layouts. + max_prefix_chars = 10 + + # If a candidate layout is wrapped horizontally but it exceeds this many + # lines, then reject the layout. + max_lines_hwrap = 2 + + # What style line endings to use in the output. + line_ending = 'unix' + + # Format command names consistently as 'lower' or 'upper' case + command_case = 'lower' + + # Format keywords consistently as 'lower' or 'upper' case + keyword_case = 'upper' + + # A list of command names which should always be wrapped + always_wrap = [] + + # If true, the argument lists which are known to be sortable will be sorted + # lexicographicall + enable_sort = True + + # If true, the parsers may infer whether or not an argument list is sortable + # (without annotation). + autosort = False + + # By default, if cmake-format cannot successfully fit everything into the + # desired linewidth it will apply the last, most agressive attempt that it + # made. If this flag is True, however, cmake-format will print error, exit + # with non-zero status code, and write-out nothing + require_valid_layout = False + + # A dictionary mapping layout nodes to a list of wrap decisions. See the + # documentation for more information. + layout_passes = {} + +# ------------------------------------------------ +# Options affecting comment reflow and formatting. +# ------------------------------------------------ +with section("markup"): + + # What character to use for bulleted lists + bullet_char = '*' + + # What character to use as punctuation after numerals in an enumerated list + enum_char = '.' + + # If comment markup is enabled, don't reflow the first comment block in each + # listfile. Use this to preserve formatting of your copyright/license + # statements. + first_comment_is_literal = False + + # If comment markup is enabled, don't reflow any comment block which matches + # this (regex) pattern. Default is `None` (disabled). + literal_comment_pattern = None + + # Regular expression to match preformat fences in comments default= + # ``r'^\s*([`~]{3}[`~]*)(.*)$'`` + fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$' + + # Regular expression to match rulers in comments default= + # ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'`` + ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$' + + # If a comment line matches starts with this pattern then it is explicitly a + # trailing comment for the preceeding argument. Default is '#<' + explicit_trailing_pattern = '#<' + + # If a comment line starts with at least this many consecutive hash + # characters, then don't lstrip() them off. This allows for lazy hash rulers + # where the first hash int8_t is not separated by space + hashruler_min_length = 10 + + # If true, then insert a space between the first hash int8_t and remaining hash + # chars in a hash ruler, and normalize its length to fill the column + canonicalize_hashrulers = True + + # enable comment markup parsing and reflow + enable_markup = True + +# ---------------------------- +# Options affecting the linter +# ---------------------------- +with section("lint"): + + # a list of lint codes to disable + disabled_codes = [] + + # regular expression pattern describing valid function names + function_pattern = '[0-9a-z_]+' + + # regular expression pattern describing valid macro names + macro_pattern = '[0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with global + # (cache) scope + global_var_pattern = '[A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with global + # scope (but internal semantic) + internal_var_pattern = '_[A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with local + # scope + local_var_pattern = '[a-z][a-z0-9_]+' + + # regular expression pattern describing valid names for privatedirectory + # variables + private_var_pattern = '_[0-9a-z_]+' + + # regular expression pattern describing valid names for public directory + # variables + public_var_pattern = '[A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for function/macro + # arguments and loop variables. + argument_var_pattern = '[a-z][a-z0-9_]+' + + # regular expression pattern describing valid names for keywords used in + # functions or macros + keyword_pattern = '[A-Z][0-9A-Z_]+' + + # In the heuristic for C0201, how many conditionals to match within a loop in + # before considering the loop a parser. + max_conditionals_custom_parser = 2 + + # Require at least this many newlines between statements + min_statement_spacing = 1 + + # Require no more than this many newlines between statements + max_statement_spacing = 2 + max_returns = 6 + max_branches = 12 + max_arguments = 5 + max_localvars = 15 + max_statements = 50 + +# ------------------------------- +# Options affecting file encoding +# ------------------------------- +with section("encode"): + + # If true, emit the unicode byte-order mark (BOM) at the start of the file + emit_byteorder_mark = False + + # Specify the encoding of the input file. Defaults to utf-8 + input_encoding = 'utf-8' + + # Specify the encoding of the output file. Defaults to utf-8. Note that cmake + # only claims to support utf-8 so be careful when using anything else + output_encoding = 'utf-8' + +# ------------------------------------- +# Miscellaneous configurations options. +# ------------------------------------- +with section("misc"): + + # A dictionary containing any per-command configuration overrides. Currently + # only `command_case` is supported. + per_command = {} diff --git a/sources/tb/cordic_tb.cpp b/sources/tb/cordic_tb.cpp index 9c09003..b09f0ec 100644 --- a/sources/tb/cordic_tb.cpp +++ b/sources/tb/cordic_tb.cpp @@ -186,7 +186,6 @@ TEST_CASE("ROM-based Cordic works with AP-Types", "[CORDIC]") { 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 @@ -222,7 +221,7 @@ TEST_CASE("ROM-based Cordic works with AP-Types", "[CORDIC]") { SECTION("W:16 - I:4 - Stages:6 - q:64 - internal scaling") { // typedef CCordicRotateRomHalfPi<16, 4, 6, 64> cordic_rom; static constexpr cordic_rom cordic {}; - + string input_fn = "../data/input.dat"; constexpr double rotation = cordic_rom::rom_cordic.rotation; @@ -300,3 +299,27 @@ TEST_CASE("ROM-based Cordic works with AP-Types", "[CORDIC]") { // Return 0 if the test passed } } + +TEST_CASE("ROM-based Cordic constexpr are evaluated during compilation.", "[CORDIC]") { + constexpr unsigned n_lines = 100000; + + SECTION("W:16 - I:4 - Stages:6 - q:64 - C-Types") { + + static constexpr cordic_rom cordic {}; + + constexpr double rotation = cordic_rom::rom_cordic.rotation; + constexpr double q = cordic_rom::rom_cordic.q; + constexpr uint64_t max_length = cordic_rom::rom_cordic.max_length; + + constexpr complex value_in = (1U << 12) * 97; + constexpr uint8_t angle = 169; + + double results_re[n_lines]; + double results_im[n_lines]; + + constexpr complex res = cordic.cordic(value_in, angle); + static_assert(res == cordic.cordic(value_in, angle), "Test"); + REQUIRE_FALSE(res == cordic.cordic(complex(1, 0), angle)); + REQUIRE(res == cordic.cordic(value_in, angle)); + } +}