1 //
2 // Copyright 2019 Ettus Research, a National Instruments Brand
3 //
4 // SPDX-License-Identifier: GPL-3.0-or-later
5 //
6 
7 #include <uhd/exception.hpp>
8 #include <uhd/rfnoc/constants.hpp>
9 #include <uhd/rfnoc/defaults.hpp>
10 #include <uhd/rfnoc/mock_block.hpp>
11 #include <uhd/rfnoc/registry.hpp>
12 #include <uhd/utils/static.hpp>
13 #include <uhdlib/rfnoc/factory.hpp>
14 #include <unordered_map>
15 #include <boost/functional/hash.hpp>
16 #include <iomanip>
17 #include <iostream>
18 #include <sstream>
19 
20 using namespace uhd::rfnoc;
21 
22 /*! Pair type for device depended block definitions. */
23 using block_device_pair_t = std::pair<noc_id_t, device_type_t>;
24 
25 
26 ///////////////////////////////////////////////////////////////////////////////
27 // There are two registries:
28 // - The "direct" registry, which is for blocks that do not have a block
29 //   descriptor file
30 // - The "descriptor" registry, which is for blocks that *do* have a block
31 //   descriptor file
32 //
33 // This is the direct registry:
34 using block_direct_reg_t = std::unordered_map<block_device_pair_t,
35     block_factory_info_t,
36     boost::hash<block_device_pair_t>>;
37 UHD_SINGLETON_FCN(block_direct_reg_t, get_direct_block_registry);
38 //
39 // This is the descriptor registry:
40 using block_descriptor_reg_t =
41     std::unordered_map<std::string /* block_key */, registry::factory_t>;
42 UHD_SINGLETON_FCN(block_descriptor_reg_t, get_descriptor_block_registry);
43 ///////////////////////////////////////////////////////////////////////////////
44 
45 /******************************************************************************
46  * Registry functions
47  *
48  * Note: Don't use UHD_LOG_*, since all of this can be executed in a static
49  * fashion.
50  *****************************************************************************/
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)51 void registry::register_block_direct(noc_id_t noc_id,
52     device_type_t device_id,
53     const std::string& block_name,
54     bool mb_access,
55     const std::string& timebase_clock,
56     const std::string& ctrlport_clock,
57     factory_t factory_fn)
58 {
59     block_device_pair_t key{noc_id, device_id};
60     if (get_direct_block_registry().count(key)) {
61         std::cerr << "[REGISTRY] WARNING: Attempting to overwrite previously "
62                      "registered RFNoC block with noc_id,device_id: "
63                   << std::hex << "0x" << noc_id << ", 0x" << device_id << std::dec
64                   << std::endl;
65         return;
66     }
67     get_direct_block_registry().emplace(key,
68         block_factory_info_t{block_name,
69             mb_access,
70             timebase_clock,
71             ctrlport_clock,
72             std::move(factory_fn)});
73 }
74 
register_block_descriptor(const std::string & block_key,factory_t factory_fn)75 void registry::register_block_descriptor(
76     const std::string& block_key, factory_t factory_fn)
77 {
78     if (get_descriptor_block_registry().count(block_key)) {
79         std::cerr << "[REGISTRY] WARNING: Attempting to overwrite previously "
80                      "registered RFNoC block with block key"
81                   << block_key << std::endl;
82         return;
83     }
84     get_descriptor_block_registry().emplace(block_key, std::move(factory_fn));
85 }
86 
87 /******************************************************************************
88  * Factory functions
89  *****************************************************************************/
get_block_factory(noc_id_t noc_id,device_type_t device_id)90 block_factory_info_t factory::get_block_factory(noc_id_t noc_id, device_type_t device_id)
91 {
92     // First, check the descriptor registry
93     // FIXME TODO
94 
95     // Second, check the direct registry
96     block_device_pair_t key{noc_id, device_id};
97 
98     if (!get_direct_block_registry().count(key)) {
99         key = block_device_pair_t(noc_id, ANY_DEVICE);
100     }
101     if (!get_direct_block_registry().count(key)) {
102         UHD_LOG_WARNING("RFNOC::BLOCK_FACTORY",
103             "Could not find block with Noc-ID " << std::hex << "0x" << key.first << ", 0x"
104                                                 << key.second << std::dec);
105         key = block_device_pair_t(DEFAULT_NOC_ID, ANY_DEVICE);
106     }
107     return get_direct_block_registry().at(key);
108 }
109