diff options
author | Lars Amsel <lars.amsel@ni.com> | 2019-07-08 15:36:52 +0200 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:32 -0800 |
commit | 2a66eb62d89c5d18c176878ce036f0109706a9e2 (patch) | |
tree | 6715fd163aa1e7bdc55a5da5e09f67d04d3a6ed6 | |
parent | 914fbdbcb297322edd8e037cb776d29be4f58c31 (diff) | |
download | uhd-2a66eb62d89c5d18c176878ce036f0109706a9e2.tar.gz uhd-2a66eb62d89c5d18c176878ce036f0109706a9e2.tar.bz2 uhd-2a66eb62d89c5d18c176878ce036f0109706a9e2.zip |
rfnoc: Introduce device-specific blocks
- Add device ID constants (e.g., E310 == 0xE310, X300 == 0xA300). These
are stored in the device FPGA, and can be used for decisions later
- Blocks can be specific to a device. For example, x300_radio_control
can only work on an X300 series device.
- Because blocks can be device-specific, all radio blocks can now share
a common Noc-ID (0x12AD1000).
- The registry and factory functions are modified to acommodate for
this.
- The motherboard access is now also factored into the same registry
macro.
-rw-r--r-- | host/include/uhd/erfnoc/core/x310_bsp.yml | 3 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/defaults.hpp | 30 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/noc_block_base.hpp | 6 | ||||
-rw-r--r-- | host/include/uhd/rfnoc/registry.hpp | 54 | ||||
-rw-r--r-- | host/include/uhd/rfnoc_graph.hpp | 2 | ||||
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/factory.hpp | 11 | ||||
-rw-r--r-- | host/lib/rfnoc/registry_factory.cpp | 97 | ||||
-rw-r--r-- | host/lib/rfnoc/rfnoc_graph.cpp | 8 | ||||
-rw-r--r-- | host/tests/rfnoc_blocks_test.cpp | 6 |
9 files changed, 108 insertions, 109 deletions
diff --git a/host/include/uhd/erfnoc/core/x310_bsp.yml b/host/include/uhd/erfnoc/core/x310_bsp.yml index 497927a08..e63d382d8 100644 --- a/host/include/uhd/erfnoc/core/x310_bsp.yml +++ b/host/include/uhd/erfnoc/core/x310_bsp.yml @@ -1,5 +1,5 @@ type: x300 -type_id: DEAD +type_id: A300 family: 7SERIES transports: - name: eth0 @@ -14,6 +14,7 @@ transports: clocks: - name: radio +- name: ce io_ports: ctrlport_radio0: diff --git a/host/include/uhd/rfnoc/defaults.hpp b/host/include/uhd/rfnoc/defaults.hpp index 3eb9e1d30..696d31f30 100644 --- a/host/include/uhd/rfnoc/defaults.hpp +++ b/host/include/uhd/rfnoc/defaults.hpp @@ -39,6 +39,36 @@ static const double DEFAULT_TICK_RATE = 1.0; // block/device-specific constraints. It will keep the frame size below 1500. static const int DEFAULT_SPP = 1996; +/*! The NoC ID is the unique identifier of the block type. All blocks of the + * same type have the same NoC ID. + */ +using noc_id_t = uint32_t; + +/*** Device Identifiers ******************************************************/ +//! Device ID Type +using device_type_t = uint16_t; +// first nibble for device family (E = E, N = 1, X = A), remaining three nibbles +// for device number +//! placeholder for unspecified device +static const device_type_t ANY_DEVICE = 0xFFFF; +//! E300 device family +static const device_type_t E300 = 0xE300; +//! E310 device +static const device_type_t E310 = 0xE310; +//! E320 +static const device_type_t E320 = 0xE320; +//! N300 device family (N300, N310) +static const device_type_t N300 = 0x1300; +//! N320 device +static const device_type_t N320 = 0x1320; +//! X300 device family (X300, X310) +static const device_type_t X300 = 0xA300; + +// block identifiers +static const noc_id_t RADIO_BLOCK = 0x12AD1000; +static const noc_id_t DUC_BLOCK = 0xD0C00000; +static const noc_id_t DDC_BLOCK = 0xDDC00000; + }} // namespace uhd::rfnoc #endif /* INCLUDED_LIBUHD_RFNOC_DEFAULTS_HPP */ diff --git a/host/include/uhd/rfnoc/noc_block_base.hpp b/host/include/uhd/rfnoc/noc_block_base.hpp index d9659862c..485b2c8a3 100644 --- a/host/include/uhd/rfnoc/noc_block_base.hpp +++ b/host/include/uhd/rfnoc/noc_block_base.hpp @@ -10,6 +10,7 @@ #include <uhd/config.hpp> #include <uhd/property_tree.hpp> #include <uhd/rfnoc/block_id.hpp> +#include <uhd/rfnoc/defaults.hpp> #include <uhd/rfnoc/node.hpp> #include <uhd/rfnoc/register_iface_holder.hpp> #include <uhd/types/device_addr.hpp> @@ -46,11 +47,6 @@ public: */ using sptr = std::shared_ptr<noc_block_base>; - /*! The NoC ID is the unique identifier of the block type. All blocks of the - * same type have the same NoC ID. - */ - using noc_id_t = uint32_t; - //! Forward declaration for the constructor arguments struct make_args_t; diff --git a/host/include/uhd/rfnoc/registry.hpp b/host/include/uhd/rfnoc/registry.hpp index 9815ce3c6..7110c3fe4 100644 --- a/host/include/uhd/rfnoc/registry.hpp +++ b/host/include/uhd/rfnoc/registry.hpp @@ -8,6 +8,7 @@ #define INCLUDED_LIBUHD_RFNOC_REGISTRY_HPP #include <uhd/config.hpp> +#include <uhd/rfnoc/defaults.hpp> #include <uhd/rfnoc/noc_block_base.hpp> #include <uhd/utils/static.hpp> #include <functional> @@ -15,8 +16,8 @@ //! This macro must be placed inside a block implementation file // after the class definition -#define UHD_RFNOC_BLOCK_REGISTER_DIRECT( \ - CLASS_NAME, NOC_ID, BLOCK_NAME, TB_CLOCK, CTRL_CLOCK) \ +#define UHD_RFNOC_BLOCK_REGISTER_FOR_DEVICE_DIRECT(CLASS_NAME, \ + NOC_ID, DEVICE_ID, BLOCK_NAME, MB_ACCESS, TB_CLOCK, CTRL_CLOCK) \ uhd::rfnoc::noc_block_base::sptr CLASS_NAME##_make( \ uhd::rfnoc::noc_block_base::make_args_ptr make_args) \ { \ @@ -24,15 +25,20 @@ } \ UHD_STATIC_BLOCK(register_rfnoc_##CLASS_NAME) \ { \ - uhd::rfnoc::registry::register_block_direct( \ - NOC_ID, BLOCK_NAME, TB_CLOCK, CTRL_CLOCK, &CLASS_NAME##_make); \ + uhd::rfnoc::registry::register_block_direct(NOC_ID, DEVICE_ID, \ + BLOCK_NAME, MB_ACCESS, \ + TB_CLOCK, CTRL_CLOCK, &CLASS_NAME##_make); \ } -#define UHD_RFNOC_BLOCK_REQUEST_MB_ACCESS(NOC_ID) \ - UHD_STATIC_BLOCK(rfnoc_block_##NOC_ID##_request_mb_access) \ - { \ - uhd::rfnoc::registry::request_mb_access(NOC_ID); \ - } +#define UHD_RFNOC_BLOCK_REGISTER_DIRECT( \ + CLASS_NAME, NOC_ID, BLOCK_NAME, TB_CLOCK, CTRL_CLOCK) \ + UHD_RFNOC_BLOCK_REGISTER_FOR_DEVICE_DIRECT(CLASS_NAME, \ + NOC_ID, ANY_DEVICE, BLOCK_NAME, false, TB_CLOCK, CTRL_CLOCK) + +#define UHD_RFNOC_BLOCK_REGISTER_DIRECT_MB_ACCESS( \ + CLASS_NAME, NOC_ID, BLOCK_NAME, TB_CLOCK, CTRL_CLOCK) \ + UHD_RFNOC_BLOCK_REGISTER_FOR_DEVICE_DIRECT(CLASS_NAME, \ + NOC_ID, ANY_DEVICE, BLOCK_NAME, true, TB_CLOCK, CTRL_CLOCK) namespace uhd { namespace rfnoc { @@ -56,13 +62,17 @@ public: * If the Noc-ID is already registered, it will print an error to stderr and * ignore the new block. * - * \param noc_id The 32-bit Noc-ID for this block (e.g. 0xDDC00000) - * \param block_name The name used for the block ID (e.g. "Radio") + * \param noc_id The 32-bit Noc-ID for this block (e.g. 0xDDC00000). + * \param device_id The 16-bit Device-ID for this block + * (ANY_DEVICE for device agnostic blocks). + * \param block_name The name used for the block ID (e.g. "Radio"). * \param factory_fn A factory function that returns a reference to the - * block + * block. */ - static void register_block_direct(noc_block_base::noc_id_t noc_id, + static void register_block_direct(noc_id_t noc_id, + device_type_t device_id, const std::string& block_name, + bool mb_access, const std::string& timebase_clock, const std::string& ctrlport_clock, factory_t factory_fn); @@ -81,24 +91,6 @@ public: static void register_block_descriptor(const std::string& block_key, factory_t factory_fn); - /*! Call this after registering a block if it requires access to the - * mb_controller - * - * Note: This is a request to the framework, and may be denied. - * - * \param noc_id Noc-ID of the block that requires access to the mb_controller - */ - static void request_mb_access(noc_block_base::noc_id_t noc_id); - - /*! Call this after registering a block if it requires access to the - * mb_controller - * - * Note: This is a request to the framework, and may be denied. - * - * \param noc_id Noc-ID of the block that requires access to the mb_controller - */ - static void request_mb_access(const std::string& block_key); - }; }} /* namespace uhd::rfnoc */ diff --git a/host/include/uhd/rfnoc_graph.hpp b/host/include/uhd/rfnoc_graph.hpp index 08d5fc095..ff7e46aa8 100644 --- a/host/include/uhd/rfnoc_graph.hpp +++ b/host/include/uhd/rfnoc_graph.hpp @@ -44,7 +44,7 @@ public: struct block_xbar_info { size_t xbar_port; - noc_block_base::noc_id_t noc_id; + noc_id_t noc_id; size_t inst_num; }; diff --git a/host/lib/include/uhdlib/rfnoc/factory.hpp b/host/lib/include/uhdlib/rfnoc/factory.hpp index be42a57e5..2bd1feb09 100644 --- a/host/lib/include/uhdlib/rfnoc/factory.hpp +++ b/host/lib/include/uhdlib/rfnoc/factory.hpp @@ -7,14 +7,16 @@ #ifndef INCLUDED_LIBUHD_RFNOC_FACTORY_HPP #define INCLUDED_LIBUHD_RFNOC_FACTORY_HPP -#include <uhd/rfnoc/registry.hpp> +#include <uhd/rfnoc/defaults.hpp> #include <uhd/rfnoc/noc_block_base.hpp> +#include <uhd/rfnoc/registry.hpp> namespace uhd { namespace rfnoc { struct block_factory_info_t { std::string block_name; + bool mb_access; std::string timebase_clk; std::string ctrlport_clk; registry::factory_t factory_fn; @@ -30,11 +32,8 @@ public: * \returns a block_factory_info_t object * \throws uhd::lookup_error if no block is found */ - static block_factory_info_t get_block_factory(noc_block_base::noc_id_t noc_id); - - /*! Check if this block has requested access to the motherboard controller - */ - static bool has_requested_mb_access(noc_block_base::noc_id_t noc_id); + static block_factory_info_t get_block_factory( + noc_id_t noc_id, device_type_t device_id); }; }} /* namespace uhd::rfnoc */ diff --git a/host/lib/rfnoc/registry_factory.cpp b/host/lib/rfnoc/registry_factory.cpp index 117b60e96..bf1bc60a5 100644 --- a/host/lib/rfnoc/registry_factory.cpp +++ b/host/lib/rfnoc/registry_factory.cpp @@ -7,8 +7,10 @@ #include <uhd/exception.hpp> #include <uhd/rfnoc/registry.hpp> #include <uhd/rfnoc/defaults.hpp> +#include <uhd/rfnoc/constants.hpp> #include <uhd/utils/static.hpp> #include <uhdlib/rfnoc/factory.hpp> +#include <boost/functional/hash.hpp> #include <unordered_map> #include <iomanip> #include <iostream> @@ -16,6 +18,10 @@ using namespace uhd::rfnoc; +/*! Pair type for device depended block definitions. */ +using block_device_pair_t = std::pair<noc_id_t, device_type_t>; + + /////////////////////////////////////////////////////////////////////////////// // There are two registries: // - The "direct" registry, which is for blocks that do not have a block @@ -24,8 +30,9 @@ using namespace uhd::rfnoc; // descriptor file // // This is the direct registry: -using block_direct_reg_t = - std::unordered_map<noc_block_base::noc_id_t, block_factory_info_t>; +using block_direct_reg_t = std::unordered_map<block_device_pair_t, + block_factory_info_t, + boost::hash<block_device_pair_t>>; UHD_SINGLETON_FCN(block_direct_reg_t, get_direct_block_registry); // // This is the descriptor registry: @@ -34,96 +41,68 @@ using block_descriptor_reg_t = UHD_SINGLETON_FCN(block_descriptor_reg_t, get_descriptor_block_registry); /////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -// These registries are for blocks that have requested motherboard access -using block_direct_mb_access_req_t = std::unordered_set<noc_block_base::noc_id_t>; -UHD_SINGLETON_FCN(block_direct_mb_access_req_t, get_direct_block_mb_access_requested); -// -// This is the descriptor registry: -using block_descriptor_mb_access_req_t = std::unordered_set<std::string>; -UHD_SINGLETON_FCN( - block_descriptor_mb_access_req_t, get_descriptor_block_mb_access_requested); -/////////////////////////////////////////////////////////////////////////////// - /****************************************************************************** * Registry functions * * Note: Don't use UHD_LOG_*, since all of this can be executed in a static * fashion. *****************************************************************************/ -void registry::register_block_direct(noc_block_base::noc_id_t noc_id, +void registry::register_block_direct(noc_id_t noc_id, + device_type_t device_id, const std::string& block_name, + bool mb_access, const std::string& timebase_clock, const std::string& ctrlport_clock, factory_t factory_fn) { - if (get_direct_block_registry().count(noc_id)) { + block_device_pair_t key{noc_id, device_id}; + if (get_direct_block_registry().count(key)) { std::cerr - << "[REGISTRY] WARNING: Attempting to overwrite previously registered RFNoC " - "block with Noc-ID 0x" - << std::hex << noc_id << std::dec << std::endl; + << "[REGISTRY] WARNING: Attempting to overwrite previously " + "registered RFNoC block with noc_id,device_id: " << std::hex + << "0x" << noc_id << ", 0x" << device_id <<std::dec << std::endl; return; } - get_direct_block_registry().emplace(noc_id, - block_factory_info_t{ - block_name, timebase_clock, ctrlport_clock, std::move(factory_fn)}); + get_direct_block_registry().emplace(key, + block_factory_info_t{block_name, + mb_access, + timebase_clock, + ctrlport_clock, + std::move(factory_fn)}); } void registry::register_block_descriptor( const std::string& block_key, factory_t factory_fn) { if (get_descriptor_block_registry().count(block_key)) { - std::cerr << "WARNING: Attempting to overwriting previously registered RFNoC " - "block with block key" - << block_key << std::endl; + std::cerr + << "[REGISTRY] WARNING: Attempting to overwrite previously " + "registered RFNoC block with block key" + << block_key << std::endl; return; } get_descriptor_block_registry().emplace(block_key, std::move(factory_fn)); } -void registry::request_mb_access(noc_block_base::noc_id_t noc_id) -{ - if (!get_direct_block_mb_access_requested().count(noc_id)) { - get_direct_block_mb_access_requested().emplace(noc_id); - } -} - -void registry::request_mb_access(const std::string& block_key) -{ - if (!get_descriptor_block_mb_access_requested().count(block_key)) { - get_descriptor_block_mb_access_requested().emplace(block_key); - } -} - /****************************************************************************** * Factory functions *****************************************************************************/ -block_factory_info_t factory::get_block_factory(noc_block_base::noc_id_t noc_id) +block_factory_info_t factory::get_block_factory(noc_id_t noc_id, device_type_t device_id) { // First, check the descriptor registry // FIXME TODO // Second, check the direct registry - if (!get_direct_block_registry().count(noc_id)) { - UHD_LOG_WARNING("RFNOC::BLOCK_FACTORY", - "Could not find block with Noc-ID " - << std::hex << std::setw(sizeof(noc_block_base::noc_id_t) * 2) << noc_id); - noc_id = DEFAULT_NOC_ID; - } - return get_direct_block_registry().at(noc_id); -} + block_device_pair_t key{noc_id, device_id}; -bool factory::has_requested_mb_access(noc_block_base::noc_id_t noc_id) -{ - if (get_direct_block_mb_access_requested().count(noc_id)) { - return true; + if (!get_direct_block_registry().count(key)) { + key = block_device_pair_t(noc_id, ANY_DEVICE); } - - // FIXME tbw: - // - Map noc_id to block key - // - Check that key's descriptor - // - If that block has requested MB access, stash the noc ID in - // get_direct_block_mb_access_requested() for faster lookups in the future - - return false; + if (!get_direct_block_registry().count(key)) { + UHD_LOG_WARNING("RFNOC::BLOCK_FACTORY", + "Could not find block with Noc-ID " << std::hex << "0x" << key.first << ", 0x" + << key.second << std::dec); + key = block_device_pair_t(DEFAULT_NOC_ID, ANY_DEVICE); + } + return get_direct_block_registry().at(key); } diff --git a/host/lib/rfnoc/rfnoc_graph.cpp b/host/lib/rfnoc/rfnoc_graph.cpp index c135247d3..bf49ca28b 100644 --- a/host/lib/rfnoc/rfnoc_graph.cpp +++ b/host/lib/rfnoc/rfnoc_graph.cpp @@ -10,6 +10,7 @@ #include <uhd/rfnoc/noc_block_make_args.hpp> #include <uhd/rfnoc/node.hpp> #include <uhd/rfnoc_graph.hpp> +#include <uhd/rfnoc/constants.hpp> #include <uhdlib/rfnoc/block_container.hpp> #include <uhdlib/rfnoc/factory.hpp> #include <uhdlib/rfnoc/graph.hpp> @@ -377,7 +378,8 @@ private: // Iterate through and register each of the blocks in this mboard for (size_t portno = 0; portno < num_blocks; ++portno) { const auto noc_id = mb_cz->get_noc_id(portno + first_block_port); - auto block_factory_info = factory::get_block_factory(noc_id); + const auto device_type = mb_cz->get_device_type(); + auto block_factory_info = factory::get_block_factory(noc_id, device_type); auto block_info = mb_cz->get_block_info(portno + first_block_port); block_id_t block_id(mb_idx, block_factory_info.block_name, @@ -410,9 +412,9 @@ private: make_args_uptr->reg_iface = block_reg_iface; make_args_uptr->tb_clk_iface = tb_clk_iface; make_args_uptr->ctrlport_clk_iface = ctrlport_clk_iface; - make_args_uptr->mb_control = (factory::has_requested_mb_access(noc_id) + make_args_uptr->mb_control = block_factory_info.mb_access ? _mb_controllers.at(mb_idx) - : nullptr); + : nullptr; const uhd::fs_path block_path(uhd::fs_path("/blocks") / block_id.to_string()); _tree->create<uint32_t>(block_path / "noc_id").set(noc_id); make_args_uptr->tree = _tree->subtree(block_path); diff --git a/host/tests/rfnoc_blocks_test.cpp b/host/tests/rfnoc_blocks_test.cpp index ca82ee305..caf50f2fa 100644 --- a/host/tests/rfnoc_blocks_test.cpp +++ b/host/tests/rfnoc_blocks_test.cpp @@ -21,7 +21,7 @@ using namespace uhd::rfnoc; namespace { -noc_block_base::make_args_ptr make_make_args(noc_block_base::noc_id_t noc_id, +noc_block_base::make_args_ptr make_make_args(noc_id_t noc_id, const std::string& block_id, const size_t n_inputs, const size_t n_outputs, @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(test_null_block) constexpr size_t num_chans = 2; constexpr uint32_t nipc = 2; constexpr uint32_t item_width = 32; - constexpr noc_block_base::noc_id_t mock_id = 0x7E570000; + constexpr noc_id_t mock_id = 0x7E570000; auto make_args = make_make_args(mock_id, "0/NullSrcSink#0", num_chans, num_chans); auto reg_iface = std::dynamic_pointer_cast<mock_reg_iface_t>(make_args->reg_iface); @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(test_ddc_block) constexpr uint32_t num_hb = 2; constexpr uint32_t max_cic = 128; constexpr size_t num_chans = 4; - constexpr noc_block_base::noc_id_t mock_noc_id = 0x7E57DDC0; + constexpr noc_id_t mock_noc_id = 0x7E57DDC0; constexpr int TEST_DECIM = 20; auto ddc_make_args = make_make_args(mock_noc_id, "0/DDC#0", num_chans, num_chans); |