[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 01/01: runtime: fix hierarchical block mess
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 01/01: runtime: fix hierarchical block message port flattening/GRC usage |
Date: |
Tue, 8 Dec 2015 19:40:41 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
jcorgan pushed a commit to branch maint
in repository gnuradio.
commit b0a992ab2049d074587c24e5d79f29b4662b4485
Author: Tim O'Shea <address@hidden>
Date: Mon Nov 30 18:05:37 2015 -0800
runtime: fix hierarchical block message port flattening/GRC usage
---
gnuradio-runtime/include/gnuradio/basic_block.h | 6 +-
gnuradio-runtime/lib/flat_flowgraph.cc | 27 ++++++-
gnuradio-runtime/lib/flat_flowgraph.h | 12 +++
gnuradio-runtime/lib/hier_block2_detail.cc | 90 ++++++++++++++--------
.../python/gnuradio/gr/qa_hier_block2.py | 51 +++++++++++-
.../blocks/qa_hier_block2_message_connections.py | 12 +--
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 2ad5078..25d9fb5 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 56123fc..4799433 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 d0b3a3a..5db38b9 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 948c05d..60910d0 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 a079f8d..005331c 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 0f8a4b8..4283f53 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 3cc16e7..003245f 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'