aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/rfnoc_graph.hpp8
-rw-r--r--host/lib/include/uhdlib/rfnoc/graph.hpp8
-rw-r--r--host/lib/rfnoc/graph.cpp56
-rw-r--r--host/lib/rfnoc/rfnoc_graph.cpp6
-rw-r--r--host/lib/rfnoc/rfnoc_python.hpp1
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)