From dd782308940e4b206e798eb2f0fa203b6e8c7f07 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 12 Nov 2011 15:45:52 -0800 Subject: convert: made conversion functions into classes so they can keep state --- host/lib/convert/convert_common.hpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'host/lib/convert/convert_common.hpp') diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 34fb848c3..ce82f6216 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -21,30 +21,30 @@ #include #include #include +#include #include -#define _DECLARE_CONVERTER(fcn, in_form, num_in, out_form, num_out, prio) \ - static void fcn( \ - const uhd::convert::input_type &inputs, \ - const uhd::convert::output_type &outputs, \ - const size_t nsamps, const double scale_factor \ - ); \ - UHD_STATIC_BLOCK(__register_##fcn##_##prio){ \ +#define _DECLARE_CONVERTER(name, in_form, num_in, out_form, num_out, prio) \ + struct name : public uhd::convert::converter{ \ + static sptr make(void){return sptr(new name());} \ + double scale_factor; \ + void set_scalar(const double s){scale_factor = s;} \ + void operator()(const input_type&, const output_type&, const size_t); \ + }; \ + UHD_STATIC_BLOCK(__register_##name##_##prio){ \ uhd::convert::id_type id; \ id.input_format = #in_form; \ id.num_inputs = num_in; \ id.output_format = #out_form; \ id.num_outputs = num_out; \ - uhd::convert::register_converter(id, fcn, prio); \ + uhd::convert::register_converter(id, boost::bind(&name::make), prio); \ } \ - static void fcn( \ - const uhd::convert::input_type &inputs, \ - const uhd::convert::output_type &outputs, \ - const size_t nsamps, const double scale_factor \ + void name::operator()( \ + const input_type &inputs, const output_type &outputs, const size_t nsamps \ ) #define DECLARE_CONVERTER(in_form, num_in, out_form, num_out, prio) \ - _DECLARE_CONVERTER(__convert_##in_form##_##num_in##_##out_form##_##num_out, in_form, num_in, out_form, num_out, prio) + _DECLARE_CONVERTER(__convert_##in_form##_##num_in##_##out_form##_##num_out##_##prio, in_form, num_in, out_form, num_out, prio) /*********************************************************************** * Typedefs -- cgit v1.2.3 From f31afff6dd03ee500ba48e81e0caf26bc61e430d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 12 Nov 2011 16:33:26 -0800 Subject: convert: added table conversion routine for sc16 to floats --- host/lib/convert/CMakeLists.txt | 1 + host/lib/convert/convert_common.hpp | 3 +- host/lib/convert/convert_with_tables.cpp | 139 +++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 host/lib/convert/convert_with_tables.cpp (limited to 'host/lib/convert/convert_common.hpp') diff --git a/host/lib/convert/CMakeLists.txt b/host/lib/convert/CMakeLists.txt index 4cc421884..1fe92d93a 100644 --- a/host/lib/convert/CMakeLists.txt +++ b/host/lib/convert/CMakeLists.txt @@ -117,5 +117,6 @@ LIBUHD_PYTHON_GEN_SOURCE( ) LIBUHD_APPEND_SOURCES( + ${CMAKE_CURRENT_SOURCE_DIR}/convert_with_tables.cpp ${CMAKE_CURRENT_SOURCE_DIR}/convert_impl.cpp ) diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index ce82f6216..f963e29ee 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #define _DECLARE_CONVERTER(name, in_form, num_in, out_form, num_out, prio) \ @@ -37,7 +36,7 @@ id.num_inputs = num_in; \ id.output_format = #out_form; \ id.num_outputs = num_out; \ - uhd::convert::register_converter(id, boost::bind(&name::make), prio); \ + uhd::convert::register_converter(id, &name::make, prio); \ } \ void name::operator()( \ const input_type &inputs, const output_type &outputs, const size_t nsamps \ diff --git a/host/lib/convert/convert_with_tables.cpp b/host/lib/convert/convert_with_tables.cpp new file mode 100644 index 000000000..b3702e6ea --- /dev/null +++ b/host/lib/convert/convert_with_tables.cpp @@ -0,0 +1,139 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "convert_common.hpp" +#include +#include + +using namespace uhd::convert; + +static const size_t sc16_table_len = size_t(1 << 16); + +#ifdef BOOST_BIG_ENDIAN +# define ITEM32_BE_TO_R16(x) boost::uint16_t(x >> 16) +# define ITEM32_BE_TO_I16(x) boost::uint16_t(x) +# define ITEM32_LE_TO_R16(x) boost::uint16_t(x) +# define ITEM32_LE_TO_I16(x) boost::uint16_t(x >> 16) +#else +# define ITEM32_BE_TO_R16(x) boost::uint16_t(x) +# define ITEM32_BE_TO_I16(x) boost::uint16_t(x >> 16) +# define ITEM32_LE_TO_R16(x) boost::uint16_t(x >> 16) +# define ITEM32_LE_TO_I16(x) boost::uint16_t(x) +#endif + +/*********************************************************************** + * Implementation for sc16 be lookup table + **********************************************************************/ +template class convert_sc16_item32_be_1_to_fcxx_1 : public converter{ +public: + convert_sc16_item32_be_1_to_fcxx_1(void): _table(sc16_table_len){} + + void set_scalar(const double scalar){ + for (size_t i = 0; i < sc16_table_len; i++){ + const boost::int16_t val = uhd::ntohx(boost::uint16_t(i & 0xffff)); + _table[i] = type(val*scalar); + } + } + + void operator()(const input_type &inputs, const output_type &outputs, const size_t nsamps){ + const item32_t *input = reinterpret_cast(inputs[0]); + std::complex *output = reinterpret_cast *>(outputs[0]); + + for (size_t i = 0; i < nsamps; i++){ + const item32_t item_be = input[i]; + output[i] = std::complex( + _table[ITEM32_BE_TO_R16(item_be)], + _table[ITEM32_BE_TO_I16(item_be)] + ); + } + } + +private: + std::vector _table; +}; + +/*********************************************************************** + * Implementation for sc16 le lookup table + **********************************************************************/ +template class convert_sc16_item32_le_1_to_fcxx_1 : public converter{ +public: + convert_sc16_item32_le_1_to_fcxx_1(void): _table(sc16_table_len){} + + void set_scalar(const double scalar){ + for (size_t i = 0; i < sc16_table_len; i++){ + const boost::int16_t val = uhd::wtohx(boost::uint16_t(i & 0xffff)); + _table[i] = type(val*scalar); + } + } + + void operator()(const input_type &inputs, const output_type &outputs, const size_t nsamps){ + const item32_t *input = reinterpret_cast(inputs[0]); + std::complex *output = reinterpret_cast *>(outputs[0]); + + for (size_t i = 0; i < nsamps; i++){ + const item32_t item_le = input[i]; + output[i] = std::complex( + _table[ITEM32_LE_TO_R16(item_le)], + _table[ITEM32_LE_TO_I16(item_le)] + ); + } + } + +private: + std::vector _table; +}; + +/*********************************************************************** + * Factory functions and registration + **********************************************************************/ +static converter::sptr make_convert_sc16_item32_be_1_to_fc32_1(void){ + return converter::sptr(new convert_sc16_item32_be_1_to_fcxx_1()); +} + +static converter::sptr make_convert_sc16_item32_be_1_to_fc64_1(void){ + return converter::sptr(new convert_sc16_item32_be_1_to_fcxx_1()); +} + +static converter::sptr make_convert_sc16_item32_le_1_to_fc32_1(void){ + return converter::sptr(new convert_sc16_item32_le_1_to_fcxx_1()); +} + +static converter::sptr make_convert_sc16_item32_le_1_to_fc64_1(void){ + return converter::sptr(new convert_sc16_item32_le_1_to_fcxx_1()); +} + +UHD_STATIC_BLOCK(register_convert_sc16_item32_1_to_fcxx_1){ + uhd::convert::id_type id; + id.num_inputs = 1; + id.num_outputs = 1; + + id.output_format = "fc32"; + id.input_format = "sc16_item32_be"; + uhd::convert::register_converter(id, &make_convert_sc16_item32_be_1_to_fc32_1, PRIORITY_TABLE); + + id.output_format = "fc64"; + id.input_format = "sc16_item32_be"; + uhd::convert::register_converter(id, &make_convert_sc16_item32_be_1_to_fc64_1, PRIORITY_TABLE); + + id.output_format = "fc32"; + id.input_format = "sc16_item32_le"; + uhd::convert::register_converter(id, &make_convert_sc16_item32_le_1_to_fc32_1, PRIORITY_TABLE); + + id.output_format = "fc64"; + id.input_format = "sc16_item32_le"; + uhd::convert::register_converter(id, &make_convert_sc16_item32_le_1_to_fc64_1, PRIORITY_TABLE); +} -- cgit v1.2.3 From aed619727e47bf2353164ac1788a6e3479b2fe16 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 15 Nov 2011 06:12:28 +0000 Subject: convert: move priorities to implementation, different for arm --- host/include/uhd/convert.hpp | 17 ++--------------- host/lib/convert/CMakeLists.txt | 6 +----- host/lib/convert/convert_common.hpp | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 20 deletions(-) (limited to 'host/lib/convert/convert_common.hpp') diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp index 6cc729819..f906ff0e9 100644 --- a/host/include/uhd/convert.hpp +++ b/host/include/uhd/convert.hpp @@ -50,21 +50,8 @@ namespace uhd{ namespace convert{ //! Conversion factory function typedef typedef boost::function function_type; - /*! - * Describe the priority of a converter function. - * A higher priority function takes precedence. - * The general case function are the lowest. - * Next comes the liborc implementations. - * Custom intrinsics implementations are highest. - */ - enum priority_type{ - PRIORITY_GENERAL = 0, - PRIORITY_LIBORC = 1, - PRIORITY_SIMD = 2, - PRIORITY_TABLE = 3, - PRIORITY_CUSTOM = 4, - PRIORITY_EMPTY = -1, - }; + //! Priority of conversion routines + typedef int priority_type; //! Identify a conversion routine in the registry struct id_type : boost::equality_comparable{ diff --git a/host/lib/convert/CMakeLists.txt b/host/lib/convert/CMakeLists.txt index 1fe92d93a..98907dc29 100644 --- a/host/lib/convert/CMakeLists.txt +++ b/host/lib/convert/CMakeLists.txt @@ -91,11 +91,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX) UNSET(CMAKE_REQUIRED_FLAGS) ENDIF(CMAKE_COMPILER_IS_GNUCXX) -IF(HAVE_ARM_NEON_H AND ENABLE_ORC) - #prefer orc support, its faster than the current intrinsic implementations - MESSAGE(STATUS "Enabled conversion support with ORC.") -ELSEIF(HAVE_ARM_NEON_H) - MESSAGE(STATUS "Enabled conversion support with NEON intrinsics.") +IF(HAVE_ARM_NEON_H) SET_SOURCE_FILES_PROPERTIES( ${CMAKE_CURRENT_SOURCE_DIR}/convert_with_neon.cpp PROPERTIES COMPILE_FLAGS "${NEON_FLAGS}" diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index f963e29ee..cc287114a 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -45,6 +45,22 @@ #define DECLARE_CONVERTER(in_form, num_in, out_form, num_out, prio) \ _DECLARE_CONVERTER(__convert_##in_form##_##num_in##_##out_form##_##num_out##_##prio, in_form, num_in, out_form, num_out, prio) +/*********************************************************************** + * Setup priorities + **********************************************************************/ +static const int PRIORITY_GENERAL = 0; +static const int PRIORITY_EMPTY = -1; + +#ifdef __ARM_NEON__ +static const int PRIORITY_LIBORC = 3; +static const int PRIORITY_SIMD = 1; //neon conversions could be implemented better, orc wins +static const int PRIORITY_TABLE = 2; //tables require large cache, so they are slower on arm +#else +static const int PRIORITY_LIBORC = 1; +static const int PRIORITY_SIMD = 2; +static const int PRIORITY_TABLE = 3; +#endif + /*********************************************************************** * Typedefs **********************************************************************/ -- cgit v1.2.3