diff options
-rw-r--r-- | host/include/uhd/rfnoc/register_iface.hpp | 63 | ||||
-rw-r--r-- | host/lib/rfnoc/ctrlport_endpoint.cpp | 15 | ||||
-rw-r--r-- | host/tests/rfnoc_mock_reg_iface.hpp | 13 |
3 files changed, 87 insertions, 4 deletions
diff --git a/host/include/uhd/rfnoc/register_iface.hpp b/host/include/uhd/rfnoc/register_iface.hpp index 729aedbe6..a89d85717 100644 --- a/host/include/uhd/rfnoc/register_iface.hpp +++ b/host/include/uhd/rfnoc/register_iface.hpp @@ -58,6 +58,33 @@ public: uhd::time_spec_t time = uhd::time_spec_t::ASAP, bool ack = false) = 0; + /*! Write two consecutive 32-bit registers implemented in the NoC block from + * one 64-bit value. + * + * Note: This is a convenience call, because all register pokes are 32-bits. + * This will concatenate two pokes in a block poke, and then return the + * combined result of the two pokes. + * + * \param addr The byte address of the lower 32-bit register to read from + * (truncated to 20 bits). + * \param data New value of the register(s). + * \param time The time at which the transaction should be executed. + * + * \throws op_failed if the transaction fails + * \throws op_timeout if no response is received + * \throws op_seqerr if a sequence error occurs + */ + void poke64(uint32_t addr, + uint64_t data, + time_spec_t time = uhd::time_spec_t::ASAP, + bool ack = false) + { + block_poke32(addr, + {uint32_t(data & 0xFFFFFFFF), uint32_t((data >> 32) & 0xFFFFFFFF)}, + time, + ack); + } + /*! Write multiple 32-bit registers implemented in the NoC block. * * This method should be called when multiple writes need to happen that are @@ -110,7 +137,6 @@ public: * * \param addr The byte address of the register to read from (truncated to 20 bits). * \param time The time at which the transaction should be executed. - * \return data New value of this register. * * \throws op_failed if the transaction fails * \throws op_timeout if no response is received @@ -118,6 +144,27 @@ public: */ virtual uint32_t peek32(uint32_t addr, time_spec_t time = uhd::time_spec_t::ASAP) = 0; + /*! Read two consecutive 32-bit registers implemented in the NoC block + * and return them as one 64-bit value. + * + * Note: This is a convenience call, because all register peeks are 32-bits. + * This will concatenate two peeks in a block peek, and then return the + * combined result of the two peeks. + * + * \param addr The byte address of the lower 32-bit register to read from + * (truncated to 20 bits). + * \param time The time at which the transaction should be executed. + * + * \throws op_failed if the transaction fails + * \throws op_timeout if no response is received + * \throws op_seqerr if a sequence error occurs + */ + uint64_t peek64(uint32_t addr, time_spec_t time = uhd::time_spec_t::ASAP) + { + const auto vals = block_peek32(addr, 2, time); + return uint64_t(vals[0]) | (uint64_t(vals[1]) << 32); + } + /*! Read multiple 32-bit consecutive registers implemented in the NoC block. * * \param first_addr The byte address of the first register to read from @@ -216,6 +263,20 @@ public: */ virtual void set_policy(const std::string& name, const uhd::device_addr_t& args) = 0; + /*! Get the endpoint ID of the software counterpart of this register interface. + * This information is useful to send async messages to the host. + * + * \return The 16-bit endpoint ID + */ + virtual uint16_t get_src_epid() const = 0; + + /*! Get the port number of the software counterpart of this register interface. + * This information is useful to send async messages to the host. + * + * \return The 10-bit port number + */ + virtual uint16_t get_port_num() const = 0; + }; // class register_iface }} /* namespace uhd::rfnoc */ diff --git a/host/lib/rfnoc/ctrlport_endpoint.cpp b/host/lib/rfnoc/ctrlport_endpoint.cpp index 93236940f..a618eaca2 100644 --- a/host/lib/rfnoc/ctrlport_endpoint.cpp +++ b/host/lib/rfnoc/ctrlport_endpoint.cpp @@ -263,7 +263,10 @@ public: UHD_LOG_ERROR( "CTRLEP", "Malformed async message request: Invalid opcode"); } else if (rx_ctrl.dst_port != _local_port) { - UHD_LOG_ERROR("CTRLEP", "Malformed async message request: Invalid port"); + UHD_LOG_ERROR("CTRLEP", + "Malformed async message request: Invalid port " + << rx_ctrl.dst_port << ", expected my local port " + << _local_port); } else if (rx_ctrl.data_vtr.empty()) { UHD_LOG_ERROR( "CTRLEP", "Malformed async message request: Invalid num_data"); @@ -291,6 +294,16 @@ public: } } + virtual uint16_t get_src_epid() const + { + return _my_epid; + } + + virtual uint16_t get_port_num() const + { + return _local_port; + } + private: //! Returns the length of the control payload in 32-bit words inline static size_t get_payload_size(const ctrl_payload& payload) diff --git a/host/tests/rfnoc_mock_reg_iface.hpp b/host/tests/rfnoc_mock_reg_iface.hpp index 3ceb95893..b43317237 100644 --- a/host/tests/rfnoc_mock_reg_iface.hpp +++ b/host/tests/rfnoc_mock_reg_iface.hpp @@ -106,6 +106,15 @@ public: "Requested to set policy for " << name << " to " << args.to_string()); } + uint16_t get_src_epid() const + { + return 0; + } + + uint16_t get_port_num() const + { + return 0; + } bool force_timeout = false; @@ -113,7 +122,8 @@ public: std::unordered_map<uint32_t, uint32_t> write_memory; protected: - virtual void _poke_cb(uint32_t /*addr*/, uint32_t /*data*/, uhd::time_spec_t /*time*/, bool /*ack*/) + virtual void _poke_cb( + uint32_t /*addr*/, uint32_t /*data*/, uhd::time_spec_t /*time*/, bool /*ack*/) { } virtual void _peek_cb(uint32_t /*addr*/, uhd::time_spec_t /*time*/) {} @@ -121,4 +131,3 @@ protected: #endif /* INCLUDED_LIBUHD_TESTS_MOCK_REG_IFACE_HPP */ - |