diff options
author | Johannes Schmitz <schmitz@ti.rwth-aachen.de> | 2014-03-07 12:31:52 -0500 |
---|---|---|
committer | Tom Rondeau <tom@trondeau.com> | 2014-03-07 12:31:52 -0500 |
commit | 216799215efaaec72aa2d60f230f90f836196d51 (patch) | |
tree | c2e404764653ee3858f0932490a79c7c2ed3ccb4 | |
parent | 0f18a39b39f74eb01865e59b5e7e1896f47d8197 (diff) |
runtime: adds ability to output flowgraph in dot format (resolves issue 245).
-rw-r--r-- | gnuradio-runtime/include/gnuradio/flowgraph.h | 6 | ||||
-rw-r--r-- | gnuradio-runtime/include/gnuradio/hier_block2.h | 7 | ||||
-rw-r--r-- | gnuradio-runtime/lib/flowgraph.cc | 33 | ||||
-rw-r--r-- | gnuradio-runtime/lib/hier_block2.cc | 7 | ||||
-rw-r--r-- | gnuradio-runtime/python/gnuradio/gr/hier_block2.py | 6 | ||||
-rw-r--r-- | gnuradio-runtime/python/gnuradio/gr/top_block.py | 28 | ||||
-rw-r--r-- | gnuradio-runtime/swig/hier_block2.i | 2 | ||||
-rw-r--r-- | gnuradio-runtime/swig/top_block.i | 9 |
8 files changed, 79 insertions, 19 deletions
diff --git a/gnuradio-runtime/include/gnuradio/flowgraph.h b/gnuradio-runtime/include/gnuradio/flowgraph.h index 1271c2d60e..1c04a5f21d 100644 --- a/gnuradio-runtime/include/gnuradio/flowgraph.h +++ b/gnuradio-runtime/include/gnuradio/flowgraph.h @@ -165,7 +165,7 @@ namespace gr { // Connect two msg endpoints void connect(const msg_endpoint &src, const msg_endpoint &dst); - + // Disconnect two msg endpoints void disconnect(const msg_endpoint &src, const msg_endpoint &dst); @@ -177,7 +177,7 @@ namespace gr { // Return vector of edges const edge_vector_t &edges() const { return d_edges; } - + // Return vector of msg edges const msg_edge_vector_t &msg_edges() const { return d_msg_edges; } @@ -265,6 +265,8 @@ namespace gr { return os; } + std::string dot_graph_fg (flowgraph_sptr fg); + } /* namespace gr */ #endif /* INCLUDED_GR_RUNTIME_FLOWGRAPH_H */ diff --git a/gnuradio-runtime/include/gnuradio/hier_block2.h b/gnuradio-runtime/include/gnuradio/hier_block2.h index 3f41930d16..1bf8dddc1a 100644 --- a/gnuradio-runtime/include/gnuradio/hier_block2.h +++ b/gnuradio-runtime/include/gnuradio/hier_block2.h @@ -179,7 +179,7 @@ namespace gr { bool has_msg_port(pmt::pmt_t which_port) { return message_port_is_hier(which_port) || basic_block::has_msg_port(which_port); } - + bool message_port_is_hier(pmt::pmt_t port_id) { return message_port_is_hier_in(port_id) || message_port_is_hier_out(port_id); } @@ -235,6 +235,11 @@ namespace gr { std::vector<int> processor_affinity(); }; + /*! + * \brief Return hierarchical block's flow graph represented in dot language + */ + GR_RUNTIME_API std::string dot_graph(hier_block2_sptr hierblock2); + inline hier_block2_sptr cast_to_hier_block2_sptr(basic_block_sptr block) { return boost::dynamic_pointer_cast<hier_block2, basic_block>(block); } diff --git a/gnuradio-runtime/lib/flowgraph.cc b/gnuradio-runtime/lib/flowgraph.cc index 634236dea0..3d8dfea65a 100644 --- a/gnuradio-runtime/lib/flowgraph.cc +++ b/gnuradio-runtime/lib/flowgraph.cc @@ -149,7 +149,7 @@ namespace gr { } } - void + void flowgraph::check_valid_port(const msg_endpoint &e) { if(FLOWGRAPH_DEBUG) @@ -496,7 +496,7 @@ namespace gr { check_valid_port(src); check_valid_port(dst); for(msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { - if(p->src() == src && p->dst() == dst){ + if(p->src() == src && p->dst() == dst){ throw std::runtime_error("connect called on already connected edge!"); } } @@ -517,4 +517,33 @@ namespace gr { throw std::runtime_error("disconnect called on non-connected edge!"); } + std::string + dot_graph_fg(flowgraph_sptr fg) + { + basic_block_vector_t blocks = fg->calc_used_blocks(); + edge_vector_t edges = fg->edges(); + + std::stringstream out; + + out << "digraph flowgraph {" << std::endl; + + // Define nodes and set labels + for(basic_block_viter_t block = blocks.begin(); block != blocks.end(); ++block) { + out << (*block)->unique_id() + << " [ label=\"" << (*block)->name() << "\" ]" + << std::endl; + } + + // Define edges + for(edge_viter_t edge = edges.begin(); edge != edges.end(); ++edge) { + out << edge->src().block()->unique_id() + << " -> " + << edge->dst().block()->unique_id() << std::endl; + } + + out << "}" << std::endl; + + return out.str(); + } + } /* namespace gr */ diff --git a/gnuradio-runtime/lib/hier_block2.cc b/gnuradio-runtime/lib/hier_block2.cc index e0acba30a0..f145b9344b 100644 --- a/gnuradio-runtime/lib/hier_block2.cc +++ b/gnuradio-runtime/lib/hier_block2.cc @@ -26,6 +26,7 @@ #include <gnuradio/hier_block2.h> #include <gnuradio/io_signature.h> +#include <gnuradio/flowgraph.h> #include "hier_block2_detail.h" #include <iostream> @@ -175,4 +176,10 @@ namespace gr { return d_detail->processor_affinity(); } + std::string + dot_graph(hier_block2_sptr hierblock2) + { + return dot_graph_fg(hierblock2->flatten()); + } + } /* namespace gr */ diff --git a/gnuradio-runtime/python/gnuradio/gr/hier_block2.py b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py index a254a58c72..d7cea3a9a3 100644 --- a/gnuradio-runtime/python/gnuradio/gr/hier_block2.py +++ b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py @@ -19,7 +19,7 @@ # Boston, MA 02110-1301, USA. # -from runtime_swig import hier_block2_swig +from runtime_swig import hier_block2_swig, dot_graph import pmt # @@ -126,3 +126,7 @@ class hier_block2(object): def message_port_register_hier_out(self, portname): self.primitive_message_port_register_hier_out(pmt.intern(portname)); + def dot_graph(self): + '''Return graph representation in dot language''' + return dot_graph(self._hb) + diff --git a/gnuradio-runtime/python/gnuradio/gr/top_block.py b/gnuradio-runtime/python/gnuradio/gr/top_block.py index e4d1f4194a..58332c3421 100644 --- a/gnuradio-runtime/python/gnuradio/gr/top_block.py +++ b/gnuradio-runtime/python/gnuradio/gr/top_block.py @@ -21,7 +21,8 @@ from runtime_swig import top_block_swig, \ top_block_wait_unlocked, top_block_run_unlocked, \ - top_block_start_unlocked, top_block_stop_unlocked + top_block_start_unlocked, top_block_stop_unlocked, \ + dot_graph_tb #import gnuradio.gr.gr_threading as _threading import gr_threading as _threading @@ -92,18 +93,18 @@ class top_block(object): python subclassing. """ def __init__(self, name="top_block"): - self._tb = top_block_swig(name) + self._tb = top_block_swig(name) def __getattr__(self, name): if not hasattr(self, "_tb"): raise RuntimeError("top_block: invalid state--did you forget to call gr.top_block.__init__ in a derived class?") - return getattr(self._tb, name) + return getattr(self._tb, name) def start(self, max_noutput_items=10000000): - top_block_start_unlocked(self._tb, max_noutput_items) + top_block_start_unlocked(self._tb, max_noutput_items) def stop(self): - top_block_stop_unlocked(self._tb) + top_block_stop_unlocked(self._tb) def run(self, max_noutput_items=10000000): self.start(max_noutput_items) @@ -122,16 +123,16 @@ class top_block(object): ''' if len (points) < 1: raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),)) - else: - if len(points) == 1: - self._tb.primitive_connect(points[0].to_basic_block()) - else: - for i in range (1, len (points)): - self._connect(points[i-1], points[i]) + else: + if len(points) == 1: + self._tb.primitive_connect(points[0].to_basic_block()) + else: + for i in range (1, len (points)): + self._connect(points[i-1], points[i]) def msg_connect(self, src, srcport, dst, dstport): self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); - + def msg_disconnect(self, src, srcport, dst, dstport): self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); @@ -169,3 +170,6 @@ class top_block(object): self._tb.primitive_disconnect(src_block.to_basic_block(), src_port, dst_block.to_basic_block(), dst_port) + def dot_graph(self): + '''Return graph representation in dot language''' + return dot_graph_tb(self._tb) diff --git a/gnuradio-runtime/swig/hier_block2.i b/gnuradio-runtime/swig/hier_block2.i index 87c936544a..053f24721d 100644 --- a/gnuradio-runtime/swig/hier_block2.i +++ b/gnuradio-runtime/swig/hier_block2.i @@ -93,4 +93,6 @@ namespace gr { gr::hier_block2_sptr to_hier_block2(); // Needed for Python type coercion }; + + std::string dot_graph(hier_block2_sptr hierblock2); } diff --git a/gnuradio-runtime/swig/top_block.i b/gnuradio-runtime/swig/top_block.i index 485159972b..60c9e1a232 100644 --- a/gnuradio-runtime/swig/top_block.i +++ b/gnuradio-runtime/swig/top_block.i @@ -53,7 +53,7 @@ namespace gr { gr::top_block_sptr to_top_block(); // Needed for Python type coercion }; } - + #ifdef SWIGPYTHON %inline %{ @@ -88,6 +88,13 @@ void top_block_stop_unlocked(gr::top_block_sptr r) throw (std::runtime_error) r->stop(); ) } + +std::string +dot_graph_tb(gr::top_block_sptr r) +{ + return dot_graph(r); +} + %} #endif |