// // Copyright 2020 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // #include #include #include #include #include #include using namespace uhd::rfnoc; //! Space (in bytes) between register banks per channel const uint32_t REG_BANK_OFFSET = 2048; const uint32_t keep_one_in_n_block_control::REG_N_OFFSET = 0 * 8; const uint32_t keep_one_in_n_block_control::REG_MODE_OFFSET = 1 * 8; const uint32_t keep_one_in_n_block_control::REG_WIDTH_N_OFFSET = 2 * 8; // User property names const std::string PROP_KEY_N = "n"; const std::string PROP_KEY_MODE = "mode"; class keep_one_in_n_block_control_impl : public keep_one_in_n_block_control { public: RFNOC_BLOCK_CONSTRUCTOR(keep_one_in_n_block_control), _keep_one_in_n_reg_iface(*this, 0, REG_BANK_OFFSET), _max_n( (2 << regs().peek32(REG_WIDTH_N_OFFSET))-1 ) // Fixed HDL parameter { UHD_ASSERT_THROW(get_num_input_ports() == get_num_output_ports()); _register_props(); } size_t get_max_n() const override { return _max_n; } void set_n(const size_t n, const size_t chan = 0) override { set_property(PROP_KEY_N, static_cast(n), chan); } size_t get_n(const size_t chan = 0) const override { return _n.at(chan).get(); } void set_mode(const mode mode, const size_t chan = 0) override { set_property(PROP_KEY_MODE, static_cast(mode), chan); } mode get_mode(const size_t chan = 0) const override { return static_cast(_mode.at(chan).get()); } protected: //! Block-specific register interface multichan_register_iface _keep_one_in_n_reg_iface; private: void _register_props() { const size_t num_chans = get_num_input_ports(); _n.reserve(num_chans); _mode.reserve(num_chans); for (size_t chan = 0; chan < num_chans; chan++) { _n.push_back(property_t( PROP_KEY_N, 1, {res_source_info::USER, chan})); _mode.push_back(property_t( PROP_KEY_MODE, static_cast(mode::SAMPLE_MODE), {res_source_info::USER, chan})); register_property(&_n.back()); register_property(&_mode.back()); add_property_resolver({&_n.back()}, {&_n.back()}, [this, chan]() { const int max_n = this->_max_n; const int n = this->_n.at(chan).get(); if (n < 1) { throw uhd::value_error("Value of n must be positive"); } else if (n > max_n) { throw uhd::value_error("Value of n must be less than " + std::to_string(max_n)); } this->regs().poke32(REG_N_OFFSET, n); }); add_property_resolver({&_mode.back()}, {&_mode.back()}, [this, chan]() { const int mode = this->_mode.at(chan).get(); this->regs().poke32(REG_MODE_OFFSET, mode); }); } } /************************************************************************** * Attributes *************************************************************************/ //! Maximum value for N const int _max_n; //! Properties for scaling_in (one per port) std::vector> _n; //! Sample mode or Packet mode std::vector> _mode; }; UHD_RFNOC_BLOCK_REGISTER_DIRECT( keep_one_in_n_block_control, KEEP_ONE_IN_N_BLOCK, "KeepOneInN", CLOCK_KEY_GRAPH, "bus_clk")