aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/rfnoc/blockdef_xml_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/rfnoc/blockdef_xml_impl.cpp')
-rw-r--r--host/lib/rfnoc/blockdef_xml_impl.cpp438
1 files changed, 0 insertions, 438 deletions
diff --git a/host/lib/rfnoc/blockdef_xml_impl.cpp b/host/lib/rfnoc/blockdef_xml_impl.cpp
deleted file mode 100644
index 2326043ca..000000000
--- a/host/lib/rfnoc/blockdef_xml_impl.cpp
+++ /dev/null
@@ -1,438 +0,0 @@
-//
-// Copyright 2014-2015 Ettus Research LLC
-// Copyright 2018 Ettus Research, a National Instruments Company
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-#include <uhd/exception.hpp>
-#include <uhd/rfnoc/blockdef.hpp>
-#include <uhd/rfnoc/constants.hpp>
-#include <uhd/utils/log.hpp>
-#include <uhd/utils/paths.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/filesystem/operations.hpp>
-#include <boost/format.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/xml_parser.hpp>
-#include <cstdlib>
-
-using namespace uhd;
-using namespace uhd::rfnoc;
-namespace fs = boost::filesystem;
-namespace pt = boost::property_tree;
-
-static const fs::path XML_BLOCKS_SUBDIR("blocks");
-static const fs::path XML_COMPONENTS_SUBDIR("components");
-static const fs::path XML_EXTENSION(".xml");
-
-
-/****************************************************************************
- * port_t stuff
- ****************************************************************************/
-const device_addr_t blockdef::port_t::PORT_ARGS("name,"
- "type,"
- "vlen=0,"
- "pkt_size=0,"
- "optional=0,"
- "bursty=0,"
- "port,");
-
-blockdef::port_t::port_t()
-{
- // This guarantees that we can access these keys
- // even if they were never initialized:
- for (const std::string& key : PORT_ARGS.keys()) {
- set(key, PORT_ARGS[key]);
- }
-}
-
-bool blockdef::port_t::is_variable(const std::string& key) const
-{
- const std::string& val = get(key);
- return (val[0] == '$');
-}
-
-bool blockdef::port_t::is_keyword(const std::string& key) const
-{
- const std::string& val = get(key);
- return (val[0] == '%');
-}
-
-bool blockdef::port_t::is_valid() const
-{
- // Check we have all the keys:
- for (const std::string& key : PORT_ARGS.keys()) {
- if (not has_key(key)) {
- return false;
- }
- }
-
- // Twelve of the clock, all seems well
- return true;
-}
-
-std::string blockdef::port_t::to_string() const
-{
- std::string result;
- for (const std::string& key : PORT_ARGS.keys()) {
- if (has_key(key)) {
- result += str(boost::format("%s=%s,") % key % get(key));
- }
- }
-
- return result;
-}
-
-/****************************************************************************
- * arg_t stuff
- ****************************************************************************/
-const device_addr_t blockdef::arg_t::ARG_ARGS(
- // List all tags/args an <arg> can have here:
- "name,"
- "type,"
- "value,"
- "check,"
- "check_message,"
- "action,"
- "port=0,");
-
-const std::set<std::string> blockdef::arg_t::VALID_TYPES = {
- // List all tags/args a <type> can have here:
- "string",
- "int",
- "int_vector",
- "double"};
-
-blockdef::arg_t::arg_t()
-{
- // This guarantees that we can access these keys
- // even if they were never initialized:
- for (const std::string& key : ARG_ARGS.keys()) {
- set(key, ARG_ARGS[key]);
- }
-}
-
-bool blockdef::arg_t::is_valid() const
-{
- // 1. Check we have all the keys:
- for (const std::string& key : ARG_ARGS.keys()) {
- if (not has_key(key)) {
- return false;
- }
- }
-
- // 2. Check arg type is valid
- if (not get("type").empty() and not VALID_TYPES.count(get("type"))) {
- return false;
- }
-
- // Twelve of the clock, all seems well
- return true;
-}
-
-std::string blockdef::arg_t::to_string() const
-{
- std::string result;
- for (const std::string& key : ARG_ARGS.keys()) {
- if (has_key(key)) {
- result += str(boost::format("%s=%s,") % key % get(key));
- }
- }
-
- return result;
-}
-
-/****************************************************************************
- * blockdef_impl stuff
- ****************************************************************************/
-class blockdef_xml_impl : public blockdef
-{
-public:
- enum xml_repr_t { DESCRIBES_BLOCK, DESCRIBES_COMPONENT };
-
- //! Returns a list of base paths for the XML files.
- // It is assumed that block definitions are in a subdir with name
- // XML_BLOCKS_SUBDIR and component definitions in a subdir with name
- // XML_COMPONENTS_SUBDIR
- static std::vector<boost::filesystem::path> get_xml_paths()
- {
- std::vector<boost::filesystem::path> paths;
-
- // Path from environment variable
- if (std::getenv(XML_PATH_ENV.c_str()) != NULL) {
- paths.push_back(boost::filesystem::path(std::getenv(XML_PATH_ENV.c_str())));
- }
-
- // Finally, the default path
- const boost::filesystem::path pkg_path = uhd::get_pkg_path();
- paths.push_back(pkg_path / XML_DEFAULT_PATH);
-
- return paths;
- }
-
- //! Matches a NoC ID through substring matching
- static bool match_noc_id(const std::string& lhs_, uint64_t rhs_)
- {
- // Sanitize input: Make both values strings with all uppercase
- // characters and no leading 0x. Check inputs are valid.
- std::string lhs = boost::to_upper_copy(lhs_);
- std::string rhs = str(boost::format("%016X") % rhs_);
- if (lhs.size() > 2 and lhs[0] == '0' and lhs[1] == 'X') {
- lhs = lhs.substr(2);
- }
- UHD_ASSERT_THROW(rhs.size() == 16);
- if (lhs.size() < 4 or lhs.size() > 16) {
- throw uhd::value_error(
- str(boost::format("%s is not a valid NoC ID (must be hexadecimal, min 4 "
- "and max 16 characters)")
- % lhs_));
- }
-
- // OK, all good now. Next, we try and match the substring lhs in rhs:
- return (rhs.find(lhs) == 0);
- }
-
- //! Open the file at filename and see if it's a block definition for the given NoC ID
- static bool has_noc_id(uint64_t noc_id, const fs::path& filename)
- {
- pt::ptree propt;
- try {
- read_xml(filename.string(), propt);
- for (pt::ptree::value_type& v : propt.get_child("nocblock.ids")) {
- if (v.first == "id" and match_noc_id(v.second.data(), noc_id)) {
- return true;
- }
- }
- } catch (std::exception& e) {
- UHD_LOGGER_WARNING("RFNOC") << "has_noc_id(): caught exception " << e.what()
- << " while parsing file: " << filename.string();
- return false;
- }
- return false;
- }
-
- blockdef_xml_impl(
- const fs::path& filename, uint64_t noc_id, xml_repr_t type = DESCRIBES_BLOCK)
- : _type(type), _noc_id(noc_id)
- {
- UHD_LOGGER_DEBUG("RFNOC")
- << boost::format("Reading XML file %s for NOC ID 0x%08X")
- % filename.string().c_str() % noc_id;
- read_xml(filename.string(), _pt);
- try {
- // Check key is valid
- get_key();
- // Check name is valid
- get_name();
- // Check there's at least one port
- ports_t in = get_input_ports();
- ports_t out = get_output_ports();
- if (in.empty() and out.empty()) {
- throw uhd::runtime_error("Block does not define inputs or outputs.");
- }
- // Check args are valid
- get_args();
- // TODO any more checks?
- } catch (const std::exception& e) {
- throw uhd::runtime_error(
- str(boost::format("Invalid block definition in %s: %s")
- % filename.string() % e.what()));
- }
- }
-
- virtual ~blockdef_xml_impl() {}
-
- bool is_block() const
- {
- return _type == DESCRIBES_BLOCK;
- }
-
- bool is_component() const
- {
- return _type == DESCRIBES_COMPONENT;
- }
-
- std::string get_key() const
- {
- try {
- return _pt.get<std::string>("nocblock.key");
- } catch (const pt::ptree_bad_path&) {
- return _pt.get<std::string>("nocblock.blockname");
- }
- }
-
- std::string get_name() const
- {
- return _pt.get<std::string>("nocblock.blockname");
- }
-
- uint64_t noc_id() const
- {
- return _noc_id;
- }
-
- ports_t get_input_ports()
- {
- return _get_ports("sink");
- }
-
- ports_t get_output_ports()
- {
- return _get_ports("source");
- }
-
- ports_t _get_ports(const std::string& port_type)
- {
- std::set<size_t> port_numbers;
- size_t n_ports = 0;
- ports_t ports;
- for (pt::ptree::value_type& v : _pt.get_child("nocblock.ports")) {
- if (v.first != port_type)
- continue;
- // Now we have the correct sink or source node:
- port_t port;
- for (const std::string& key : port_t::PORT_ARGS.keys()) {
- port[key] = v.second.get(key, port_t::PORT_ARGS[key]);
- }
- // We have to be extra-careful with the port numbers:
- if (port["port"].empty()) {
- port["port"] = std::to_string(n_ports);
- }
- size_t new_port_number;
- try {
- new_port_number = boost::lexical_cast<size_t>(port["port"]);
- } catch (const boost::bad_lexical_cast& e) {
- throw uhd::value_error(
- str(boost::format("Invalid port number '%s' on port '%s'")
- % port["port"] % port["name"]));
- }
- if (port_numbers.count(new_port_number) or new_port_number > MAX_NUM_PORTS) {
- throw uhd::value_error(
- str(boost::format("Port '%s' has invalid port number %d!")
- % port["name"] % new_port_number));
- }
- port_numbers.insert(new_port_number);
- n_ports++;
- ports.push_back(port);
- }
- return ports;
- }
-
- std::vector<size_t> get_all_port_numbers()
- {
- std::set<size_t> set_ports;
- for (const port_t& port : get_input_ports()) {
- set_ports.insert(boost::lexical_cast<size_t>(port["port"]));
- }
- for (const port_t& port : get_output_ports()) {
- set_ports.insert(boost::lexical_cast<size_t>(port["port"]));
- }
- return std::vector<size_t>(set_ports.begin(), set_ports.end());
- }
-
-
- blockdef::args_t get_args()
- {
- args_t args;
- bool is_valid = true;
- pt::ptree def;
- for (pt::ptree::value_type& v : _pt.get_child("nocblock.args", def)) {
- arg_t arg;
- if (v.first != "arg")
- continue;
- for (const std::string& key : arg_t::ARG_ARGS.keys()) {
- arg[key] = v.second.get(key, arg_t::ARG_ARGS[key]);
- }
- if (arg["type"].empty()) {
- arg["type"] = "string";
- }
- if (not arg.is_valid()) {
- UHD_LOGGER_WARNING("RFNOC")
- << "Found invalid argument: " << arg.to_string();
- is_valid = false;
- }
- args.push_back(arg);
- }
- if (not is_valid) {
- throw uhd::runtime_error(
- str(boost::format("Found invalid arguments for block %s.") % get_name()));
- }
- return args;
- }
-
- registers_t get_settings_registers()
- {
- return _get_regs("setreg");
- }
-
- registers_t get_readback_registers()
- {
- return _get_regs("readback");
- }
-
- registers_t _get_regs(const std::string& reg_type)
- {
- registers_t registers;
- pt::ptree def;
- for (pt::ptree::value_type& v : _pt.get_child("nocblock.registers", def)) {
- if (v.first != reg_type)
- continue;
- registers[v.second.get<std::string>("name")] =
- boost::lexical_cast<size_t>(v.second.get<size_t>("address"));
- }
- return registers;
- }
-
-
-private:
- //! Tells us if is this for a NoC block, or a component.
- const xml_repr_t _type;
- //! The NoC-ID as reported (there may be several valid NoC IDs, this is the one used)
- const uint64_t _noc_id;
-
- //! This is a boost property tree, not the same as
- // our property tree.
- pt::ptree _pt;
-};
-
-blockdef::sptr blockdef::make_from_noc_id(uint64_t noc_id)
-{
- std::vector<fs::path> paths = blockdef_xml_impl::get_xml_paths();
- std::vector<fs::path> valid;
-
- // Check if any of the paths exist
- for (const auto& base_path : paths) {
- fs::path this_path = base_path / XML_BLOCKS_SUBDIR;
- if (fs::exists(this_path) and fs::is_directory(this_path)) {
- valid.push_back(this_path);
- }
- }
-
- if (valid.empty()) {
- throw uhd::assertion_error("Failed to find a valid XML path for RFNoC blocks.\n"
- "Try setting the enviroment variable UHD_RFNOC_DIR "
- "to the correct location");
- }
-
- // Iterate over all paths
- for (const auto& path : valid) {
- // Iterate over all .xml files
- fs::directory_iterator end_itr;
- for (fs::directory_iterator i(path); i != end_itr; ++i) {
- if (not fs::exists(*i) or fs::is_directory(*i) or fs::is_empty(*i)) {
- continue;
- }
- if (i->path().filename().extension() != XML_EXTENSION) {
- continue;
- }
- if (blockdef_xml_impl::has_noc_id(noc_id, i->path())) {
- return blockdef::sptr(new blockdef_xml_impl(i->path(), noc_id));
- }
- }
- }
-
- return blockdef::sptr();
-}
-// vim: sw=4 et: