commit-gnuradio
[Top][All Lists]
Advanced

[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'
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]