diff options
-rw-r--r-- | host/include/uhd/rfnoc_graph.hpp | 8 | ||||
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/graph.hpp | 8 | ||||
-rw-r--r-- | host/lib/rfnoc/graph.cpp | 56 | ||||
-rw-r--r-- | host/lib/rfnoc/rfnoc_graph.cpp | 6 | ||||
-rw-r--r-- | host/lib/rfnoc/rfnoc_python.hpp | 1 |
5 files changed, 79 insertions, 0 deletions
diff --git a/host/include/uhd/rfnoc_graph.hpp b/host/include/uhd/rfnoc_graph.hpp index dcb530e5a..867f6080e 100644 --- a/host/include/uhd/rfnoc_graph.hpp +++ b/host/include/uhd/rfnoc_graph.hpp @@ -327,6 +327,14 @@ public: */ virtual void release() = 0; + /*! Create a dot representation of the current graph + * + * The graph is represented in the dot language, which can be visualized + * using the Graphviz tools. It contains all blocks and their connections. + * The connections are drawn between the ports of the blocks. + */ + virtual std::string to_dot() = 0; + /****************************************** * Streaming ******************************************/ diff --git a/host/lib/include/uhdlib/rfnoc/graph.hpp b/host/lib/include/uhdlib/rfnoc/graph.hpp index f1d1b51ff..d0f5c864f 100644 --- a/host/lib/include/uhdlib/rfnoc/graph.hpp +++ b/host/lib/include/uhdlib/rfnoc/graph.hpp @@ -88,6 +88,14 @@ public: */ std::vector<graph_edge_t> enumerate_edges(); + /*! Create a dot representation of the current graph + * + * The graph is represented in the dot language, which can be visualized + * using the Graphviz tools. It contains all blocks and their connections. + * The connections are drawn between the ports of the blocks. + */ + std::string to_dot(); + private: friend class graph_accessor_t; diff --git a/host/lib/rfnoc/graph.cpp b/host/lib/rfnoc/graph.cpp index 3525faab5..12a179f44 100644 --- a/host/lib/rfnoc/graph.cpp +++ b/host/lib/rfnoc/graph.cpp @@ -286,6 +286,62 @@ std::vector<graph_t::graph_edge_t> graph_t::enumerate_edges() return result; } +std::string graph_t::to_dot() +{ + std::string result("digraph rfnoc_graph {\n" + " rankdir=LR\n" + " node [shape=record]\n\n"); + + for (const auto& elem : _node_map) { + // add block, prepend with cluster, + // the cluster prefix ensures a box around the node + result += str(boost::format(" subgraph \"cluster_%s\" {\n" + " label=\"%s\"\n") + % elem.first->get_unique_id() % elem.first->get_unique_id()); + + // add input ports as joint blocks using "|<ref> label" notation + if (elem.first->get_num_input_ports() > 0) { + result += str( + boost::format(" \"%s_in\" [label=\"in") % elem.first->get_unique_id()); + for (size_t i = 0; i < elem.first->get_num_input_ports(); i++) { + result += str(boost::format("|<in_%d> %d") % i % i); + } + result += "\"]\n"; + } + + // add input ports as joint blocks using "|<ref> label" notation + if (elem.first->get_num_output_ports() > 0) { + result += str(boost::format(" \"%s_out\" [label=\"out") + % elem.first->get_unique_id()); + for (size_t i = 0; i < elem.first->get_num_output_ports(); i++) { + result += str(boost::format("|<out_%d> %d") % i % i); + } + result += "\"]\n"; + } + + result += " }\n"; + + // add an invisible connection between in and out ports so they + // get aligned inputs left and outputs right + if ((elem.first->get_num_input_ports() > 0) + && (elem.first->get_num_output_ports() > 0)) { + result += str(boost::format(" \"%s_in\" -> \"%s_out\" [style=invis]\n") + % elem.first->get_unique_id() % elem.first->get_unique_id()); + } + result += "\n"; + } + result += "\n"; + + // add current connections + for (const auto& elem : enumerate_edges()) { + result += + str(boost::format(" \"%s_out\":\"out_%d\" -> \"%s_in\":\"in_%d\"\n") + % elem.src_blockid % elem.src_port % elem.dst_blockid % elem.dst_port); + } + result += "}\n"; + return result; +} + /****************************************************************************** * Private methods to be called by friends *****************************************************************************/ diff --git a/host/lib/rfnoc/rfnoc_graph.cpp b/host/lib/rfnoc/rfnoc_graph.cpp index 509f98b04..34f08250a 100644 --- a/host/lib/rfnoc/rfnoc_graph.cpp +++ b/host/lib/rfnoc/rfnoc_graph.cpp @@ -578,6 +578,7 @@ public: void commit() override { _graph->commit(); + UHD_LOG_TRACE(LOG_ID, "new graph committed" << std::endl << _graph->to_dot()); } void release() override @@ -585,6 +586,11 @@ public: _graph->release(); } + std::string to_dot() override + { + return _graph->to_dot(); + } + private: /************************************************************************** * Device Setup diff --git a/host/lib/rfnoc/rfnoc_python.hpp b/host/lib/rfnoc/rfnoc_python.hpp index b53de268c..53c61d3f2 100644 --- a/host/lib/rfnoc/rfnoc_python.hpp +++ b/host/lib/rfnoc/rfnoc_python.hpp @@ -223,6 +223,7 @@ void export_rfnoc(py::module& m) .def("enumerate_active_connections", &rfnoc_graph::enumerate_active_connections) .def("commit", &rfnoc_graph::commit) .def("release", &rfnoc_graph::release) + .def("to_dot", &rfnoc_graph::to_dot) .def("create_rx_streamer", &rfnoc_graph::create_rx_streamer) .def("create_tx_streamer", &rfnoc_graph::create_tx_streamer) .def("get_num_mboards", &rfnoc_graph::get_num_mboards) |