diff options
author | Martin Braun <martin.braun@ettus.com> | 2018-01-22 09:47:21 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2018-02-19 14:51:47 -0800 |
commit | eff796f64b1e05036b7eca2185f53528a0de870b (patch) | |
tree | a470a6d1f3f3d2bb8a422b8b7f3815f2924c766c | |
parent | 1adae2b432d1b66d7b9133a67fedce8af0b6b560 (diff) | |
download | uhd-eff796f64b1e05036b7eca2185f53528a0de870b.tar.gz uhd-eff796f64b1e05036b7eca2185f53528a0de870b.tar.bz2 uhd-eff796f64b1e05036b7eca2185f53528a0de870b.zip |
rfnoc: Factored out FPGA compat check
- Applied changes to DUC and DDC blocks
- Fixed minor formatting
-rw-r--r-- | host/lib/include/uhdlib/utils/compat_check.hpp | 30 | ||||
-rw-r--r-- | host/lib/rfnoc/ddc_block_ctrl_impl.cpp | 88 | ||||
-rw-r--r-- | host/lib/rfnoc/duc_block_ctrl_impl.cpp | 90 | ||||
-rw-r--r-- | host/lib/utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/lib/utils/compat_check.cpp | 114 |
5 files changed, 234 insertions, 89 deletions
diff --git a/host/lib/include/uhdlib/utils/compat_check.hpp b/host/lib/include/uhdlib/utils/compat_check.hpp new file mode 100644 index 000000000..acdf97340 --- /dev/null +++ b/host/lib/include/uhdlib/utils/compat_check.hpp @@ -0,0 +1,30 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0 +// + +#ifndef INCLUDED_UHDLIB_UTILS_COMPATCHECK_HPP +#define INCLUDED_UHDLIB_UTILS_COMPATCHECK_HPP + +#include <cstddef> +#include <string> + +namespace uhd { + + /*! Checks for FPGA compatibility, and throws an exception on mismatch. + * + * \throws uhd::runtime_error on mismatch. + */ + void assert_fpga_compat( + const size_t uhd_major, + const size_t uhd_minor, + const uint64_t fpga_compat, + const std::string& fpga_component, + const std::string& log_component, + const bool fail_on_minor_behind=false + ); + +} /* namespace uhd */ + +#endif /* INCLUDED_UHDLIB_UTILS_COMPATCHECK_HPP */ diff --git a/host/lib/rfnoc/ddc_block_ctrl_impl.cpp b/host/lib/rfnoc/ddc_block_ctrl_impl.cpp index 62a5ce896..9c7764045 100644 --- a/host/lib/rfnoc/ddc_block_ctrl_impl.cpp +++ b/host/lib/rfnoc/ddc_block_ctrl_impl.cpp @@ -9,6 +9,8 @@ #include <uhd/utils/log.hpp> #include <uhd/convert.hpp> #include <uhd/types/ranges.hpp> +#include <uhdlib/utils/narrow.hpp> +#include <uhdlib/utils/compat_check.hpp> #include <boost/math/special_functions/round.hpp> #include <cmath> @@ -24,10 +26,23 @@ class ddc_block_ctrl_impl : public ddc_block_ctrl public: UHD_RFNOC_BLOCK_CONSTRUCTOR(ddc_block_ctrl) + , _fpga_compat(user_reg_read64(RB_REG_COMPAT_NUM)) + , _num_halfbands(uhd::narrow_cast<size_t>( + user_reg_read64(RB_REG_NUM_HALFBANDS))) + , _cic_max_decim(uhd::narrow_cast<size_t>( + user_reg_read64(RB_REG_CIC_MAX_DECIM))) { - check_compat_num(); - _num_halfbands = (size_t) user_reg_read64(RB_REG_NUM_HALFBANDS); - _cic_max_decim = (size_t) user_reg_read64(RB_REG_CIC_MAX_DECIM); + UHD_LOG_DEBUG(unique_id(), + "Loading DDC with " << get_num_halfbands() << " halfbands and " + "max CIC decimation " << get_cic_max_decim() + ); + uhd::assert_fpga_compat( + MAJOR_COMP, MINOR_COMP, + _fpga_compat, + "DDC", "DDC", + false /* Let it slide if minors mismatch */ + ); + // Argument/prop tree hooks for (size_t chan = 0; chan < get_input_ports().size(); chan++) { double default_freq = get_arg<double>("freq", chan); @@ -186,14 +201,15 @@ public: } private: + static constexpr size_t MAJOR_COMP = 1; + static constexpr size_t MINOR_COMP = 0; + static constexpr size_t RB_REG_COMPAT_NUM = 0; + static constexpr size_t RB_REG_NUM_HALFBANDS = 1; + static constexpr size_t RB_REG_CIC_MAX_DECIM = 2; - size_t _num_halfbands; - size_t _cic_max_decim; - static const size_t MAJOR_COMP = 1; - static const size_t MINOR_COMP = 0; - static const size_t RB_REG_COMPAT_NUM = 0; - static const size_t RB_REG_NUM_HALFBANDS = 1; - static const size_t RB_REG_CIC_MAX_DECIM = 2; + const uint64_t _fpga_compat; + const size_t _num_halfbands; + const size_t _cic_max_decim; //! Set the CORDIC frequency shift the signal to \p requested_freq double set_freq(const double requested_freq, const size_t chan) @@ -224,7 +240,7 @@ private: for (int hb = _num_halfbands; hb >= 0; hb--) { const size_t decim_offset = _cic_max_decim<<(hb-1); for(size_t decim = _cic_max_decim; decim > 0; decim--) { - const size_t hb_cic_decim = decim*(1<<hb); + const size_t hb_cic_decim = decim*(1<<hb); if(hb == 0 || hb_cic_decim > decim_offset) { range.push_back(uhd::range_t(input_rate/hb_cic_decim)); } @@ -315,39 +331,23 @@ private: sr_write("SCALE_IQ", actual_scalar, chan); } - //Get cached value of _num_halfbands - size_t get_num_halfbands() const - { - return _num_halfbands; - } - - //Get cached value of _cic_max_decim readback - size_t get_cic_max_decim() const - { - return _cic_max_decim; - } - - //Check compatibility num, if not current, throw error. - //MAJOR COMPATIBILITY, top 32 bits = 0x1 - //MINOR COMPATIBILITY, lower 32 bits = 0x0 - void check_compat_num() - { - uint64_t compat_num = user_reg_read64(RB_REG_COMPAT_NUM); - uint32_t compat_num_major = compat_num>>32; - uint32_t compat_num_minor = compat_num&0xFFFFFFFF; - if (compat_num_major > MAJOR_COMP) { - throw uhd::runtime_error(str(boost::format( - "DDC RFNoC block is too new for this software. Please upgrade to a driver that supports hardware revision %d.") - % compat_num_major)); - } else if (compat_num_major < MAJOR_COMP) { - throw uhd::runtime_error(str(boost::format( - "DDC software is too new for this hardware. Please downgrade to a driver that supports hardware revision %d.") - % compat_num_major)); - } - if (compat_num_minor != MINOR_COMP) { - UHD_LOGGER_WARNING("DDC") << "DDC hardware compatability does not match software, this may have adverse affects on the block's behavior."; - } - } + //! Get cached value of FPGA compat number + uint64_t get_fpga_compat() const + { + return _fpga_compat; + } + + //! Get cached value of _num_halfbands + size_t get_num_halfbands() const + { + return _num_halfbands; + } + + //! Get cached value of _cic_max_decim readback + size_t get_cic_max_decim() const + { + return _cic_max_decim; + } }; UHD_RFNOC_BLOCK_REGISTER(ddc_block_ctrl, "DDC"); diff --git a/host/lib/rfnoc/duc_block_ctrl_impl.cpp b/host/lib/rfnoc/duc_block_ctrl_impl.cpp index 3a779566b..0e1521d9f 100644 --- a/host/lib/rfnoc/duc_block_ctrl_impl.cpp +++ b/host/lib/rfnoc/duc_block_ctrl_impl.cpp @@ -9,6 +9,8 @@ #include <uhd/utils/log.hpp> #include <uhd/convert.hpp> #include <uhd/types/ranges.hpp> +#include <uhdlib/utils/narrow.hpp> +#include <uhdlib/utils/compat_check.hpp> #include <boost/math/special_functions/round.hpp> #include <cmath> @@ -35,10 +37,23 @@ class duc_block_ctrl_impl : public duc_block_ctrl public: UHD_RFNOC_BLOCK_CONSTRUCTOR(duc_block_ctrl) + , _fpga_compat(user_reg_read64(RB_REG_COMPAT_NUM)) + , _num_halfbands(uhd::narrow_cast<size_t>( + user_reg_read64(RB_REG_NUM_HALFBANDS))) + , _cic_max_interp(uhd::narrow_cast<size_t>( + user_reg_read64(RB_REG_CIC_MAX_INTERP))) { - check_compat_num(); - _num_halfbands = (size_t) user_reg_read64(RB_REG_NUM_HALFBANDS); - _cic_max_interp = (size_t) user_reg_read64(RB_REG_CIC_MAX_INTERP); + UHD_LOG_DEBUG(unique_id(), + "Loading DUC with " << get_num_halfbands() << " halfbands and " + "max CIC interpolation " << get_cic_max_interp() + ); + uhd::assert_fpga_compat( + MAJOR_COMP, MINOR_COMP, + _fpga_compat, + "DUC", "DUC", + false /* Let it slide if minors mismatch */ + ); + // Argument/prop tree hooks for (size_t chan = 0; chan < get_input_ports().size(); chan++) { double default_freq = get_arg<double>("freq", chan); @@ -149,13 +164,15 @@ public: private: - size_t _num_halfbands; - size_t _cic_max_interp; - static const size_t MAJOR_COMP = 1; - static const size_t MINOR_COMP = 0; - static const size_t RB_REG_COMPAT_NUM = 0; - static const size_t RB_REG_NUM_HALFBANDS = 1; - static const size_t RB_REG_CIC_MAX_INTERP = 2; + static constexpr size_t MAJOR_COMP = 1; + static constexpr size_t MINOR_COMP = 0; + static constexpr size_t RB_REG_COMPAT_NUM = 0; + static constexpr size_t RB_REG_NUM_HALFBANDS = 1; + static constexpr size_t RB_REG_CIC_MAX_INTERP = 2; + + const uint64_t _fpga_compat; + const size_t _num_halfbands; + const size_t _cic_max_interp; //! Set the CORDIC frequency shift the signal to \p requested_freq double set_freq(const double requested_freq, const size_t chan) @@ -187,7 +204,7 @@ private: for (int hb = _num_halfbands; hb >= 0; hb--) { const size_t interp_offset = _cic_max_interp<<(hb-1); for(size_t interp = _cic_max_interp; interp > 0; interp--) { - const size_t hb_cic_interp = interp*(1<<hb); + const size_t hb_cic_interp = interp*(1<<hb); if(hb == 0 || hb_cic_interp > interp_offset) { range.push_back(uhd::range_t(output_rate/hb_cic_interp)); } @@ -263,40 +280,23 @@ private: sr_write("SCALE_IQ", actual_scalar, chan); } - //Get cached value of _num_halfbands - size_t get_num_halfbands() const - { - return (size_t) _num_halfbands; - } - - //Get cached value of _cic_max_decim readback - size_t get_cic_max_decim() const - { - return (size_t) _cic_max_interp; - } - - //Check compatibility num, if not current, throw error. - //MAJOR COMPATIBILITY, top 32 bits = 0x1 - //MINOR COMPATIBILITY, lower 32 bits = 0x0 - void check_compat_num() - { - uint64_t compat_num = user_reg_read64(RB_REG_COMPAT_NUM); - uint32_t compat_num_major = compat_num>>32; - uint32_t compat_num_minor = compat_num&0xFFFFFFFF; - if ( compat_num_major > MAJOR_COMP) { - throw uhd::runtime_error(str(boost::format( - "DUC RFNoC block is too new for this software. Please upgrade to a driver that supports hardware revision %d.") - % compat_num_major)); - } else if ( compat_num_major < MAJOR_COMP) { - throw uhd::runtime_error(str(boost::format( - "DUC software is too new for this hardware. Please downgrade to a driver that supports hardware revision %d.") - % compat_num_major)); - } - if (compat_num_minor != MINOR_COMP) { - UHD_LOGGER_WARNING("DDC") << "DDC hardware compatability does not match software, this may have adverse affects on the block's behavior."; - } - } + //! Get cached value of FPGA compat number + uint64_t get_fpga_compat() const + { + return _fpga_compat; + } + + //Get cached value of _num_halfbands + size_t get_num_halfbands() const + { + return _num_halfbands; + } + + //Get cached value of _cic_max_decim readback + size_t get_cic_max_interp() const + { + return _cic_max_interp; + } }; UHD_RFNOC_BLOCK_REGISTER(duc_block_ctrl, "DUC"); - diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index afaf99274..c7de9fbf8 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -160,6 +160,7 @@ SET_SOURCE_FILES_PROPERTIES( LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/csv.cpp ${CMAKE_CURRENT_SOURCE_DIR}/config_parser.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/compat_check.cpp ${CMAKE_CURRENT_SOURCE_DIR}/eeprom_utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gain_group.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ihex.cpp diff --git a/host/lib/utils/compat_check.cpp b/host/lib/utils/compat_check.cpp new file mode 100644 index 000000000..aebf6e6bf --- /dev/null +++ b/host/lib/utils/compat_check.cpp @@ -0,0 +1,114 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0 +// + +#include <uhd/exception.hpp> +#include <uhd/utils/log.hpp> +#include <uhdlib/utils/compat_check.hpp> +#include <boost/format.hpp> + +void uhd::assert_fpga_compat( + const size_t uhd_major, + const size_t uhd_minor, + const uint64_t fpga_compat, + const std::string& fpga_component, + const std::string& log_component, + const bool fail_on_minor_behind +) { + const size_t fpga_major = fpga_compat >> 32; + const size_t fpga_minor = fpga_compat & 0xFFFFFFFF; + + if (!log_component.empty()) { + UHD_LOGGER_DEBUG(log_component) + << "Checking compat number for FPGA component `" << fpga_component + << "': Expecting " << uhd_major << "." << uhd_minor << ", actual: " + << fpga_major << "." << fpga_minor << "." + ; + } + + if (uhd_major > fpga_major) { + if (!log_component.empty()) { + UHD_LOGGER_ERROR(log_component) + << "Major compat number mismatch for " << fpga_component << ":" + " Expecting " << uhd_major << ", got " << fpga_major << "." + ; + } + throw uhd::runtime_error(str( + boost::format("FPGA component `%s' is revision %d and UHD supports" + " revision %d. Please either upgrade the FPGA" + " image (recommended) or downgrade UHD.") + % fpga_component + % fpga_major + % uhd_major + )); + } + if (uhd_major < fpga_major) { + if (!log_component.empty()) { + UHD_LOGGER_ERROR(log_component) + << "Major compat number mismatch for " << fpga_component << ":" + " Expecting " << uhd_major << ", got " << fpga_major << "." + ; + } + throw uhd::runtime_error(str( + boost::format("FPGA component `%s' is revision %d and UHD supports" + " revision %d. Please either upgrade UHD " + " (recommended) or downgrade the FPGA image.") + % fpga_component + % fpga_major + % uhd_major + )); + + } + if (uhd_minor > fpga_minor) { + if (fail_on_minor_behind) { + if (!log_component.empty()) { + UHD_LOGGER_ERROR(log_component) << str( + boost::format("Minor compat number mismatch for `%s':" + " Expecting %d.%d, got %d.%d.") + % fpga_component + % uhd_major + % uhd_minor + % fpga_major + % fpga_minor + ); + } + throw uhd::runtime_error(str( + boost::format("FPGA component `%s' is revision %d.%d and UHD supports" + " revision %d.%d. Please either upgrade UHD " + " (recommended) or downgrade the FPGA image.") + % fpga_component + % fpga_major + % fpga_minor + % uhd_major + % uhd_minor + )); + } else { + if (!log_component.empty()) { + UHD_LOGGER_WARNING(log_component) << str( + boost::format("Non-critical minor compat number mismatch " + "for `%s': Expecting %d.%d, got %d.%d.") + % fpga_component + % uhd_major + % uhd_minor + % fpga_major + % fpga_minor + ); + } + } + } else if (uhd_minor < fpga_minor) { + if (!log_component.empty()) { + UHD_LOGGER_WARNING(log_component) << str( + boost::format("Non-critical minor compat number mismatch " + "for `%s': Expecting %d.%d, got %d.%d.") + % fpga_component + % uhd_major + % uhd_minor + % fpga_major + % fpga_minor + ); + } + } + // We got here? Then all is good. +} |