summaryrefslogtreecommitdiff
path: root/gnuradio-core
diff options
context:
space:
mode:
authorjcorgan2008-04-24 20:32:58 +0000
committerjcorgan2008-04-24 20:32:58 +0000
commitb92c457af141ed992671d14bf0a1b269b4946f8d (patch)
tree1e11d1b457f1c97c07a90d905b1b2921f8b394cd /gnuradio-core
parentb9ba2711addfc9057c136b520afc9e121ec19be9 (diff)
downloadgnuradio-b92c457af141ed992671d14bf0a1b269b4946f8d.tar.gz
gnuradio-b92c457af141ed992671d14bf0a1b269b4946f8d.tar.bz2
gnuradio-b92c457af141ed992671d14bf0a1b269b4946f8d.zip
Merged changeset r8231:8270 from jcorgan/merge-fix into trunk. Fixes flowgraph reconfiguration bug reported by Tim O'Shea and Mark Schneider.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@8271 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gnuradio-core')
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc116
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h5
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block_impl.cc12
3 files changed, 95 insertions, 38 deletions
diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
index 0a73d716d..aa1aa8353 100644
--- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
+++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
@@ -62,7 +62,7 @@ gr_flat_flowgraph::setup_connections()
}
gr_block_detail_sptr
-gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block, gr_block_detail_sptr old_detail)
+gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block)
{
int ninputs = calc_used_ports(block, true).size();
int noutputs = calc_used_ports(block, false).size();
@@ -71,21 +71,10 @@ gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block, gr_block_det
if (GR_FLAT_FLOWGRAPH_DEBUG)
std::cout << "Creating block detail for " << block << std::endl;
- // Re-use or allocate output buffers
for (int i = 0; i < noutputs; i++) {
- gr_buffer_sptr buffer;
-
- if (!old_detail || i >= old_detail->noutputs()) {
- if (GR_FLAT_FLOWGRAPH_DEBUG)
- std::cout << "Allocating new buffer for output " << i << std::endl;
- buffer = allocate_buffer(block, i);
- }
- else {
- if (GR_FLAT_FLOWGRAPH_DEBUG)
- std::cout << "Reusing old buffer for output " << i << std::endl;
- buffer = old_detail->output(i);
- }
-
+ gr_buffer_sptr buffer = allocate_buffer(block, i);
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "Allocated buffer for output " << block << ":" << i << std::endl;
detail->set_output(i, buffer);
}
@@ -156,35 +145,66 @@ gr_flat_flowgraph::connect_block_inputs(gr_basic_block_sptr block)
void
gr_flat_flowgraph::merge_connections(gr_flat_flowgraph_sptr old_ffg)
{
- std::map<gr_block_sptr, gr_block_detail_sptr> old_details;
-
- // Allocate or reuse output buffers
+ // Allocate block details if needed. Only new blocks that aren't pruned out
+ // by flattening will need one; existing blocks still in the new flowgraph will
+ // already have one.
for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
gr_block_sptr block = make_gr_block_sptr(*p);
-
- gr_block_detail_sptr old_detail = block->detail();
- block->set_detail(allocate_block_detail(block, old_detail));
-
- // Save old detail for use in next step
- old_details[block] = old_detail;
+
+ if (!block->detail()) {
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "merge: allocating new detail for block " << (*p) << std::endl;
+ block->set_detail(allocate_block_detail(block));
+ }
+ else
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "merge: reusing original detail for block " << (*p) << std::endl;
}
+ // Calculate the old edges that will be going away, and clear the buffer readers
+ // on the RHS.
+ for (gr_edge_viter_t old_edge = old_ffg->d_edges.begin(); old_edge != old_ffg->d_edges.end(); old_edge++) {
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "merge: testing old edge " << (*old_edge) << "...";
+
+ gr_edge_viter_t new_edge;
+ for (new_edge = d_edges.begin(); new_edge != d_edges.end(); new_edge++)
+ if (new_edge->src() == old_edge->src() &&
+ new_edge->dst() == old_edge->dst())
+ break;
+
+ if (new_edge == d_edges.end()) { // not found in new edge list
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "not in new edge list" << std::endl;
+ // zero the buffer reader on RHS of old edge
+ gr_block_sptr block(make_gr_block_sptr(old_edge->dst().block()));
+ int port = old_edge->dst().port();
+ block->detail()->set_input(port, gr_buffer_reader_sptr());
+ }
+ else {
+ if (GR_FLAT_FLOWGRAPH_DEBUG)
+ std::cout << "found in new edge list" << std::endl;
+ }
+ }
+
+ // Now connect inputs to outputs, reusing old buffer readers if they exist
for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
gr_block_sptr block = make_gr_block_sptr(*p);
if (GR_FLAT_FLOWGRAPH_DEBUG)
- std::cout << "merge: testing " << (*p) << "...";
+ std::cout << "merge: merging " << (*p) << "...";
if (old_ffg->has_block_p(*p)) {
// Block exists in old flow graph
if (GR_FLAT_FLOWGRAPH_DEBUG)
std::cout << "used in old flow graph" << std::endl;
gr_block_detail_sptr detail = block->detail();
-
+
// Iterate through the inputs and see what needs to be done
- for (int i = 0; i < detail->ninputs(); i++) {
+ int ninputs = calc_used_ports(block, true).size(); // Might be different now
+ for (int i = 0; i < ninputs; i++) {
if (GR_FLAT_FLOWGRAPH_DEBUG)
- std::cout << "Checking input " << i << "...";
+ std::cout << "Checking input " << block << ":" << i << "...";
gr_edge edge = calc_upstream_edge(*p, i);
// Fish out old buffer reader and see if it matches correct buffer from edge list
@@ -192,16 +212,13 @@ gr_flat_flowgraph::merge_connections(gr_flat_flowgraph_sptr old_ffg)
gr_block_detail_sptr src_detail = src_block->detail();
gr_buffer_sptr src_buffer = src_detail->output(edge.src().port());
gr_buffer_reader_sptr old_reader;
- gr_block_detail_sptr old_detail = old_details[block];
- if (old_detail && i < old_detail->ninputs())
- old_reader = old_detail->input(i);
+ if (i < detail->ninputs()) // Don't exceed what the original detail has
+ old_reader = detail->input(i);
// If there's a match, use it
if (old_reader && (src_buffer == old_reader->buffer())) {
if (GR_FLAT_FLOWGRAPH_DEBUG)
- std::cout << "matched" << std::endl;
- detail->set_input(i, old_reader);
-
+ std::cout << "matched, reusing" << std::endl;
}
else {
if (GR_FLAT_FLOWGRAPH_DEBUG)
@@ -218,6 +235,37 @@ gr_flat_flowgraph::merge_connections(gr_flat_flowgraph_sptr old_ffg)
std::cout << "new block" << std::endl;
connect_block_inputs(block);
}
+
+ // Now deal with the fact that the block details might have changed numbers of
+ // inputs and outputs vs. in the old flowgraph.
}
}
+void gr_flat_flowgraph::dump()
+{
+ for (gr_edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++)
+ std::cout << " edge: " << (*e) << std::endl;
+
+ for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {
+ std::cout << " block: " << (*p) << std::endl;
+ gr_block_detail_sptr detail = make_gr_block_sptr(*p)->detail();
+ std::cout << " detail @" << detail << ":" << std::endl;
+
+ int ni = detail->ninputs();
+ int no = detail->noutputs();
+ for (int i = 0; i < no; i++) {
+ gr_buffer_sptr buffer = detail->output(i);
+ std::cout << " output " << i << ": " << buffer
+ << " space=" << buffer->space_available() << std::endl;
+ }
+
+ for (int i = 0; i < ni; i++) {
+ gr_buffer_reader_sptr reader = detail->input(i);
+ std::cout << " reader " << i << ": " << reader
+ << " reading from buffer=" << reader->buffer()
+ << " avail=" << reader->items_available() << " items"
+ << std::endl;
+ }
+ }
+
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h
index 10c5d6416..184ee4514 100644
--- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h
+++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h
@@ -53,12 +53,13 @@ public:
// Merge applicable connections from existing flat flowgraph
void merge_connections(gr_flat_flowgraph_sptr sfg);
+ void dump();
+
private:
gr_flat_flowgraph();
static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE;
- gr_block_detail_sptr allocate_block_detail(gr_basic_block_sptr block,
- gr_block_detail_sptr old_detail=gr_block_detail_sptr());
+ gr_block_detail_sptr allocate_block_detail(gr_basic_block_sptr block);
gr_buffer_sptr allocate_buffer(gr_basic_block_sptr block, int port);
void connect_block_inputs(gr_basic_block_sptr block);
};
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
index aa9368e4c..51755a65d 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
+++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
@@ -215,10 +215,18 @@ gr_top_block_impl::restart()
// Create new simple flow graph
gr_flat_flowgraph_sptr new_ffg = d_owner->flatten();
new_ffg->validate(); // check consistency, sanity, etc
+
+ if (GR_TOP_BLOCK_IMPL_DEBUG) {
+ std::cout << std::endl << "*** Existing flat flowgraph @" << d_ffg << ":" << std::endl;
+ d_ffg->dump();
+ }
new_ffg->merge_connections(d_ffg); // reuse buffers, etc
- if (GR_TOP_BLOCK_IMPL_DEBUG)
- std::cout << "restart: replacing old flow graph with new" << std::endl;
+ if (GR_TOP_BLOCK_IMPL_DEBUG) {
+ std::cout << std::endl << "*** New flat flowgraph after merge @" << new_ffg << ":" << std::endl;
+ new_ffg->dump();
+ }
+
d_ffg = new_ffg;
start_threads();