diff options
author | Tim O'Shea <tim.oshea753@gmail.com> | 2015-11-30 18:05:37 -0800 |
---|---|---|
committer | Johnathan Corgan <johnathan@corganlabs.com> | 2015-12-08 11:12:27 -0800 |
commit | b0a992ab2049d074587c24e5d79f29b4662b4485 (patch) | |
tree | 61eb18f1a690ce64a1f8f58507171cf26760e80e | |
parent | bf6d4e2a8abf32e49a923f361162584b32e7afec (diff) |
runtime: fix hierarchical block message port flattening/GRC usage
-rw-r--r-- | gnuradio-runtime/include/gnuradio/basic_block.h | 6 | ||||
-rw-r--r-- | gnuradio-runtime/lib/flat_flowgraph.cc | 27 | ||||
-rw-r--r-- | gnuradio-runtime/lib/flat_flowgraph.h | 12 | ||||
-rw-r--r-- | gnuradio-runtime/lib/hier_block2_detail.cc | 90 | ||||
-rw-r--r-- | gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py | 51 | ||||
-rw-r--r-- | gr-blocks/python/blocks/qa_hier_block2_message_connections.py | 12 | ||||
-rw-r--r-- | grc/python/flow_graph.tmpl | 4 |
7 files changed, 152 insertions, 50 deletions
diff --git a/gnuradio-runtime/include/gnuradio/basic_block.h b/gnuradio-runtime/include/gnuradio/basic_block.h index 2ad507894b..25d9fb5a78 100644 --- a/gnuradio-runtime/include/gnuradio/basic_block.h +++ b/gnuradio-runtime/include/gnuradio/basic_block.h @@ -187,9 +187,9 @@ namespace gr { void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target); void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target); - virtual bool message_port_is_hier(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier\n"; return false; } - virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_in\n"; return false; } - virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_out\n"; return false; } + virtual bool message_port_is_hier(pmt::pmt_t port_id) { (void) port_id; return false; } + virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { (void) port_id; return false; } + virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { (void) port_id; return false; } /*! * \brief Get input message port names. diff --git a/gnuradio-runtime/lib/flat_flowgraph.cc b/gnuradio-runtime/lib/flat_flowgraph.cc index 56123fcc88..479943353b 100644 --- a/gnuradio-runtime/lib/flat_flowgraph.cc +++ b/gnuradio-runtime/lib/flat_flowgraph.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007,2013 Free Software Foundation, Inc. + * Copyright 2015 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -94,7 +94,9 @@ namespace gr { block_sptr grblock = cast_to_block_sptr(block); if(!grblock) - throw std::runtime_error("allocate_block_detail found non-gr::block"); + throw std::runtime_error( + (boost::format("allocate_block_detail found non-gr::block (%s)")% + block->alias()).str()); if(FLAT_FLOWGRAPH_DEBUG) std::cout << "Creating block detail for " << block << std::endl; @@ -415,6 +417,23 @@ namespace gr { } void + flat_flowgraph::clear_hier() + { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "Clear_hier()" << std::endl; + for(size_t i=0; i<d_msg_edges.size(); i++) { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "edge: " << d_msg_edges[i].src() << "-->" << d_msg_edges[i].dst() << std::endl; + if(d_msg_edges[i].src().is_hier() || d_msg_edges[i].dst().is_hier()){ + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "is hier" << std::endl; + d_msg_edges.erase(d_msg_edges.begin() + i); + i--; + } + } + } + + void flat_flowgraph::replace_endpoint(const msg_endpoint &e, const msg_endpoint &r, bool is_src) { size_t n_replr(0); @@ -425,7 +444,7 @@ namespace gr { if(d_msg_edges[i].src() == e) { if(FLAT_FLOWGRAPH_DEBUG) std::cout << boost::format("flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") \ - % r.block()% d_msg_edges[i].dst().block(); + % r% d_msg_edges[i].dst(); d_msg_edges.push_back( msg_edge(r, d_msg_edges[i].dst() ) ); n_replr++; } @@ -434,7 +453,7 @@ namespace gr { if(d_msg_edges[i].dst() == e) { if(FLAT_FLOWGRAPH_DEBUG) std::cout << boost::format("flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") \ - % r.block()% d_msg_edges[i].dst().block(); + % r% d_msg_edges[i].src(); d_msg_edges.push_back( msg_edge(d_msg_edges[i].src(), r ) ); n_replr++; } diff --git a/gnuradio-runtime/lib/flat_flowgraph.h b/gnuradio-runtime/lib/flat_flowgraph.h index d0b3a3ae64..5db38b9dae 100644 --- a/gnuradio-runtime/lib/flat_flowgraph.h +++ b/gnuradio-runtime/lib/flat_flowgraph.h @@ -66,10 +66,22 @@ namespace gr { */ static block_vector_t make_block_vector(basic_block_vector_t &blocks); + /*! + * replace hierarchical message connections with internal primitive ones + */ void replace_endpoint(const msg_endpoint &e, const msg_endpoint &r, bool is_src); + + /*! + * remove a specific hier message connection after replacement + */ void clear_endpoint(const msg_endpoint &e, bool is_src); /*! + * remove remainin hier message connections (non primitive) + */ + void clear_hier(); + + /*! * Enables export of perf. counters to ControlPort on all blocks in * the flowgraph. */ diff --git a/gnuradio-runtime/lib/hier_block2_detail.cc b/gnuradio-runtime/lib/hier_block2_detail.cc index 948c05d3a1..60910d0dd9 100644 --- a/gnuradio-runtime/lib/hier_block2_detail.cc +++ b/gnuradio-runtime/lib/hier_block2_detail.cc @@ -56,7 +56,7 @@ namespace gr { d_inputs = std::vector<endpoint_vector_t>(max_inputs); d_outputs = endpoint_vector_t(max_outputs); - + d_max_output_buffer = std::vector<size_t>(std::max(max_outputs,1), 0); d_min_output_buffer = std::vector<size_t>(std::max(max_outputs,1), 0); } @@ -158,37 +158,41 @@ namespace gr { if(HIER_BLOCK2_DETAIL_DEBUG) std::cout << "connecting message port..." << std::endl; - // register the subscription - // this is done later... - // src->message_port_sub(srcport, pmt::cons(dst->alias_pmt(), dstport)); - // add block uniquely to list to internal blocks if(std::find(d_blocks.begin(), d_blocks.end(), dst) == d_blocks.end()){ d_blocks.push_back(src); d_blocks.push_back(dst); } - bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; - bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); + + bool hier_in=false, hier_out=false; + if(d_owner == src.get()){ + hier_out = src->message_port_is_hier_in(srcport); + } else if (d_owner == dst.get()){ + hier_in = dst->message_port_is_hier_out(dstport);; + } else { + hier_out = src->message_port_is_hier_out(srcport); + hier_in = dst->message_port_is_hier_in(dstport); + } hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); if(src_block && src.get() != d_owner) { if(HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl; + std::cout << "msg_connect: src is hierarchical, setting parent to " << this << std::endl; src_block->d_detail->d_parent_detail = this; } if(dst_block && dst.get() != d_owner) { if(HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl; + std::cout << "msg_connect: dst is hierarchical, setting parent to " << this << std::endl; dst_block->d_detail->d_parent_detail = this; } // add edge for this message connection if(HIER_BLOCK2_DETAIL_DEBUG) - std::cout << boost::format("connect( (%s, %s, %d), (%s, %s, %d) )\n") % \ + std::cout << boost::format("msg_connect( (%s, %s, %d), (%s, %s, %d) )\n") % \ src % srcport % hier_out % dst % dstport % hier_in; d_fg->connect(msg_endpoint(src, srcport, hier_out), msg_endpoint(dst, dstport, hier_in)); @@ -202,8 +206,15 @@ namespace gr { std::cout << "disconnecting message port..." << std::endl; // remove edge for this message connection - bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport); - bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); + bool hier_in=false, hier_out=false; + if(d_owner == src.get()){ + hier_out = src->message_port_is_hier_in(srcport); + } else if (d_owner == dst.get()){ + hier_in = dst->message_port_is_hier_out(dstport);; + } else { + hier_out = src->message_port_is_hier_out(srcport); + hier_in = dst->message_port_is_hier_in(dstport); + } d_fg->disconnect(msg_endpoint(src, srcport, hier_out), msg_endpoint(dst, dstport, hier_in)); @@ -506,7 +517,8 @@ namespace gr { hier_block2_detail::flatten_aux(flat_flowgraph_sptr sfg) const { if(HIER_BLOCK2_DETAIL_DEBUG) - std::cout << " ** Flattening " << d_owner->name() << std::endl; + std::cout << " ** Flattening " << d_owner->name() << " parent: " << d_parent_detail << std::endl; + bool is_top_block = (d_parent_detail == NULL); // Add my edges to the flow graph, resolving references to actual endpoints edge_vector_t edges = d_fg->edges(); @@ -697,35 +709,32 @@ namespace gr { q->src().block() % q->src().port() % q->src().is_hier() % q->dst().block() % \ q->dst().port() % q->dst().is_hier(); - bool normal_connection = true; - // resolve existing connections to hier ports - if(q->dst().is_hier()) { + if(q->src().is_hier() && q->src().block().get() == d_owner){ + // connection into this block .. if(HIER_BLOCK2_DETAIL_DEBUG) - std::cout << boost::format(" resolve hier output (%s, %s)") % \ - q->dst().block() % q->dst().port() << std::endl; - sfg->replace_endpoint( q->dst(), q->src(), true ); - resolved_endpoints.push_back(std::pair<msg_endpoint, bool>(q->dst(),true)); - normal_connection = false; - } - - if(q->src().is_hier()) { + std::cout << "hier incoming port: " << q->src() << std::endl; + sfg->replace_endpoint(q->src(), q->dst(), false); + resolved_endpoints.push_back( std::pair<msg_endpoint,bool>( q->src(), false)); + } else + if(q->dst().is_hier() && q->dst().block().get() == d_owner){ + // connection out of this block if(HIER_BLOCK2_DETAIL_DEBUG) - std::cout << boost::format(" resolve hier input (%s, %s)") % \ - q->src().block() % q->src().port() << std::endl; - sfg->replace_endpoint( q->src(), q->dst(), false ); - resolved_endpoints.push_back(std::pair<msg_endpoint, bool>(q->src(),false)); - normal_connection = false; - } - - // propogate non hier connections through - if(normal_connection){ + std::cout << "hier outgoing port: " << q->dst() << std::endl; + sfg->replace_endpoint(q->dst(), q->src(), true); + resolved_endpoints.push_back( std::pair<msg_endpoint,bool>(q->dst(), true)); + } else { + // internal connection only + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "internal msg connection: " << q->src() << "-->" << q->dst() << std::endl; sfg->connect( q->src(), q->dst() ); } } for(std::vector<std::pair<msg_endpoint, bool> >::iterator it = resolved_endpoints.begin(); it != resolved_endpoints.end(); it++) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "sfg->clear_endpoint(" << (*it).first << ", " << (*it).second << ") " << std::endl; sfg->clear_endpoint((*it).first, (*it).second); } @@ -839,10 +848,23 @@ namespace gr { if(hier_block2 && (hier_block2.get() != d_owner)) { if(HIER_BLOCK2_DETAIL_DEBUG) std::cout << "flatten_aux: recursing into hierarchical block " - << hier_block2 << std::endl; + << hier_block2->alias() << std::endl; hier_block2->d_detail->flatten_aux(sfg); } } + + // prune any remaining hier connections + // if they were not replaced with hier internal connections while in sub-calls + // they must remain unconnected and can be deleted... + if(is_top_block){ + sfg->clear_hier(); + } + + // print all primitive connections at exit + if(HIER_BLOCK2_DETAIL_DEBUG && is_top_block){ + std::cout << "flatten_aux finished in top_block" << std::endl; + sfg->dump(); + } } void diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py b/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py index a079f8de70..005331c2ec 100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py @@ -19,9 +19,33 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr_unittest +import pmt, time +from gnuradio import gr_unittest, blocks, gr, analog from gnuradio.gr.hier_block2 import _multiple_endpoints, _optional_endpoints +class test_hblk(gr.hier_block2): + def __init__(self, io_sig=1*[gr.sizeof_gr_complex], ndebug=2): + # parent constructor + gr.hier_block2.__init__(self, + "test_hblk", + gr.io_signature(len(io_sig), len(io_sig), io_sig[0]), + gr.io_signature(0,0,0)) + + self.message_port_register_hier_in("msg_in"); + + # Internal Stream Blocks + self.vsnk = blocks.vector_sink_c() + + # Internal Msg Blocks + self.blks = []; + for i in range(0, ndebug): + self.blks.append( blocks.message_debug() ) + + # Set up internal connections + self.connect( self, self.vsnk ) + for blk in self.blks: + self.msg_connect( self, "msg_in", blk, "print" ) + class test_hier_block2(gr_unittest.TestCase): @@ -87,6 +111,31 @@ class test_hier_block2(gr_unittest.TestCase): with self.assertRaises(ValueError): self.multi(self.Block(), 5) + def test_010(self): + s, h, k = analog.sig_source_c(44100, analog.GR_COS_WAVE, 440, 1.0, 0.0), blocks.head(gr.sizeof_gr_complex, 1000), test_hblk([gr.sizeof_gr_complex], 0) + tb = gr.top_block() + tb.connect(s,h,k) + tb.run() + + def test_011(self): + s, st, h, k = analog.sig_source_c(44100, analog.GR_COS_WAVE, 440, 1.0, 0.0), blocks.message_strobe(pmt.PMT_NIL, 100), blocks.head(gr.sizeof_gr_complex, 1000), test_hblk([gr.sizeof_gr_complex], 1) + tb = gr.top_block() + tb.connect(s,h,k) + tb.msg_connect(st,"strobe",k,"msg_in") + tb.start() + time.sleep(1) + tb.stop() + tb.wait() + + def test_012(self): + s, st, h, k = analog.sig_source_c(44100, analog.GR_COS_WAVE, 440, 1.0, 0.0), blocks.message_strobe(pmt.PMT_NIL, 100), blocks.head(gr.sizeof_gr_complex, 1000), test_hblk([gr.sizeof_gr_complex], 16) + tb = gr.top_block() + tb.connect(s,h,k) + tb.msg_connect(st,"strobe",k,"msg_in") + tb.start() + time.sleep(1) + tb.stop() + tb.wait() if __name__ == '__main__': gr_unittest.run(test_hier_block2, "test_hier_block2.xml") diff --git a/gr-blocks/python/blocks/qa_hier_block2_message_connections.py b/gr-blocks/python/blocks/qa_hier_block2_message_connections.py index 0f8a4b8543..4283f537e8 100644 --- a/gr-blocks/python/blocks/qa_hier_block2_message_connections.py +++ b/gr-blocks/python/blocks/qa_hier_block2_message_connections.py @@ -53,9 +53,9 @@ class hier_block_with_message_output(gr.hier_block2): "hier_block_with_message_output", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature - self.message_port_register_hier_in("test") + self.message_port_register_hier_out("test") self.block = block_with_message_output() - self.msg_connect(self.block, "test", weakref.proxy(self), "test") + self.msg_connect(self.block, "test", self, "test") class hier_block_with_message_input(gr.hier_block2): @@ -65,9 +65,9 @@ class hier_block_with_message_input(gr.hier_block2): "hier_block_with_message_output", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature - self.message_port_register_hier_out("test") + self.message_port_register_hier_in("test") self.block = block_with_message_input() - self.msg_connect(weakref.proxy(self), "test", self.block, "test") + self.msg_connect(self, "test", self.block, "test") class hier_block_with_message_inout(gr.hier_block2): @@ -77,10 +77,10 @@ class hier_block_with_message_inout(gr.hier_block2): "hier_block_with_message_inout", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature - self.message_port_register_hier_out("test") self.message_port_register_hier_in("test") + self.message_port_register_hier_out("test") self.input = block_with_message_input() - self.msg_connect(weakref.proxy(self), "test", self.input, "test") + self.msg_connect(self, "test", self.input, "test") self.output = block_with_message_output() self.msg_connect(self.output, "test", weakref.proxy(self), "test") diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index 3cc16e7e14..003245f006 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -145,10 +145,10 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) $make_io_sig($out_sigs), ) #for $pad in $flow_graph.get_hier_block_message_io('in') - self.message_port_register_hier_out("$pad['label']") + self.message_port_register_hier_in("$pad['label']") #end for #for $pad in $flow_graph.get_hier_block_message_io('out') - self.message_port_register_hier_in("$pad['label']") + self.message_port_register_hier_out("$pad['label']") #end for #if $generate_options == 'hb_qt_gui' |