aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/rfnoc/register_iface.hpp63
-rw-r--r--host/lib/rfnoc/ctrlport_endpoint.cpp15
-rw-r--r--host/tests/rfnoc_mock_reg_iface.hpp13
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 */
-