1 //
2 // Copyright 2014 Ettus Research LLC
3 // Copyright 2018 Ettus Research, a National Instruments Company
4 // Copyright 2019 Ettus Research, A National Instruments Brand
5 //
6 // SPDX-License-Identifier: GPL-3.0-or-later
7 //
8 
9 #include <uhd/exception.hpp>
10 #include <uhd/property_tree.hpp>
11 #include <uhd/rfnoc/block_id.hpp>
12 #include <uhd/rfnoc/constants.hpp>
13 #include <boost/format.hpp>
14 #include <boost/lexical_cast.hpp>
15 #include <iostream>
16 #include <regex>
17 
18 using namespace uhd::rfnoc;
19 
block_id_t()20 block_id_t::block_id_t() : _device_no(0), _block_name(""), _block_ctr(0) {}
21 
block_id_t(const std::string & block_str)22 block_id_t::block_id_t(const std::string& block_str)
23     : _device_no(0), _block_name(""), _block_ctr(0)
24 {
25     if (not set(block_str)) {
26         throw uhd::value_error(
27             "block_id_t: Invalid block ID string: `" + block_str + "'");
28     }
29 }
30 
block_id_t(const size_t device_no,const std::string & block_name,const size_t block_ctr)31 block_id_t::block_id_t(
32     const size_t device_no, const std::string& block_name, const size_t block_ctr)
33     : _device_no(device_no), _block_name(block_name), _block_ctr(block_ctr)
34 {
35     if (not is_valid_blockname(block_name)) {
36         throw uhd::value_error("block_id_t: Invalid block name.");
37     }
38 }
39 
is_valid_blockname(const std::string & block_name)40 bool block_id_t::is_valid_blockname(const std::string& block_name)
41 {
42     return std::regex_match(block_name, std::regex(VALID_BLOCKNAME_REGEX));
43 }
44 
is_valid_block_id(const std::string & block_name)45 bool block_id_t::is_valid_block_id(const std::string& block_name)
46 {
47     return std::regex_match(block_name, std::regex(VALID_BLOCKID_REGEX));
48 }
49 
to_string() const50 std::string block_id_t::to_string() const
51 {
52     return str(boost::format("%d/%s") % get_device_no() % get_local());
53 }
54 
get_local() const55 std::string block_id_t::get_local() const
56 {
57     return str(boost::format("%s#%d") % get_block_name() % get_block_count());
58 }
59 
get_tree_root() const60 uhd::fs_path block_id_t::get_tree_root() const
61 {
62     return str(boost::format("/mboards/%d/xbar/%s") % get_device_no() % get_local());
63 }
64 
match(const std::string & block_str)65 bool block_id_t::match(const std::string& block_str)
66 {
67     std::cmatch matches;
68     if (not std::regex_match(
69             block_str.c_str(), matches, std::regex(VALID_BLOCKID_REGEX))) {
70         return false;
71     }
72     try {
73         return (matches[1] == "" or boost::lexical_cast<size_t>(matches[1]) == _device_no)
74                and (matches[2] == "" or matches[2] == _block_name)
75                and (matches[3] == ""
76                        or boost::lexical_cast<size_t>(matches[3]) == _block_ctr)
77                and not(matches[1] == "" and matches[2] == "" and matches[3] == "");
78     } catch (const std::bad_cast&) {
79         return false;
80     }
81     return false;
82 }
83 
set(const std::string & new_name)84 bool block_id_t::set(const std::string& new_name)
85 {
86     std::cmatch matches;
87     if (not std::regex_match(
88             new_name.c_str(), matches, std::regex(VALID_BLOCKID_REGEX))) {
89         return false;
90     }
91     if (not(matches[1] == "")) {
92         _device_no = boost::lexical_cast<size_t>(matches[1]);
93     }
94     if (not(matches[2] == "")) {
95         _block_name = matches[2];
96     }
97     if (not(matches[3] == "")) {
98         _block_ctr = boost::lexical_cast<size_t>(matches[3]);
99     }
100     return true;
101 }
102 
set(const size_t device_no,const std::string & block_name,const size_t block_ctr)103 bool block_id_t::set(
104     const size_t device_no, const std::string& block_name, const size_t block_ctr)
105 {
106     if (not set_block_name(block_name)) {
107         return false;
108     }
109     set_device_no(device_no);
110     set_block_count(block_ctr);
111     return true;
112 }
113 
set_block_name(const std::string & block_name)114 bool block_id_t::set_block_name(const std::string& block_name)
115 {
116     if (not is_valid_blockname(block_name)) {
117         return false;
118     }
119     _block_name = block_name;
120     return true;
121 }
122