diff options
Diffstat (limited to 'host/lib')
| -rw-r--r-- | host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp | 9 | ||||
| -rw-r--r-- | host/lib/include/uhdlib/rfnoc/rfnoc_rx_streamer.hpp | 1 | ||||
| -rw-r--r-- | host/lib/include/uhdlib/rfnoc/rfnoc_tx_streamer.hpp | 1 | ||||
| -rw-r--r-- | host/lib/include/uhdlib/transport/rx_streamer_impl.hpp | 6 | ||||
| -rw-r--r-- | host/lib/include/uhdlib/transport/tx_streamer_impl.hpp | 6 | ||||
| -rw-r--r-- | host/lib/rfnoc/radio_control_impl.cpp | 37 | ||||
| -rw-r--r-- | host/lib/rfnoc/rfnoc_rx_streamer.cpp | 33 | ||||
| -rw-r--r-- | host/lib/rfnoc/rfnoc_tx_streamer.cpp | 32 | 
8 files changed, 115 insertions, 10 deletions
| diff --git a/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp b/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp index de83c403c..ace5b7a45 100644 --- a/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp +++ b/host/lib/include/uhdlib/rfnoc/radio_control_impl.hpp @@ -323,6 +323,13 @@ protected:          return _rate;      } +    /* +     * Returns the number of bytes to be processed in each clock cycle. +     */ +    size_t get_atomic_item_size() const +    { +        return (_samp_width / 8) * _spc; +    }      //! Properties for samp_rate (one per port)      std::vector<property_t<double>> _samp_rate_in;      //! Properties for samp_rate (one per port) @@ -380,6 +387,8 @@ private:      const uint32_t _spc;      std::vector<property_t<int>> _spp_prop; +    std::vector<property_t<size_t>> _atomic_item_size_in; +    std::vector<property_t<size_t>> _atomic_item_size_out;      //! Properties for type_in (one per port)      std::vector<property_t<io_type_t>> _type_in;      //! Properties for type_out (one per port) diff --git a/host/lib/include/uhdlib/rfnoc/rfnoc_rx_streamer.hpp b/host/lib/include/uhdlib/rfnoc/rfnoc_rx_streamer.hpp index ca569e338..2ed11182a 100644 --- a/host/lib/include/uhdlib/rfnoc/rfnoc_rx_streamer.hpp +++ b/host/lib/include/uhdlib/rfnoc/rfnoc_rx_streamer.hpp @@ -110,6 +110,7 @@ private:      std::vector<property_t<double>> _tick_rate_in;      std::vector<property_t<std::string>> _type_in;      std::vector<property_t<size_t>> _mtu_in; +    std::vector<property_t<size_t>> _atomic_item_size_in;      // Streamer unique ID      const std::string _unique_id; diff --git a/host/lib/include/uhdlib/rfnoc/rfnoc_tx_streamer.hpp b/host/lib/include/uhdlib/rfnoc/rfnoc_tx_streamer.hpp index a071d7248..76369474f 100644 --- a/host/lib/include/uhdlib/rfnoc/rfnoc_tx_streamer.hpp +++ b/host/lib/include/uhdlib/rfnoc/rfnoc_tx_streamer.hpp @@ -113,6 +113,7 @@ private:      std::vector<property_t<double>> _tick_rate_out;      std::vector<property_t<std::string>> _type_out;      std::vector<property_t<size_t>> _mtu_out; +    std::vector<property_t<size_t>> _atomic_item_size_out;      // Streamer unique ID      const std::string _unique_id; diff --git a/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp b/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp index 1b25b308b..03cd3824a 100644 --- a/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp +++ b/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp @@ -208,6 +208,12 @@ protected:          _converters[chan]->set_scalar(scale_factor);      } +    //! set maximum number of sample (per packet) +    void set_max_num_samps(const size_t value) +    { +        _spp = value; +    } +      //! Returns the maximum payload size      size_t get_mtu() const      { diff --git a/host/lib/include/uhdlib/transport/tx_streamer_impl.hpp b/host/lib/include/uhdlib/transport/tx_streamer_impl.hpp index 6b34c1c10..38f16671a 100644 --- a/host/lib/include/uhdlib/transport/tx_streamer_impl.hpp +++ b/host/lib/include/uhdlib/transport/tx_streamer_impl.hpp @@ -329,6 +329,12 @@ protected:          return _zero_copy_streamer.get_tick_rate();      } +    //! set maximum number of sample (per packet) +    void set_max_num_samps(const size_t value) +    { +        _spp = value; +    } +      //! Returns the maximum payload size      size_t get_mtu() const      { diff --git a/host/lib/rfnoc/radio_control_impl.cpp b/host/lib/rfnoc/radio_control_impl.cpp index a5c69e229..a08470d8a 100644 --- a/host/lib/rfnoc/radio_control_impl.cpp +++ b/host/lib/rfnoc/radio_control_impl.cpp @@ -9,6 +9,7 @@  #include <uhd/rfnoc/multichan_register_iface.hpp>  #include <uhd/rfnoc/register_iface.hpp>  #include <uhd/utils/log.hpp> +#include <uhd/utils/math.hpp>  #include <uhdlib/rfnoc/radio_control_impl.hpp>  #include <uhdlib/utils/compat_check.hpp>  #include <map> @@ -106,6 +107,8 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)          });      // Register spp properties and resolvers      _spp_prop.reserve(get_num_output_ports()); +    _atomic_item_size_in.reserve(get_num_input_ports()); +    _atomic_item_size_out.reserve(get_num_output_ports());      _samp_rate_in.reserve(get_num_input_ports());      _samp_rate_out.reserve(get_num_output_ports());      _type_in.reserve(get_num_input_ports()); @@ -116,6 +119,14 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)              get_max_spp(get_max_payload_size({res_source_info::OUTPUT_EDGE, chan}));          _spp_prop.push_back(              property_t<int>(PROP_KEY_SPP, default_spp, {res_source_info::USER, chan})); +        _atomic_item_size_in.push_back( +            property_t<size_t>(PROP_KEY_ATOMIC_ITEM_SIZE, +            get_atomic_item_size(), +            {res_source_info::INPUT_EDGE, chan})); +        _atomic_item_size_out.push_back( +            property_t<size_t>(PROP_KEY_ATOMIC_ITEM_SIZE, +            get_atomic_item_size(), +            {res_source_info::OUTPUT_EDGE, chan}));          _samp_rate_in.push_back(property_t<double>(              PROP_KEY_SAMP_RATE, get_tick_rate(), {res_source_info::INPUT_EDGE, chan}));          _samp_rate_out.push_back(property_t<double>( @@ -132,6 +143,8 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)              _radio_reg_iface.poke32(                  regmap::REG_RX_MAX_WORDS_PER_PKT, words_per_pkt, chan);          }); +        register_property(&_atomic_item_size_in.back()); +        register_property(&_atomic_item_size_out.back());          register_property(&_samp_rate_in.back());          register_property(&_samp_rate_out.back());          register_property(&_type_in.back()); @@ -163,6 +176,30 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)                          "spp must be greater than zero! Coercing to " << spp.get());                  }              }); +        add_property_resolver({&_atomic_item_size_in.back(), +            get_mtu_prop_ref({res_source_info::INPUT_EDGE, chan})}, +            {&_atomic_item_size_in.back()}, +            [this, chan, +                &ais_in = _atomic_item_size_in.back()]() { +                ais_in = uhd::math::lcm<size_t>(ais_in, get_atomic_item_size()); +                ais_in = std::min<size_t>(ais_in, get_mtu({res_source_info::INPUT_EDGE, chan})); +                if (ais_in.get() % get_atomic_item_size() > 0) { +                    ais_in = ais_in - (ais_in.get() % get_atomic_item_size()); +                } +                RFNOC_LOG_TRACE("Resolve atomic item size in to " << ais_in); +            }); +        add_property_resolver({&_atomic_item_size_out.back(), +            get_mtu_prop_ref({res_source_info::OUTPUT_EDGE, chan})}, +            {&_atomic_item_size_out.back()}, +            [this, chan, +                &ais_out = _atomic_item_size_out.back()]() { +                ais_out = uhd::math::lcm<size_t>(ais_out, get_atomic_item_size()); +                ais_out = std::min<size_t>(ais_out, get_mtu({res_source_info::OUTPUT_EDGE, chan})); +                if (ais_out.get() % get_atomic_item_size() > 0) { +                    ais_out = ais_out - (ais_out.get() % get_atomic_item_size()); +                } +                RFNOC_LOG_TRACE("Resolve atomic item size out to " << ais_out); +            });          // Note: The following resolver calls coerce_rate(), which is virtual.          // At run time, it will use the implementation by the child class.          add_property_resolver({&_samp_rate_in.back(), &_samp_rate_out.back()}, diff --git a/host/lib/rfnoc/rfnoc_rx_streamer.cpp b/host/lib/rfnoc/rfnoc_rx_streamer.cpp index d57b8aab2..5e6dddcbe 100644 --- a/host/lib/rfnoc/rfnoc_rx_streamer.cpp +++ b/host/lib/rfnoc/rfnoc_rx_streamer.cpp @@ -59,6 +59,7 @@ rfnoc_rx_streamer::rfnoc_rx_streamer(const size_t num_chans,      _tick_rate_in.reserve(num_chans);      _type_in.reserve(num_chans);      _mtu_in.reserve(num_chans); +    _atomic_item_size_in.reserve(num_chans);      for (size_t i = 0; i < num_chans; i++) {          _register_props(i, stream_args.otw_format); @@ -188,13 +189,16 @@ void rfnoc_rx_streamer::_register_props(const size_t chan, const std::string& ot          PROP_KEY_TYPE, otw_format, {res_source_info::INPUT_EDGE, chan}));      _mtu_in.emplace_back(          property_t<size_t>(PROP_KEY_MTU, get_mtu(), {res_source_info::INPUT_EDGE, chan})); +    _atomic_item_size_in.emplace_back( +        property_t<size_t>(PROP_KEY_ATOMIC_ITEM_SIZE, 1, {res_source_info::INPUT_EDGE, chan}));      // Give us some shorthands for the rest of this function -    property_t<double>* scaling_in   = &_scaling_in.back(); -    property_t<double>* samp_rate_in = &_samp_rate_in.back(); -    property_t<double>* tick_rate_in = &_tick_rate_in.back(); -    property_t<std::string>* type_in = &_type_in.back(); -    property_t<size_t>* mtu_in       = &_mtu_in.back(); +    property_t<double>* scaling_in          = &_scaling_in.back(); +    property_t<double>* samp_rate_in        = &_samp_rate_in.back(); +    property_t<double>* tick_rate_in        = &_tick_rate_in.back(); +    property_t<std::string>* type_in        = &_type_in.back(); +    property_t<size_t>* mtu_in              = &_mtu_in.back(); +    property_t<size_t>* atomic_item_size_in = &_atomic_item_size_in.back();      // Register them      register_property(scaling_in); @@ -202,6 +206,7 @@ void rfnoc_rx_streamer::_register_props(const size_t chan, const std::string& ot      register_property(tick_rate_in);      register_property(type_in);      register_property(mtu_in); +    register_property(atomic_item_size_in);      // Add resolvers      add_property_resolver({scaling_in}, {}, [& scaling_in = *scaling_in, chan, this]() { @@ -228,6 +233,24 @@ void rfnoc_rx_streamer::_register_props(const size_t chan, const std::string& ot                  this->set_tick_rate(tick_rate_in.get());              }          }); + +    add_property_resolver( +        {atomic_item_size_in, mtu_in}, {}, [&ais = *atomic_item_size_in, chan, this]() { +            const auto UHD_UNUSED(log_chan) = chan; +            RFNOC_LOG_TRACE("Calling resolver for `atomic_item_size'@" << chan); +            if (ais.is_valid()) { +                const auto spp = this->rx_streamer_impl::get_max_num_samps(); +                if (spp < ais.get()) { +                    throw uhd::value_error("samples per package must not be smaller than atomic item size"); +                } +                const auto misalignment = spp % ais.get(); +                RFNOC_LOG_TRACE("Check atomic item size " << ais.get() << " divides spp " << spp); +                if (misalignment > 0) { +                    RFNOC_LOG_TRACE("Reduce spp by " << misalignment << " to align with atomic item size"); +                    this->rx_streamer_impl::set_max_num_samps(spp - misalignment); +                } +            } +        });  }  void rfnoc_rx_streamer::_handle_rx_event_action( diff --git a/host/lib/rfnoc/rfnoc_tx_streamer.cpp b/host/lib/rfnoc/rfnoc_tx_streamer.cpp index 969c41ae6..411affe62 100644 --- a/host/lib/rfnoc/rfnoc_tx_streamer.cpp +++ b/host/lib/rfnoc/rfnoc_tx_streamer.cpp @@ -47,6 +47,7 @@ rfnoc_tx_streamer::rfnoc_tx_streamer(const size_t num_chans,      _tick_rate_out.reserve(num_chans);      _type_out.reserve(num_chans);      _mtu_out.reserve(num_chans); +    _atomic_item_size_out.reserve(num_chans);      for (size_t i = 0; i < num_chans; i++) {          _register_props(i, stream_args.otw_format); @@ -171,13 +172,16 @@ void rfnoc_tx_streamer::_register_props(const size_t chan, const std::string& ot          PROP_KEY_TYPE, otw_format, {res_source_info::OUTPUT_EDGE, chan}));      _mtu_out.push_back(property_t<size_t>(          PROP_KEY_MTU, get_mtu(), {res_source_info::OUTPUT_EDGE, chan})); +    _atomic_item_size_out.push_back( +        property_t<size_t>(PROP_KEY_ATOMIC_ITEM_SIZE, 1, {res_source_info::OUTPUT_EDGE, chan}));      // Give us some shorthands for the rest of this function -    property_t<double>* scaling_out   = &_scaling_out.back(); -    property_t<double>* samp_rate_out = &_samp_rate_out.back(); -    property_t<double>* tick_rate_out = &_tick_rate_out.back(); -    property_t<std::string>* type_out = &_type_out.back(); -    property_t<size_t>* mtu_out       = &_mtu_out.back(); +    property_t<double>* scaling_out          = &_scaling_out.back(); +    property_t<double>* samp_rate_out        = &_samp_rate_out.back(); +    property_t<double>* tick_rate_out        = &_tick_rate_out.back(); +    property_t<std::string>* type_out        = &_type_out.back(); +    property_t<size_t>* mtu_out              = &_mtu_out.back(); +    property_t<size_t>* atomic_item_size_out = &_atomic_item_size_out.back();      // Register them      register_property(scaling_out); @@ -185,6 +189,7 @@ void rfnoc_tx_streamer::_register_props(const size_t chan, const std::string& ot      register_property(tick_rate_out);      register_property(type_out);      register_property(mtu_out); +    register_property(atomic_item_size_out);      // Add resolvers      add_property_resolver( @@ -212,6 +217,23 @@ void rfnoc_tx_streamer::_register_props(const size_t chan, const std::string& ot                  this->set_tick_rate(tick_rate_out.get());              }          }); +    add_property_resolver( +        {atomic_item_size_out, mtu_out}, {}, [&ais = *atomic_item_size_out, chan, this]() { +            const auto UHD_UNUSED(log_chan) = chan; +            RFNOC_LOG_TRACE("Calling resolver for `atomic_item_size'@" << chan); +            if (ais.is_valid()) { +                const auto spp = this->tx_streamer_impl::get_max_num_samps(); +                if (spp < ais.get()) { +                    throw uhd::value_error("samples per package must not be smaller than atomic item size"); +                } +                const auto misalignment = spp % ais.get(); +                RFNOC_LOG_TRACE("Check atomic item size " << ais.get() << " divides spp " << spp); +                if (misalignment > 0) { +                    RFNOC_LOG_TRACE("Reduce spp by " << misalignment << " to align with atomic item size"); +                    this->tx_streamer_impl::set_max_num_samps(spp - misalignment); +                } +            } +        });  }  void rfnoc_tx_streamer::_handle_tx_event_action( | 
