[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r4914 - in gnuradio/branches/developers/jcorgan/hier2/
From: |
jcorgan |
Subject: |
[Commit-gnuradio] r4914 - in gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src: lib/runtime python/gnuradio/gr |
Date: |
Sat, 7 Apr 2007 08:22:29 -0600 (MDT) |
Author: jcorgan
Date: 2007-04-07 08:22:29 -0600 (Sat, 07 Apr 2007)
New Revision: 4914
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.h
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.i
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.cc
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.h
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.i
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py
Log:
Merged -r4703:4704 from jcorgan/hier into jcorgan/hier2
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -61,3 +61,10 @@
{
d_detail->connect(src_name, src_port, dst_name, dst_port);
}
+
+void
+gr_hier_block2::disconnect(const std::string &src_name, int src_port,
+ const std::string &dst_name, int dst_port)
+{
+ d_detail->disconnect(src_name, src_port, dst_name, dst_port);
+}
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.h
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.h
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.h
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -62,6 +62,8 @@
void define_component(const std::string &name, gr_basic_block_sptr
basic_block);
void connect(const std::string &src_name, int src_port,
const std::string &dst_name, int dst_port);
+ void disconnect(const std::string &src_name, int src_port,
+ const std::string &dst_name, int dst_port);
};
#endif /* INCLUDED_GR_HIER_BLOCK2_H */
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.i
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.i
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2.i
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005 Free Software Foundation, Inc.
+ * Copyright 2005,2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -49,4 +49,7 @@
void connect(const std::string &src_name, int src_port,
const std::string &dst_name, int dst_port)
throw (std::invalid_argument);
+ void disconnect(const std::string &src_name, int src_port,
+ const std::string &dst_name, int dst_port)
+ throw (std::invalid_argument);
};
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,5 +1,5 @@
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -29,199 +29,248 @@
#include <stdexcept>
#include <iostream>
+#define GR_HIER_BLOCK2_DETAIL_DEBUG 1
+
gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) :
-d_owner(owner)
+ d_owner(owner)
{
}
gr_hier_block2_detail::~gr_hier_block2_detail()
{
- d_owner = 0; // Don't use delete, we didn't allocate
+ d_owner = 0; // Don't use delete, we didn't allocate
}
gr_basic_block_sptr
gr_hier_block2_detail::lookup_block(const std::string &name)
{
- gr_hier_component_miter_t p = d_components.find(name);
- if (p != d_components.end())
- return p->second;
- else
- return gr_basic_block_sptr();
+ gr_hier_component_miter_t p = d_components.find(name);
+ if (p != d_components.end())
+ return p->second;
+ else
+ return gr_basic_block_sptr();
}
void
gr_hier_block2_detail::define_component(const std::string &name,
gr_basic_block_sptr block)
{
- if (!block)
- throw std::invalid_argument("null block passed");
+ if (!block)
+ throw std::invalid_argument("null block passed");
- if (name == "self")
- throw std::invalid_argument("name is reserved");
+ if (name == "self" || name == "NC")
+ throw std::invalid_argument("name is reserved");
- // TODO: reject names with '.' inside
-
- if (!lookup_block(name))
- d_components[name] = block;
- else
- throw std::invalid_argument("name already in use");
+ if (name.find('.') != std::string::npos ||
+ name.find('/') != std::string::npos)
+ throw std::invalid_argument("illegal character in name");
+
+ if (!lookup_block(name))
+ d_components[name] = block;
+ else
+ throw std::invalid_argument("name already in use");
}
void
gr_hier_block2_detail::connect(const std::string &src_name, int src_port,
const std::string &dst_name, int dst_port)
{
- gr_io_signature_sptr src_io_signature;
- gr_io_signature_sptr dst_io_signature;
+ gr_io_signature_sptr src_io_signature;
+ gr_io_signature_sptr dst_io_signature;
- // Check against our *input_signature* if we're wiring from one of our
external inputs
+ // Check against our *input_signature* if we're wiring from one of our
external inputs
+ if (src_name != "NC") {
if (src_name == "self")
- src_io_signature = d_owner->input_signature();
+ src_io_signature = d_owner->input_signature();
else {
- gr_basic_block_sptr src_block = lookup_block(src_name);
- if (!src_block)
- throw std::invalid_argument("undefined src name");
- src_io_signature = src_block->output_signature();
+ gr_basic_block_sptr src_block = lookup_block(src_name);
+ if (!src_block)
+ throw std::invalid_argument("undefined src name");
+ src_io_signature = src_block->output_signature();
}
- // Check against our *output_signature* if we're wiring to one of our
external outputs
+ check_valid_port(src_io_signature, src_port);
+ }
+
+ // Check against our *output_signature* if we're wiring to one of our
external outputs
+ if (dst_name != "NC") {
if (dst_name == "self")
- dst_io_signature = d_owner->output_signature();
+ dst_io_signature = d_owner->output_signature();
else {
- gr_basic_block_sptr dst_block = lookup_block(dst_name);
- if (!dst_block)
- throw std::invalid_argument("undefined dst name");
- dst_io_signature = dst_block->input_signature();
+ gr_basic_block_sptr dst_block = lookup_block(dst_name);
+ if (!dst_block)
+ throw std::invalid_argument("undefined dst name");
+ dst_io_signature = dst_block->input_signature();
}
-
- // Check port numbers are valid
- check_valid_port(src_io_signature, src_port);
+
check_valid_port(dst_io_signature, dst_port);
-
- // Check destination port not already in use
check_dst_not_used(dst_name, dst_port);
+ }
- // Check endpoint types match
+ // Check endpoint types match
+ if (src_name != "NC" && dst_name != "NC")
check_type_match(src_io_signature, src_port, dst_io_signature, dst_port);
- d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port));
+ gr_edge_sptr edge = gr_make_edge(src_name, src_port, dst_name, dst_port);
+ d_edges.push_back(edge);
}
void
+gr_hier_block2_detail::disconnect(const std::string &src_name, int src_port,
+ const std::string &dst_name, int dst_port)
+{
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ if (((*p)->src_name() == src_name) &&
+ ((*p)->src_port() == src_port) &&
+ ((*p)->dst_name() == dst_name) &&
+ ((*p)->dst_port() == dst_port)) {
+ d_edges.erase(p);
+ return;
+ }
+ }
+
+ throw std::invalid_argument("edge to disconnect not found");
+}
+
+void
gr_hier_block2_detail::check_valid_port(gr_io_signature_sptr sig, int port)
{
- if (port < 0)
- throw std::invalid_argument("port number must not be negative");
+ if (port < 0)
+ throw std::invalid_argument("port number must not be negative");
- if (sig->max_streams() >= 0 && port >= sig->max_streams())
- throw std::invalid_argument("port number exceeds max streams");
+ if (sig->max_streams() >= 0 && port >= sig->max_streams())
+ throw std::invalid_argument("port number exceeds max streams");
}
void
gr_hier_block2_detail::check_dst_not_used(const std::string name, int port)
{
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
- if ((*p)->dst_name() == name && (*p)->dst_port() == port)
- throw std::invalid_argument("destination port in use");
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+ if ((*p)->dst_name() == name && (*p)->dst_port() == port)
+ throw std::invalid_argument("destination port in use");
}
void
gr_hier_block2_detail::check_type_match(gr_io_signature_sptr src_sig, int
src_port,
gr_io_signature_sptr dst_sig, int
dst_port)
{
- if (src_sig->sizeof_stream_item(src_port) !=
dst_sig->sizeof_stream_item(dst_port))
- throw std::invalid_argument("type mismatch");
+ if (src_sig->sizeof_stream_item(src_port) !=
dst_sig->sizeof_stream_item(dst_port))
+ throw std::invalid_argument("type mismatch");
}
std::string
gr_hier_block2_detail::prepend_prefix(const std::string &prefix, const
std::string &str)
{
- return prefix + ((prefix == "") ? "" : ".") + str;
+ return prefix + ((prefix == "") ? "" : ".") + str;
}
gr_endpoint
gr_hier_block2_detail::match_endpoint(const std::string &name, int port, bool
is_input)
{
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
- if (is_input) {
- if ((*p)->src_name() == name && (*p)->src_port() == port)
- return resolve_endpoint((*p)->dst_name(), (*p)->dst_port(),
"", !is_input);
- }
- else {
- if ((*p)->dst_name() == name && (*p)->dst_port() == port)
- return resolve_endpoint((*p)->src_name(), (*p)->src_port(),
"", !is_input);
- }
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ if (is_input) {
+ if ((*p)->src_name() == name && (*p)->src_port() == port)
+ return resolve_endpoint((*p)->dst_name(), (*p)->dst_port(), "",
!is_input);
}
+ else {
+ if ((*p)->dst_name() == name && (*p)->dst_port() == port)
+ return resolve_endpoint((*p)->src_name(), (*p)->src_port(), "",
!is_input);
+ }
+ }
- // Should never get here
- throw std::runtime_error("unable to match endpoint");
+ // Should never get here
+ throw std::runtime_error("unable to match endpoint");
}
gr_endpoint
gr_hier_block2_detail::resolve_endpoint(const std::string &name, int port,
const std::string &prefix, bool
is_input)
{
- gr_basic_block_sptr basic_block = lookup_block(name);
+ gr_basic_block_sptr basic_block = lookup_block(name);
- // Check if 'name' points to gr_block (leaf node)
- gr_block_sptr block(boost::dynamic_pointer_cast<gr_block,
gr_basic_block>(basic_block));
- if (block)
- return gr_endpoint(prepend_prefix(prefix, name), port);
+ // Check if 'name' points to gr_block (leaf node)
+ gr_block_sptr block(boost::dynamic_pointer_cast<gr_block,
gr_basic_block>(basic_block));
+ if (block)
+ return gr_endpoint(prepend_prefix(prefix, name), port);
- // Check if 'name' points to hierarchical block
- gr_hier_block2_sptr
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2,
gr_basic_block>(basic_block));
- if (hier_block2) {
- std::string child_prefix = prepend_prefix(prefix, name);
- gr_endpoint match(hier_block2->d_detail->match_endpoint("self", port,
!is_input));
- return gr_endpoint(prepend_prefix(child_prefix, match.name()),
match.port());
- }
+ // Check if 'name' points to hierarchical block
+ gr_hier_block2_sptr hier_block2(boost::dynamic_pointer_cast<gr_hier_block2,
gr_basic_block>(basic_block));
+ if (hier_block2) {
+ std::string child_prefix = prepend_prefix(prefix, name);
+ gr_endpoint match(hier_block2->d_detail->match_endpoint("self", port,
!is_input));
+ return gr_endpoint(prepend_prefix(child_prefix, match.name()),
match.port());
+ }
- // Shouldn't ever get here
- throw std::runtime_error("unable to resolve endpoint");
+ // Shouldn't ever get here
+ throw std::runtime_error("unable to resolve endpoint");
}
void
gr_hier_block2_detail::flatten(gr_simple_flowgraph_sptr sfg, const std::string
&prefix)
{
- flatten_components(sfg, prefix);
- flatten_edges(sfg, prefix);
+ flatten_components(sfg, prefix);
+ flatten_edges(sfg, prefix);
}
void
gr_hier_block2_detail::flatten_components(gr_simple_flowgraph_sptr sfg, const
std::string &prefix)
{
- // Add my non-hierarchical components to the simple flowgraph, then recurse
- for (gr_hier_component_miter_t p = d_components.begin(); p !=
d_components.end(); p++) {
- std::string name = prepend_prefix(prefix, p->first);
+ // Add my non-hierarchical components to the simple flowgraph, then recurse
+ std::vector<std::string> names = calc_used_components();
- gr_basic_block_sptr basic_block = p->second;
- gr_block_sptr block(boost::dynamic_pointer_cast<gr_block,
gr_basic_block>(basic_block));
- if (block)
- sfg->define_component(name, block);
+ for (std::vector<std::string>::iterator p = names.begin(); p != names.end();
p++) {
+ gr_basic_block_sptr basic_block = lookup_block(*p);
+ std::string name = prepend_prefix(prefix, *p);
- gr_hier_block2_sptr
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2,
gr_basic_block>(basic_block));
- if (hier_block2)
- hier_block2->d_detail->flatten_components(sfg, name);
- }
+ gr_block_sptr block(boost::dynamic_pointer_cast<gr_block,
gr_basic_block>(basic_block));
+ if (block)
+ sfg->define_component(name, block);
+
+ gr_hier_block2_sptr
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2,
gr_basic_block>(basic_block));
+ if (hier_block2)
+ hier_block2->d_detail->flatten_components(sfg, name);
+ }
}
void
gr_hier_block2_detail::flatten_edges(gr_simple_flowgraph_sptr sfg, const
std::string &prefix)
{
- // Add my edges to the flow graph, resolving references to actual endpoints
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
- // Connections to self get resolved/added by parent if actually
connected
- if ((*p)->src_name() == "self" || (*p)->dst_name() == "self")
- continue;
+ // Add my edges to the flow graph, resolving references to actual endpoints
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ // Connections to self get resolved/added by parent if actually connected
+ if ((*p)->src_name() == "self" || (*p)->dst_name() == "self")
+ continue;
- gr_endpoint src_endp = resolve_endpoint((*p)->src_name(),
(*p)->src_port(), prefix, true);
- gr_endpoint dst_endp = resolve_endpoint((*p)->dst_name(),
(*p)->dst_port(), prefix, false);
- sfg->connect(src_endp.name(), src_endp.port(), dst_endp.name(),
dst_endp.port());
- }
+ // Connections to "NC" are silently ignored
+ if ((*p)->src_name() == "NC" || (*p)->dst_name() == "NC")
+ continue;
- // Recurse hierarchical children
- for (gr_hier_component_miter_t p = d_components.begin(); p !=
d_components.end(); p++) {
- gr_hier_block2_sptr
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2,
gr_basic_block>(p->second));
- if (hier_block2)
- hier_block2->d_detail->flatten_edges(sfg, prepend_prefix(prefix,
p->first));
- }
+ gr_endpoint src_endp = resolve_endpoint((*p)->src_name(),
(*p)->src_port(), prefix, true);
+ gr_endpoint dst_endp = resolve_endpoint((*p)->dst_name(),
(*p)->dst_port(), prefix, false);
+ sfg->connect(src_endp.name(), src_endp.port(), dst_endp.name(),
dst_endp.port());
+ }
+
+ // Recurse hierarchical children
+ for (gr_hier_component_miter_t p = d_components.begin(); p !=
d_components.end(); p++) {
+ gr_hier_block2_sptr
hier_block2(boost::dynamic_pointer_cast<gr_hier_block2,
gr_basic_block>(p->second));
+ if (hier_block2)
+ hier_block2->d_detail->flatten_edges(sfg, prepend_prefix(prefix,
p->first));
+ }
}
+
+std::vector<std::string>
+gr_hier_block2_detail::calc_used_components()
+{
+ std::vector<std::string> tmp, result;
+ std::insert_iterator<std::vector<std::string> > inserter(result,
result.begin());
+
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ if ((*p)->src_name() != "NC")
+ tmp.push_back((*p)->dst_name());
+ if ((*p)->dst_name() != "NC")
+ tmp.push_back((*p)->src_name());
+ }
+
+ sort(tmp.begin(), tmp.end());
+ unique_copy(tmp.begin(), tmp.end(), inserter);
+ return result;
+}
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,5 +1,5 @@
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -47,6 +47,8 @@
gr_basic_block_sptr lookup_block(const std::string &name);
void connect(const std::string &src_name, int src_port,
const std::string &dst_name, int dst_port);
+ void disconnect(const std::string &src_name, int src_port,
+ const std::string &dst_name, int dst_port);
void check_valid_port(gr_io_signature_sptr sig, int port);
void check_dst_not_used(const std::string name, int port);
void check_type_match(gr_io_signature_sptr src_sig, int src_port,
@@ -58,7 +60,8 @@
gr_endpoint match_endpoint(const std::string &name, int port, bool
is_input);
gr_endpoint resolve_endpoint(const std::string &name, int port,
const std::string &prefix, bool is_input);
-
+ std::vector<std::string> calc_used_components();
+
public:
~gr_hier_block2_detail();
};
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.cc
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.cc
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.cc
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -34,57 +34,64 @@
gr_runtime_sptr
gr_make_runtime(gr_hier_block2_sptr top_block)
{
- return gr_runtime_sptr(new gr_runtime(top_block));
+ return gr_runtime_sptr(new gr_runtime(top_block));
}
gr_runtime::gr_runtime(gr_hier_block2_sptr top_block)
{
- d_impl = new gr_runtime_impl(top_block);
- s_runtime = this;
+ d_impl = new gr_runtime_impl(top_block);
+ s_runtime = this;
}
gr_runtime::~gr_runtime()
{
- s_runtime = 0; // we don't own this
- delete d_impl;
+ s_runtime = 0; // we don't own this
+ delete d_impl;
}
// FIXME: This prevents using more than one gr_runtime instance
static void
runtime_sigint_handler(int signum)
{
-
- if (s_runtime)
- s_runtime->stop();
+ if (s_runtime)
+ s_runtime->stop();
}
void
gr_runtime::start()
{
- gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+ gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
- d_impl->start();
+ d_impl->start();
}
void
gr_runtime::stop()
{
- d_impl->stop();
+ d_impl->stop();
}
void
gr_runtime::wait()
{
- gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+ gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
- d_impl->wait();
+ d_impl->wait();
}
void
gr_runtime::run()
{
- gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+ gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
- d_impl->start();
- d_impl->wait();
+ d_impl->start();
+ d_impl->wait();
}
+
+void
+gr_runtime::restart()
+{
+ gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+
+ d_impl->restart();
+}
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.h
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.h
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.h
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -29,21 +29,57 @@
gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block);
+/*!
+ *\brief Runtime object that controls simple flow graph operation
+ *
+ * This class is instantiated with a top-level gr_hier_block2. The
+ * runtime then flattens the hierarchical block into a gr_simple_flowgraph,
+ * and allows control through start(), stop(), wait(), and run().
+ *
+ */
class gr_runtime
{
private:
- gr_runtime(gr_hier_block2_sptr top_block);
- friend gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block);
+ gr_runtime(gr_hier_block2_sptr top_block);
+ friend gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block);
- gr_runtime_impl *d_impl;
+ gr_runtime_impl *d_impl;
public:
- ~gr_runtime();
+ ~gr_runtime();
- void start();
- void stop();
- void wait();
- void run();
+ /*!
+ * Start the flow graph. Creates an undetached scheduler thread for
+ * each flow graph partition. Returns to caller once created.
+ */
+ void start();
+
+ /*!
+ * Stop a running flow graph. Tells each created scheduler thread
+ * to exit, then returns to caller.
+ */
+ void stop();
+
+ /*!
+ * Wait for a stopped flow graph to complete. Joins each completed
+ * thread.
+ */
+ void wait();
+
+ /*!
+ * Calls start(), then wait(). Used to run a flow graph that will stop
+ * on its own, or to run a flow graph indefinitely until SIGTERM is
+ * received().
+ */
+ void run();
+
+ /*!
+ * Restart a running flow graph, after topology changes have
+ * been made to its top_block (or children). Causes each created
+ * scheduler thread to end, recalculates the flow graph, and
+ * recreates new threads (possibly a different number from before.)
+ */
+ void restart();
};
#endif /* INCLUDED_GR_RUNTIME_H */
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.i
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.i
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime.i
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2006 Free Software Foundation, Inc.
+ * Copyright 2004,2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -36,6 +36,7 @@
void start() throw (std::runtime_error);
void stop() throw (std::runtime_error);
void wait() throw (std::runtime_error);
+ void restart() throw (std::runtime_error);
};
%{
@@ -72,4 +73,10 @@
r->wait();
}
+void runtime_restart_unlocked(gr_runtime_sptr r) throw (std::runtime_error)
+{
+ ensure_py_gil_state2 _lock;
+ r->restart();
+}
+
%}
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
2007-04-07 14:22:29 UTC (rev 4914)
@@ -52,56 +52,86 @@
void
gr_runtime_impl::start()
{
- if (d_running)
- throw std::runtime_error("already running");
- else
- d_running = true;
+ if (d_running)
+ throw std::runtime_error("already running");
+ else
+ d_running = true;
- d_sfg->d_detail->reset();
- d_top_block->d_detail->flatten(d_sfg);
- d_sfg->d_detail->validate();
- d_sfg->d_detail->setup_connections();
+ // Create new simple flow graph by flattening hierarchical block
+ d_sfg->d_detail->reset();
+ d_top_block->d_detail->flatten(d_sfg);
- d_graphs = d_sfg->d_detail->partition();
- if (GR_RUNTIME_IMPL_DEBUG)
- std::cout << "Flow graph has " << d_graphs.size()
- << " sub-graphs." << std::endl;
+ // Validate new simple flow graph and wire it up
+ d_sfg->d_detail->validate();
+ d_sfg->d_detail->setup_connections();
- d_threads.clear();
- for (std::vector<gr_block_vector_t>::iterator p = d_graphs.begin();
- p != d_graphs.end(); p++) {
- gr_scheduler_thread *thread = new gr_scheduler_thread(*p);
- thread->start();
- d_threads.push_back(thread);
- }
+ // Execute scheduler threads
+ start_threads();
}
void
+gr_runtime_impl::start_threads()
+{
+ d_graphs = d_sfg->d_detail->partition();
+ if (GR_RUNTIME_IMPL_DEBUG)
+ std::cout << "Flow graph has " << d_graphs.size()
+ << " sub-graphs." << std::endl;
+
+ d_threads.clear();
+ for (std::vector<gr_block_vector_t>::iterator p = d_graphs.begin();
+ p != d_graphs.end(); p++) {
+ gr_scheduler_thread *thread = new gr_scheduler_thread(*p);
+ thread->start();
+ d_threads.push_back(thread);
+ }
+}
+
+void
gr_runtime_impl::stop()
{
- if (!d_running)
- throw std::runtime_error("not running");
+ if (!d_running)
+ throw std::runtime_error("not running");
- for (gr_scheduler_thread_viter_t p = d_threads.begin(); p !=
d_threads.end(); p++)
- (*p)->stop();
+ for (gr_scheduler_thread_viter_t p = d_threads.begin(); p !=
d_threads.end(); p++)
+ (*p)->stop();
- d_running = false;
+ d_running = false;
}
void
gr_runtime_impl::wait()
{
- void *dummy_status; // don't ever dereference this
+ void *dummy_status; // don't ever dereference this
- for (gr_scheduler_thread_viter_t p = d_threads.begin(); p !=
d_threads.end(); p++) {
- (*p)->join(&dummy_status); // pthreads will self-delete, so pointer is
now dead
- (*p) = 0; // FIXME: switch to stl::list and actually remove from
container
- }
+ for (gr_scheduler_thread_viter_t p = d_threads.begin(); p !=
d_threads.end(); p++) {
+ (*p)->join(&dummy_status); // pthreads will self-delete, so pointer is now
dead
+ (*p) = 0; // FIXME: switch to stl::list and actually remove from container
+ }
}
+void
+gr_runtime_impl::restart()
+{
+ if (!d_running)
+ throw std::runtime_error("not running");
+
+ // Stop scheduler threads and wait for completion
+ stop();
+ wait();
+
+ // Create new simple flow graph
+ gr_simple_flowgraph_sptr new_sfg = gr_make_simple_flowgraph();
+ d_top_block->d_detail->flatten(new_sfg);
+ new_sfg->validate();
+ new_sfg->d_detail->merge_connections(d_sfg);
+ // d_sfg = new_sfg;
+
+ start_threads();
+}
+
gr_scheduler_thread::gr_scheduler_thread(gr_block_vector_t graph) :
- omni_thread(NULL, PRIORITY_NORMAL),
- d_sts(gr_make_single_threaded_scheduler(graph))
+ omni_thread(NULL, PRIORITY_NORMAL),
+ d_sts(gr_make_single_threaded_scheduler(graph))
{
}
@@ -111,28 +141,30 @@
void gr_scheduler_thread::start()
{
- start_undetached();
+ start_undetached();
}
void *
gr_scheduler_thread::run_undetached(void *arg)
{
- // First code to run in new thread context
+ // First code to run in new thread context
- // Mask off SIGINT in this thread to gaurantee mainline thread gets signal
+ // Mask off SIGINT in this thread to gaurantee mainline thread gets signal
#ifdef HAVE_SIGPROCMASK
- sigset_t old_set;
- sigset_t new_set;
- sigemptyset(&new_set);
- sigaddset(&new_set, SIGINT);
- sigprocmask(SIG_BLOCK, &new_set, &old_set);
+ sigset_t old_set;
+ sigset_t new_set;
+ sigemptyset(&new_set);
+ sigaddset(&new_set, SIGINT);
+ sigprocmask(SIG_BLOCK, &new_set, &old_set);
#endif
- // Run the single-threaded scheduler
- d_sts->run();
- return 0;
+ // Run the single-threaded scheduler
+ d_sts->run();
+ return 0;
}
-void gr_scheduler_thread::stop()
+void
+gr_scheduler_thread::stop()
{
- d_sts->stop();
+ d_sts->stop();
}
+
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -33,38 +33,56 @@
typedef std::vector<gr_scheduler_thread *> gr_scheduler_thread_vector_t;
typedef gr_scheduler_thread_vector_t::iterator gr_scheduler_thread_viter_t;
+/*!
+ *\brief A single thread of execution for the scheduler
+ *
+ * This class implements a single thread that runs undetached, and
+ * invokes the single-threaded block scheduler. The runtime makes
+ * one of these for each distinct partition of a flowgraph and runs
+ * them in parallel.
+ *
+ */
class gr_scheduler_thread : public omni_thread
{
private:
- gr_single_threaded_scheduler_sptr d_sts;
+ gr_single_threaded_scheduler_sptr d_sts;
public:
- gr_scheduler_thread(gr_block_vector_t graph);
- ~gr_scheduler_thread();
+ gr_scheduler_thread(gr_block_vector_t graph);
+ ~gr_scheduler_thread();
- virtual void *run_undetached(void *arg);
- void start();
- void stop();
+ virtual void *run_undetached(void *arg);
+ void start();
+ void stop();
};
+/*!
+ *\brief Implementation details of gr_runtime
+ *
+ * The actual implementation of gr_runtime. Separate class allows
+ * decoupling of changes from dependent classes.
+ *
+ */
class gr_runtime_impl
{
private:
- gr_runtime_impl(gr_hier_block2_sptr top_block);
- friend class gr_runtime;
+ gr_runtime_impl(gr_hier_block2_sptr top_block);
+ friend class gr_runtime;
- bool d_running;
- gr_hier_block2_sptr d_top_block;
- gr_simple_flowgraph_sptr d_sfg;
- std::vector<gr_block_vector_t> d_graphs;
- gr_scheduler_thread_vector_t d_threads;
+ bool d_running;
+ gr_hier_block2_sptr d_top_block;
+ gr_simple_flowgraph_sptr d_sfg;
+ std::vector<gr_block_vector_t> d_graphs;
+ gr_scheduler_thread_vector_t d_threads;
- void start();
- void stop();
- void wait();
-
+ void start();
+ void start_threads();
+ void stop();
+ void wait();
+ void restart();
+
public:
- ~gr_runtime_impl();
+ ~gr_runtime_impl();
};
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -31,22 +31,33 @@
class gr_simple_flowgraph_detail;
+/*!
+ *\brief Class representing a low-level, "flattened" flow graph
+ *
+ * This class holds the results of the call to gr.hier_block2.flatten(),
+ * which is a graph that has only the connected blocks and edges of
+ * the original hier_block2, with all the hierarchy removed.
+ *
+ * While this class is exported to Python via SWIG for ease of QA
+ * testing, it is not used by application developers, and there is
+ * no way to feed this to a gr.runtime() instance.
+ */
class gr_simple_flowgraph
{
private:
- friend class gr_runtime_impl;
- friend gr_simple_flowgraph_sptr gr_make_simple_flowgraph();
- gr_simple_flowgraph();
+ friend class gr_runtime_impl;
+ friend gr_simple_flowgraph_sptr gr_make_simple_flowgraph();
+ gr_simple_flowgraph();
- gr_simple_flowgraph_detail *d_detail;
+ gr_simple_flowgraph_detail *d_detail;
public:
- ~gr_simple_flowgraph();
+ ~gr_simple_flowgraph();
- void define_component(const std::string &name, gr_block_sptr block);
- void connect(const std::string &src, int src_port,
- const std::string &dst, int dst_port);
- void validate();
+ void define_component(const std::string &name, gr_block_sptr block);
+ void connect(const std::string &src, int src_port,
+ const std::string &dst, int dst_port);
+ void validate();
};
#endif /* INCLUDED_GR_SIMPLE_FLOWGRAPH_H */
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -32,13 +32,13 @@
#include <iostream>
#include <stdexcept>
-#define GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG 0
+#define GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG 1
gr_edge_sptr
gr_make_edge(const std::string &src_name, int src_port,
const std::string &dst_name, int dst_port)
{
- return gr_edge_sptr(new gr_edge(src_name, src_port, dst_name, dst_port));
+ return gr_edge_sptr(new gr_edge(src_name, src_port, dst_name, dst_port));
}
gr_edge::gr_edge(const std::string &src_name, int src_port, const std::string
&dst_name, int dst_port)
@@ -52,8 +52,8 @@
}
gr_simple_flowgraph_detail::gr_simple_flowgraph_detail() :
-d_components(),
-d_edges()
+ d_components(),
+ d_edges()
{
}
@@ -64,162 +64,161 @@
void
gr_simple_flowgraph_detail::reset()
{
- // Boost shared pointers will deallocate as needed
- d_edges.clear();
- d_components.clear();
+ // Boost shared pointers will deallocate as needed
+ d_edges.clear();
+ d_components.clear();
}
gr_block_sptr
gr_simple_flowgraph_detail::lookup_block(const std::string &name)
{
- gr_component_miter_t p = d_components.find(name);
- if (p != d_components.end())
- return p->second;
- else
- return gr_block_sptr();
+ gr_component_miter_t p = d_components.find(name);
+ if (p != d_components.end())
+ return p->second;
+ else
+ return gr_block_sptr();
}
std::string
gr_simple_flowgraph_detail::lookup_name(gr_block_sptr block)
{
- for (gr_component_miter_t p = d_components.begin(); p !=
d_components.end(); p++) {
- if (p->second == block)
- return p->first;
- }
+ for (gr_component_miter_t p = d_components.begin(); p != d_components.end();
p++) {
+ if (p->second == block)
+ return p->first;
+ }
- return std::string(""); // Not found
+ return std::string(""); // Not found
}
void
gr_simple_flowgraph_detail::define_component(const std::string &name,
gr_block_sptr block)
{
- if (!block)
- throw std::invalid_argument("null block passed");
+ if (!block)
+ throw std::invalid_argument("null block passed");
- if (!lookup_block(name))
- d_components[name] = block;
- else
- throw std::invalid_argument("name already in use");
+ if (!lookup_block(name))
+ d_components[name] = block;
+ else
+ throw std::invalid_argument("name already in use");
}
void
gr_simple_flowgraph_detail::connect(const std::string &src_name, int src_port,
const std::string &dst_name, int dst_port)
{
- gr_block_sptr src_block = lookup_block(src_name);
- gr_block_sptr dst_block = lookup_block(dst_name);
+ gr_block_sptr src_block = lookup_block(src_name);
+ gr_block_sptr dst_block = lookup_block(dst_name);
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "Connecting " << src_name << ":" << src_port << "->"
- << dst_name << ":" << dst_port << std::endl;
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "SFG connecting " << src_name << ":" << src_port << "->"
+ << dst_name << ":" << dst_port << std::endl;
- if (!src_block)
- throw std::invalid_argument("unknown src name");
- if (!dst_block)
- throw std::invalid_argument("unknown dst name");
+ if (!src_block)
+ throw std::invalid_argument("unknown src name");
+ if (!dst_block)
+ throw std::invalid_argument("unknown dst name");
- check_valid_port(src_block->output_signature(), src_port);
- check_valid_port(dst_block->input_signature(), dst_port);
- check_dst_not_used(dst_name, dst_port);
- check_type_match(src_block, src_port, dst_block, dst_port);
+ check_valid_port(src_block->output_signature(), src_port);
+ check_valid_port(dst_block->input_signature(), dst_port);
+ check_dst_not_used(dst_name, dst_port);
+ check_type_match(src_block, src_port, dst_block, dst_port);
- d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port));
+ d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port));
}
void
gr_simple_flowgraph_detail::check_valid_port(gr_io_signature_sptr sig, int
port)
{
- if (port < 0)
- throw std::invalid_argument("negative port number");
- if (sig->max_streams() >= 0 && port >= sig->max_streams())
- throw std::invalid_argument("port number exceeds max");
+ if (port < 0)
+ throw std::invalid_argument("negative port number");
+ if (sig->max_streams() >= 0 && port >= sig->max_streams())
+ throw std::invalid_argument("port number exceeds max");
}
void
gr_simple_flowgraph_detail::check_dst_not_used(const std::string &name, int
port)
{
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
- if ((*p)->dst_name() == name && (*p)->dst_port() == port)
- throw std::invalid_argument("dst already in use");
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+ if ((*p)->dst_name() == name && (*p)->dst_port() == port)
+ throw std::invalid_argument("dst already in use");
}
void
gr_simple_flowgraph_detail::check_type_match(gr_block_sptr src_block, int
src_port,
gr_block_sptr dst_block, int
dst_port)
{
- int src_size = src_block->output_signature()->sizeof_stream_item(src_port);
- int dst_size = dst_block->input_signature()->sizeof_stream_item(dst_port);
+ int src_size = src_block->output_signature()->sizeof_stream_item(src_port);
+ int dst_size = dst_block->input_signature()->sizeof_stream_item(dst_port);
- if (src_size != dst_size)
- throw std::invalid_argument("type size mismatch");
+ if (src_size != dst_size)
+ throw std::invalid_argument("type size mismatch");
}
void
gr_simple_flowgraph_detail::validate()
{
- for (gr_component_miter_t p = d_components.begin(); p !=
d_components.end(); p++) {
- std::vector<int> used_ports;
- int ninputs, noutputs;
+ for (gr_component_miter_t p = d_components.begin(); p != d_components.end();
p++) {
+ std::vector<int> used_ports;
+ int ninputs, noutputs;
- used_ports = calc_used_ports(p->first, true); // inputs
- ninputs = used_ports.size();
- check_contiguity(p->second, used_ports, true); // inputs
+ used_ports = calc_used_ports(p->first, true); // inputs
+ ninputs = used_ports.size();
+ check_contiguity(p->second, used_ports, true); // inputs
- used_ports = calc_used_ports(p->first, false); // outputs
- noutputs = used_ports.size();
- check_contiguity(p->second, used_ports, false); // outputs
+ used_ports = calc_used_ports(p->first, false); // outputs
+ noutputs = used_ports.size();
+ check_contiguity(p->second, used_ports, false); // outputs
- if (!(p->second->check_topology(ninputs, noutputs)))
- throw std::runtime_error("check topology failed");
- }
+ if (!(p->second->check_topology(ninputs, noutputs)))
+ throw std::runtime_error("check topology failed");
+ }
}
std::vector<int>
gr_simple_flowgraph_detail::calc_used_ports(const std::string &name, bool
check_inputs)
{
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "Calculating used " << (check_inputs ? "input " : "output
")
- << "ports...";
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "Calculating used " << (check_inputs ? "input " : "output ")
+ << "ports...";
- std::vector<int> tmp, result;
- std::insert_iterator<std::vector<int> > inserter(result, result.begin());
+ std::vector<int> tmp, result;
+ std::insert_iterator<std::vector<int> > inserter(result, result.begin());
- gr_edge_vector_t edges = calc_connections(name, check_inputs);
+ gr_edge_vector_t edges = calc_connections(name, check_inputs);
+ for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) {
+ if (check_inputs == true)
+ tmp.push_back((*p)->dst_port());
+ else
+ tmp.push_back((*p)->src_port());
+ }
- for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) {
- if (check_inputs == true)
- tmp.push_back((*p)->dst_port());
- else
- tmp.push_back((*p)->src_port());
- }
+ // remove duplicates
+ std::sort(tmp.begin(), tmp.end());
+ std::unique_copy(tmp.begin(), tmp.end(), inserter);
- // remove duplicates
- std::sort(tmp.begin(), tmp.end());
- std::unique_copy(tmp.begin(), tmp.end(), inserter);
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << result.size() << std::endl;
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << result.size() << std::endl;
-
- return result;
+ return result;
}
gr_edge_vector_t
gr_simple_flowgraph_detail::calc_connections(const std::string &name, bool
check_inputs)
{
- gr_edge_vector_t result;
+ gr_edge_vector_t result;
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
- if (check_inputs) {
- if ((*p)->dst_name() == name)
- result.push_back(*p);
- }
- else {
- if ((*p)->src_name() == name)
- result.push_back(*p);
- }
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ if (check_inputs) {
+ if ((*p)->dst_name() == name)
+ result.push_back(*p);
}
+ else {
+ if ((*p)->src_name() == name)
+ result.push_back(*p);
+ }
+ }
- return result; // assumes no duplicates
+ return result; // assumes no duplicates
}
void
@@ -227,335 +226,346 @@
const std::vector<int>
&used_ports,
bool check_inputs)
{
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "Checking " << (check_inputs ? "input " : "output ")
- << "contiguity...";
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "Checking " << (check_inputs ? "input " : "output ")
+ << "contiguity...";
- gr_io_signature_sptr sig =
- check_inputs ? block->input_signature() : block->output_signature();
+ gr_io_signature_sptr sig =
+ check_inputs ? block->input_signature() : block->output_signature();
- int nports = used_ports.size();
- int min_ports = sig->min_streams();
+ int nports = used_ports.size();
+ int min_ports = sig->min_streams();
- if (nports == 0) {
- if (min_ports == 0) {
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "ok." << std::endl;
- return;
- }
- else {
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "needs " << min_ports << ", only has "
- << nports << std::endl;
-
- throw std::runtime_error("insufficient ports");
- }
+ if (nports == 0) {
+ if (min_ports == 0) {
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "ok." << std::endl;
+ return;
}
+ else {
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "needs " << min_ports << ", only has "
+ << nports << std::endl;
+ throw std::runtime_error("insufficient ports");
+ }
+ }
- if (used_ports[nports-1]+1 != nports) {
- for (int i = 0; i < nports; i++) {
- if (used_ports[i] != i) {
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "missing " << (check_inputs ? "input
":"output ")
- << i << std::endl;
+ if (used_ports[nports-1]+1 != nports) {
+ for (int i = 0; i < nports; i++) {
+ if (used_ports[i] != i) {
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "missing " << (check_inputs ? "input ":"output ")
+ << i << std::endl;
- throw std::runtime_error("missing input assignment");
- }
- }
+ throw std::runtime_error("missing input assignment");
+ }
}
+ }
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "ok." << std::endl;
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "ok." << std::endl;
}
void
gr_simple_flowgraph_detail::setup_connections()
{
- // Assign block details to component blocks
- for (gr_component_miter_t p = d_components.begin(); p !=
d_components.end(); p++) {
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "Allocating output buffers for " << p->first << "..."
<< std::endl;
+ // Assign block details to component blocks
+ for (gr_component_miter_t p = d_components.begin(); p != d_components.end();
p++) {
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "Allocating output buffers for " << p->first << "..." <<
std::endl;
- int ninputs = calc_used_ports(p->first, true).size();
- int noutputs = calc_used_ports(p->first, false).size();
- gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs);
- for (int i = 0; i < noutputs; i++)
- detail->set_output(i, allocate_buffer(p->first, i));
- p->second->set_detail(detail);
- }
+ int ninputs = calc_used_ports(p->first, true).size();
+ int noutputs = calc_used_ports(p->first, false).size();
+ gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs);
+ for (int i = 0; i < noutputs; i++)
+ detail->set_output(i, allocate_buffer(p->first, i));
+ p->second->set_detail(detail);
+ }
- // Connect inputs to outputs for each block
- for(gr_component_miter_t p = d_components.begin(); p !=
d_components.end(); p++) {
- // Get its detail and edges that feed into it
- gr_block_detail_sptr detail = p->second->detail();
- gr_edge_vector_t in_edges = calc_upstream_edges(p->first);
+ // Connect inputs to outputs for each block
+ for(gr_component_miter_t p = d_components.begin(); p != d_components.end();
p++) {
+ // Get its detail and edges that feed into it
+ gr_block_detail_sptr detail = p->second->detail();
+ gr_edge_vector_t in_edges = calc_upstream_edges(p->first);
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- if (in_edges.size() > 0)
- std::cout << "Connecting inputs to " << p->first << "..."
<< std::endl;
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ if (in_edges.size() > 0)
+ std::cout << "Connecting inputs to " << p->first << "..." << std::endl;
- // For each edge that feeds into it
- for (gr_edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) {
- // Set the input buffer on the destination port to the output
- // buffer on the source port
- int dst_port = (*e)->dst_port();
- int src_port = (*e)->src_port();
- gr_block_sptr src_block = lookup_block((*e)->src_name());
- gr_buffer_sptr src_buffer = src_block->detail()->output(src_port);
+ // For each edge that feeds into it
+ for (gr_edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) {
+ // Set the input reader on the destination port to the output
+ // buffer on the source port
+ int dst_port = (*e)->dst_port();
+ int src_port = (*e)->src_port();
+ gr_block_sptr src_block = lookup_block((*e)->src_name());
+ gr_buffer_sptr src_buffer = src_block->detail()->output(src_port);
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "Setting input on " << (*e)->dst_name()
- << ":" << dst_port << std::endl;
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "Setting input on " << (*e)->dst_name()
+ << ":" << dst_port << std::endl;
- detail->set_input(dst_port, gr_buffer_add_reader(src_buffer,
p->second->history()-1));
- }
+ detail->set_input(dst_port, gr_buffer_add_reader(src_buffer,
p->second->history()-1));
}
+ }
}
gr_buffer_sptr
gr_simple_flowgraph_detail::allocate_buffer(const std::string &name, int port)
{
- gr_block_sptr block = lookup_block(name);
- int item_size = block->output_signature()->sizeof_stream_item(port);
- int nitems = s_fixed_buffer_size/item_size;
+ gr_block_sptr block = lookup_block(name);
+ int item_size = block->output_signature()->sizeof_stream_item(port);
+ int nitems = s_fixed_buffer_size/item_size;
- // Make sure there are at least twice the output_multiple no. of items
- if (nitems < 2*block->output_multiple()) // Note: this means
output_multiple()
- nitems = 2*block->output_multiple(); // can't be changed by block
dynamically
+ // Make sure there are at least twice the output_multiple no. of items
+ if (nitems < 2*block->output_multiple()) // Note: this means
output_multiple()
+ nitems = 2*block->output_multiple(); // can't be changed by block
dynamically
- // If any downstream blocks are decimators and/or have a large
output_multiple,
- // ensure we have a buffer at least twice their decimation
factor*output_multiple
- gr_block_vector_t blocks = calc_downstream_blocks(name, port);
- for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
- int decimation = (int)(1.0/(*p)->relative_rate());
- int multiple = (*p)->output_multiple();
- int history = (*p)->history();
- nitems = std::max(nitems, 2*(decimation*multiple+history));
- }
+ // If any downstream blocks are decimators and/or have a large
output_multiple,
+ // ensure we have a buffer at least twice their decimation
factor*output_multiple
+ gr_block_vector_t blocks = calc_downstream_blocks(name, port);
+ for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+ int decimation = (int)(1.0/(*p)->relative_rate());
+ int multiple = (*p)->output_multiple();
+ int history = (*p)->history();
+ nitems = std::max(nitems, 2*(decimation*multiple+history));
+ }
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "Allocating buffer for port " << port << " with "
- << nitems << " items of size " << item_size << std::endl;
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "Allocating buffer for port " << port << " with "
+ << nitems << " items of size " << item_size << std::endl;
- return gr_make_buffer(nitems, item_size);
+ return gr_make_buffer(nitems, item_size);
}
gr_block_vector_t
gr_simple_flowgraph_detail::calc_downstream_blocks(const std::string &name,
int port)
{
- gr_block_vector_t tmp, result;
- std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
+ gr_block_vector_t tmp, result;
+ std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
- if ((*p)->src_name() == name && (*p)->src_port() == port)
- tmp.push_back(lookup_block((*p)->dst_name()));
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+ if ((*p)->src_name() == name && (*p)->src_port() == port)
+ tmp.push_back(lookup_block((*p)->dst_name()));
- // Remove duplicates
- sort(tmp.begin(), tmp.end());
- unique_copy(tmp.begin(), tmp.end(), inserter);
- return result;
+ // Remove duplicates
+ sort(tmp.begin(), tmp.end());
+ unique_copy(tmp.begin(), tmp.end(), inserter);
+ return result;
}
gr_block_vector_t
gr_simple_flowgraph_detail::calc_downstream_blocks(const std::string &name)
{
- gr_block_vector_t tmp, result;
- std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
+ gr_block_vector_t tmp, result;
+ std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
- if ((*p)->src_name() == name)
- tmp.push_back(lookup_block((*p)->dst_name()));
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+ if ((*p)->src_name() == name)
+ tmp.push_back(lookup_block((*p)->dst_name()));
- // Remove duplicates
- sort(tmp.begin(), tmp.end());
- unique_copy(tmp.begin(), tmp.end(), inserter);
- return result;
+ // Remove duplicates
+ sort(tmp.begin(), tmp.end());
+ unique_copy(tmp.begin(), tmp.end(), inserter);
+ return result;
}
gr_edge_vector_t
gr_simple_flowgraph_detail::calc_upstream_edges(const std::string &name)
{
- gr_edge_vector_t result;
+ gr_edge_vector_t result;
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
- if ((*p)->dst_name() == name)
- result.push_back(*p);
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)
+ if ((*p)->dst_name() == name)
+ result.push_back(*p);
- return result; // Assume no duplicates
+ return result; // Assume no duplicates
}
gr_block_vector_t
gr_simple_flowgraph_detail::calc_used_blocks()
{
- std::vector<std::string> tmp, tmp_unique;
- std::insert_iterator<std::vector<std::string> > inserter(tmp_unique,
tmp_unique.begin());
- gr_block_vector_t result;
+ std::vector<std::string> tmp, tmp_unique;
+ std::insert_iterator<std::vector<std::string> > inserter(tmp_unique,
tmp_unique.begin());
+ gr_block_vector_t result;
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
- tmp.push_back((*p)->src_name());
- tmp.push_back((*p)->dst_name());
- }
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
+ tmp.push_back((*p)->src_name());
+ tmp.push_back((*p)->dst_name());
+ }
- sort(tmp.begin(), tmp.end());
- unique_copy(tmp.begin(), tmp.end(), inserter);
+ sort(tmp.begin(), tmp.end());
+ unique_copy(tmp.begin(), tmp.end(), inserter);
- for (std::vector<std::string>::iterator p = tmp_unique.begin();
- p != tmp_unique.end(); p++)
- result.push_back(lookup_block(*p));
+ for (std::vector<std::string>::iterator p = tmp_unique.begin();
+ p != tmp_unique.end(); p++)
+ result.push_back(lookup_block(*p));
- if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "Flowgraph uses " << result.size()
- << " distinct blocks." << std::endl;
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "Flowgraph uses " << result.size()
+ << " distinct blocks." << std::endl;
- return result;
+ return result;
}
std::vector<gr_block_vector_t>
gr_simple_flowgraph_detail::partition()
{
- std::vector<gr_block_vector_t> result;
- gr_block_vector_t blocks = calc_used_blocks();
- gr_block_vector_t graph;
+ std::vector<gr_block_vector_t> result;
+ gr_block_vector_t blocks = calc_used_blocks();
+ gr_block_vector_t graph;
- while (blocks.size() > 0) {
- graph = calc_reachable_blocks(blocks[0], blocks);
- assert(graph.size());
- result.push_back(topological_sort(graph));
+ while (blocks.size() > 0) {
+ graph = calc_reachable_blocks(blocks[0], blocks);
+ assert(graph.size());
+ result.push_back(topological_sort(graph));
- for (gr_block_viter_t p = graph.begin(); p != graph.end(); p++)
- blocks.erase(find(blocks.begin(), blocks.end(), *p));
- }
+ for (gr_block_viter_t p = graph.begin(); p != graph.end(); p++)
+ blocks.erase(find(blocks.begin(), blocks.end(), *p));
+ }
- return result;
+ return result;
}
gr_block_vector_t
gr_simple_flowgraph_detail::calc_reachable_blocks(gr_block_sptr block,
gr_block_vector_t &blocks)
{
- gr_block_vector_t result;
+ gr_block_vector_t result;
- // Mark all blocks as unvisited
- for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
- (*p)->detail()->set_color(gr_block_detail::WHITE);
+ // Mark all blocks as unvisited
+ for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
+ (*p)->detail()->set_color(gr_block_detail::WHITE);
- // Recursively mark all reachable blocks
- reachable_dfs_visit(block, blocks);
+ // Recursively mark all reachable blocks
+ reachable_dfs_visit(block, blocks);
- // Collect all the blocks that have been visited
- for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
- if ((*p)->detail()->color() == gr_block_detail::BLACK)
- result.push_back(*p);
+ // Collect all the blocks that have been visited
+ for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++)
+ if ((*p)->detail()->color() == gr_block_detail::BLACK)
+ result.push_back(*p);
- return result;
+ return result;
}
// Recursively mark all reachable blocks from given block and block list
void
gr_simple_flowgraph_detail::reachable_dfs_visit(gr_block_sptr block,
gr_block_vector_t &blocks)
{
- // Mark the current one as visited
- block->detail()->set_color(gr_block_detail::BLACK);
+ // Mark the current one as visited
+ block->detail()->set_color(gr_block_detail::BLACK);
- // Recurse into adjacent vertices
- gr_block_vector_t adjacent = calc_adjacent_blocks(block, blocks);
+ // Recurse into adjacent vertices
+ gr_block_vector_t adjacent = calc_adjacent_blocks(block, blocks);
- for (gr_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++)
- if ((*p)->detail()->color() == gr_block_detail::WHITE)
- reachable_dfs_visit(*p, blocks);
+ for (gr_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++)
+ if ((*p)->detail()->color() == gr_block_detail::WHITE)
+ reachable_dfs_visit(*p, blocks);
}
// Return a list of block adjacent to a given block along any edge
gr_block_vector_t
gr_simple_flowgraph_detail::calc_adjacent_blocks(gr_block_sptr block,
gr_block_vector_t &blocks)
{
- gr_block_vector_t tmp, result;
- std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
+ gr_block_vector_t tmp, result;
+ std::insert_iterator<gr_block_vector_t> inserter(result, result.begin());
- // Find any blocks that are inputs or outputs
- for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
- if (lookup_block((*p)->src_name()) == block)
- tmp.push_back(lookup_block((*p)->dst_name()));
- if (lookup_block((*p)->dst_name()) == block)
- tmp.push_back(lookup_block((*p)->src_name()));
- }
+ // Find any blocks that are inputs or outputs
+ for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {
- // Remove duplicates
- sort(tmp.begin(), tmp.end());
- unique_copy(tmp.begin(), tmp.end(), inserter);
- return result;
+ // Edges to "NC" are silently ignored
+ if ((*p)->src_name() == "NC" || (*p)->dst_name() == "NC")
+ continue;
+
+ if (lookup_block((*p)->src_name()) == block)
+ tmp.push_back(lookup_block((*p)->dst_name()));
+ if (lookup_block((*p)->dst_name()) == block)
+ tmp.push_back(lookup_block((*p)->src_name()));
+ }
+
+ // Remove duplicates
+ sort(tmp.begin(), tmp.end());
+ unique_copy(tmp.begin(), tmp.end(), inserter);
+ return result;
}
gr_block_vector_t
gr_simple_flowgraph_detail::topological_sort(gr_block_vector_t &blocks)
{
- gr_block_vector_t result, tmp;
- tmp = sort_sources_first(blocks);
+ gr_block_vector_t result, tmp;
+ tmp = sort_sources_first(blocks);
- // Start 'em all white
- for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++)
- (*p)->detail()->set_color(gr_block_detail::WHITE);
+ // Start 'em all white
+ for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++)
+ (*p)->detail()->set_color(gr_block_detail::WHITE);
- for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++) {
- if ((*p)->detail()->color() == gr_block_detail::WHITE)
- topological_dfs_visit(*p, result);
- }
+ for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++) {
+ if ((*p)->detail()->color() == gr_block_detail::WHITE)
+ topological_dfs_visit(*p, result);
+ }
- reverse(result.begin(), result.end());
+ reverse(result.begin(), result.end());
- return result;
+ return result;
}
bool
gr_simple_flowgraph_detail::source_p(gr_block_sptr block)
{
- return (calc_upstream_edges(lookup_name(block)).size() == 0);
+ return (calc_upstream_edges(lookup_name(block)).size() == 0);
}
gr_block_vector_t
gr_simple_flowgraph_detail::sort_sources_first(gr_block_vector_t &blocks)
{
- gr_block_vector_t sources, nonsources, result;
+ gr_block_vector_t sources, nonsources, result;
- for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
- if (source_p(*p))
- sources.push_back(*p);
- else
- nonsources.push_back(*p);
- }
+ for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+ if (source_p(*p))
+ sources.push_back(*p);
+ else
+ nonsources.push_back(*p);
+ }
- for (gr_block_viter_t p = sources.begin(); p != sources.end(); p++)
- result.push_back(*p);
+ for (gr_block_viter_t p = sources.begin(); p != sources.end(); p++)
+ result.push_back(*p);
- for (gr_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++)
- result.push_back(*p);
+ for (gr_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++)
+ result.push_back(*p);
- return result;
+ return result;
}
void
gr_simple_flowgraph_detail::topological_dfs_visit(gr_block_sptr block,
gr_block_vector_t &output)
{
- block->detail()->set_color(gr_block_detail::GREY);
+ block->detail()->set_color(gr_block_detail::GREY);
- gr_block_vector_t blocks(calc_downstream_blocks(lookup_name(block)));
+ gr_block_vector_t blocks(calc_downstream_blocks(lookup_name(block)));
- for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
- switch ((*p)->detail()->color()) {
- case gr_block_detail::WHITE:
- topological_dfs_visit(*p, output);
- break;
+ for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
+ switch ((*p)->detail()->color()) {
+ case gr_block_detail::WHITE:
+ topological_dfs_visit(*p, output);
+ break;
- case gr_block_detail::GREY:
- throw std::runtime_error("flow graph has loops!");
+ case gr_block_detail::GREY:
+ throw std::runtime_error("flow graph has loops!");
- case gr_block_detail::BLACK:
- continue;
+ case gr_block_detail::BLACK:
+ continue;
- default:
- throw std::runtime_error("invalid color on block!");
- }
+ default:
+ throw std::runtime_error("invalid color on block!");
}
+ }
- block->detail()->set_color(gr_block_detail::BLACK);
- output.push_back(block);
+ block->detail()->set_color(gr_block_detail::BLACK);
+ output.push_back(block);
}
+
+void
+gr_simple_flowgraph_detail::merge_connections(gr_simple_flowgraph_sptr sfg)
+{
+ if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
+ std::cout << "merge_connections() hit" << std::endl;
+}
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
2007-04-07 14:22:29 UTC (rev 4914)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,6 +25,7 @@
#include <gr_block.h>
#include <map>
+#include <iostream>
#define GR_FIXED_BUFFER_SIZE (32*(1L<<10))
@@ -34,13 +35,13 @@
class gr_endpoint
{
private:
- std::string d_name;
- int d_port;
+ std::string d_name;
+ int d_port;
public:
- gr_endpoint(const std::string &name, int port) { d_name = name; d_port =
port; }
- const std::string &name() const { return d_name; }
- int port() const { return d_port; }
+ gr_endpoint(const std::string &name, int port) { d_name = name; d_port =
port; }
+ const std::string &name() const { return d_name; }
+ int port() const { return d_port; }
};
class gr_edge;
@@ -51,20 +52,23 @@
class gr_edge
{
private:
- friend gr_edge_sptr gr_make_edge(const std::string &src_name, int src_port,
- const std::string &dst_name, int
dst_port);
- gr_edge(const std::string &name, int src_port,
- const std::string &name, int dst_port);
+ friend gr_edge_sptr gr_make_edge(const std::string &src_name, int src_port,
+ const std::string &dst_name, int dst_port);
+ gr_edge(const std::string &name, int src_port,
+ const std::string &name, int dst_port);
- gr_endpoint d_src;
- gr_endpoint d_dst;
+ gr_endpoint d_src;
+ gr_endpoint d_dst;
public:
- ~gr_edge();
- const std::string src_name() const { return d_src.name(); }
- const std::string dst_name() const { return d_dst.name(); }
- int src_port() const { return d_src.port(); }
- int dst_port() const { return d_dst.port(); }
+ ~gr_edge();
+
+ gr_endpoint src() const { return d_src; }
+ gr_endpoint dst() const { return d_dst; }
+ const std::string src_name() const { return d_src.name(); }
+ const std::string dst_name() const { return d_dst.name(); }
+ int src_port() const { return d_src.port(); }
+ int dst_port() const { return d_dst.port(); }
};
typedef std::vector<gr_edge_sptr> gr_edge_vector_t;
@@ -73,63 +77,80 @@
class gr_simple_flowgraph_detail
{
private:
- friend class gr_simple_flowgraph;
- friend class gr_runtime_impl;
- friend class topo_block_cmp;
+ friend class gr_simple_flowgraph;
+ friend class gr_runtime_impl;
+ friend class topo_block_cmp;
- gr_simple_flowgraph_detail();
+ gr_simple_flowgraph_detail();
- gr_component_map_t d_components;
- gr_edge_vector_t d_edges;
- static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE;
+ gr_component_map_t d_components;
+ gr_edge_vector_t d_edges;
+ static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE;
- void reset();
- void define_component(const std::string &name, gr_block_sptr block);
- void connect(const std::string &src, int src_port,
- const std::string &dst, int dst_port);
- gr_block_sptr lookup_block(const std::string &name);
- std::string lookup_name(const gr_block_sptr block);
+ void reset();
+ void define_component(const std::string &name, gr_block_sptr block);
+ void connect(const std::string &src, int src_port,
+ const std::string &dst, int dst_port);
+ gr_block_sptr lookup_block(const std::string &name);
+ std::string lookup_name(const gr_block_sptr block);
- void check_valid_port(gr_io_signature_sptr sig, int port);
- void check_dst_not_used(const std::string &name, int port);
- void check_type_match(gr_block_sptr src_block, int src_port,
- gr_block_sptr dst_block, int dst_port);
- void validate();
- gr_edge_vector_t calc_connections(const std::string &name, bool
check_inputs); // false=use outputs
- std::vector<int> calc_used_ports(const std::string &name, bool
check_inputs);
- void check_contiguity(gr_block_sptr block, const std::vector<int>
&used_ports,
- bool check_inputs);
- void setup_connections();
- gr_buffer_sptr allocate_buffer(const std::string &name, int port);
- gr_block_vector_t calc_downstream_blocks(const std::string &name, int
port);
- gr_block_vector_t calc_downstream_blocks(const std::string &name);
- gr_edge_vector_t calc_upstream_edges(const std::string &name);
- gr_block_vector_t calc_used_blocks();
- std::vector<gr_block_vector_t> partition();
- gr_block_vector_t calc_reachable_blocks(gr_block_sptr block,
gr_block_vector_t &blocks);
- gr_block_vector_t topological_sort(gr_block_vector_t &blocks);
- void reachable_dfs_visit(gr_block_sptr block, gr_block_vector_t &blocks);
- gr_block_vector_t calc_adjacent_blocks(gr_block_sptr block,
gr_block_vector_t &blocks);
- bool source_p(gr_block_sptr block);
- gr_block_vector_t sort_sources_first(gr_block_vector_t &blocks);
- void topological_dfs_visit(gr_block_sptr block, gr_block_vector_t &output);
+ void check_valid_port(gr_io_signature_sptr sig, int port);
+ void check_dst_not_used(const std::string &name, int port);
+ void check_type_match(gr_block_sptr src_block, int src_port,
+ gr_block_sptr dst_block, int dst_port);
+ void validate();
+ gr_edge_vector_t calc_connections(const std::string &name, bool
check_inputs); // false=use outputs
+ std::vector<int> calc_used_ports(const std::string &name, bool
check_inputs);
+ void check_contiguity(gr_block_sptr block, const std::vector<int>
&used_ports,
+ bool check_inputs);
+ void setup_connections();
+ void merge_connections(gr_simple_flowgraph_sptr sfg);
+
+ gr_buffer_sptr allocate_buffer(const std::string &name, int port);
+ gr_block_vector_t calc_downstream_blocks(const std::string &name, int port);
+ gr_block_vector_t calc_downstream_blocks(const std::string &name);
+ gr_edge_vector_t calc_upstream_edges(const std::string &name);
+ gr_block_vector_t calc_used_blocks();
+ std::vector<gr_block_vector_t> partition();
+ gr_block_vector_t calc_reachable_blocks(gr_block_sptr block,
gr_block_vector_t &blocks);
+ gr_block_vector_t topological_sort(gr_block_vector_t &blocks);
+ void reachable_dfs_visit(gr_block_sptr block, gr_block_vector_t &blocks);
+ gr_block_vector_t calc_adjacent_blocks(gr_block_sptr block,
gr_block_vector_t &blocks);
+ bool source_p(gr_block_sptr block);
+ gr_block_vector_t sort_sources_first(gr_block_vector_t &blocks);
+ void topological_dfs_visit(gr_block_sptr block, gr_block_vector_t &output);
public:
- ~gr_simple_flowgraph_detail();
+ ~gr_simple_flowgraph_detail();
};
inline std::ostream&
operator <<(std::ostream& os, const gr_block_sptr p)
{
- os << "<gr_block " << p->name() << " (" << p->unique_id() << ")>";
- return os;
+ os << "<gr_block " << p->name() << " (" << p->unique_id() << ")>";
+ return os;
}
inline std::ostream&
operator <<(std::ostream &os, const gr_endpoint endp)
{
- os << endp.name() << ":" << endp.port();
- return os;
+ os << endp.name() << ":" << endp.port();
+ return os;
}
+inline std::ostream&
+operator <<(std::ostream &os, const gr_edge_sptr edge)
+{
+ os << edge->src() << "->" << edge->dst();
+ return os;
+}
+
+inline void
+enumerate_edges(gr_edge_vector_t &edges)
+{
+ std::cout << "Edge list has " << edges.size() << " elements" << std::endl;
+ for(gr_edge_viter_t p = edges.begin(); p != edges.end(); p++)
+ std::cout << *p << std::endl;
+}
+
#endif /* INCLUDED_GR_SIMPLE_FLOWGRAPH_H */
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/hier_block2.py
2007-04-07 14:22:29 UTC (rev 4914)
@@ -21,7 +21,7 @@
from gnuradio_swig_python import hier_block2_swig, gr_make_runtime, \
runtime_run_unlocked, runtime_start_unlocked, runtime_stop_unlocked, \
- runtime_wait_unlocked
+ runtime_wait_unlocked, runtime_restart_unlocked
#
# This hack forces a 'has-a' relationship to look like an 'is-a' one.
@@ -41,6 +41,10 @@
def define_component(self, name, comp):
return self._hb.define_component(name, comp.basic_block())
+# This allows the 'run_locked' methods, which are defined in gr_runtime.i,
+# to release the Python global interpreter lock before calling the actual
+# method in gr.runtime
+
class runtime(object):
def __init__(self, top_block):
if (isinstance(top_block, hier_block2)):
@@ -59,3 +63,6 @@
def wait(self):
runtime_wait_unlocked(self._r)
+
+ def restart(self):
+ runtime_restart_unlocked(self._r)
Modified:
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py
===================================================================
---
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py
2007-04-07 14:16:19 UTC (rev 4913)
+++
gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py
2007-04-07 14:22:29 UTC (rev 4914)
@@ -6,10 +6,10 @@
def setUp(self):
pass
-
+
def tearDown(self):
pass
-
+
def test_001_make(self):
hblock = gr.hier_block2("test_block",
gr.io_signature(1,1,gr.sizeof_int),
@@ -33,11 +33,22 @@
gr.io_signature(1,1,gr.sizeof_int))
self.assertRaises(ValueError,
lambda: hblock.define_component("self", gr.nop(gr.sizeof_int)))
+ self.assertRaises(ValueError,
+ lambda: hblock.define_component("NC", gr.nop(gr.sizeof_int)))
- def test_004_define_component_name_in_use(self):
+ def test_004_define_component_illegal_character(self):
hblock = gr.hier_block2("test_block",
gr.io_signature(1,1,gr.sizeof_int),
gr.io_signature(1,1,gr.sizeof_int))
+ self.assertRaises(ValueError,
+ lambda: hblock.define_component("nop.1", gr.nop(gr.sizeof_int)))
+ self.assertRaises(ValueError,
+ lambda: hblock.define_component("nop/1", gr.nop(gr.sizeof_int)))
+
+ def test_005_define_component_name_in_use(self):
+ hblock = gr.hier_block2("test_block",
+ gr.io_signature(1,1,gr.sizeof_int),
+ gr.io_signature(1,1,gr.sizeof_int))
hblock.define_component("src", gr.null_source(gr.sizeof_int))
self.assertRaises(ValueError,
lambda: hblock.define_component("src", gr.null_sink(gr.sizeof_int)))
@@ -72,7 +83,7 @@
hblock.define_component("nop1", nop1)
self.assertRaises(ValueError,
lambda: hblock.connect("nop2", 0, "self", 0))
-
+
def test_010_connect_unknown_dst(self):
hblock = gr.hier_block2("test_block",
gr.io_signature(1,1,gr.sizeof_int),
@@ -96,7 +107,7 @@
hblock.define_component("nop1", gr.nop(gr.sizeof_int))
self.assertRaises(ValueError,
lambda: hblock.connect("self", 1, "nop1", 0))
-
+
def test_013_connect_invalid_dst_port_neg(self):
hblock = gr.hier_block2("test_block",
gr.io_signature(1,1,gr.sizeof_int),
@@ -122,7 +133,7 @@
hblock.connect("nop1", 0, "self", 0);
self.assertRaises(ValueError,
lambda: hblock.connect("nop1", 0, "self", 0))
-
+
def test_016_connect_one_src_two_dst(self):
hblock = gr.hier_block2("test_block",
gr.io_signature(1,1,gr.sizeof_int),
@@ -146,93 +157,85 @@
gr.io_signature(0,0,gr.sizeof_int),
gr.io_signature(0,0,gr.sizeof_int))
hblock.check_topology(0, 0);
- """
- def test_019_validate(self):
- hblock = gr.hier_block2("test_block",
- gr.io_signature(0,0,gr.sizeof_int),
- gr.io_signature(0,0,gr.sizeof_int))
- runtime = gr.runtime(hblock)
- runtime.validate()
-
- def test_020_validate_1(self):
- hblock = gr.hier_block2("test_block",
- gr.io_signature(0,0,gr.sizeof_int),
- gr.io_signature(0,0,gr.sizeof_int))
- hblock.define_component("src", gr.null_source(gr.sizeof_int))
- hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
- hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
- hblock.connect("src", 0, "dst1", 0)
- hblock.connect("src", 0, "dst2", 0)
- runtime = gr.runtime(hblock)
- runtime.validate()
- def test_021_validate_2(self):
+ def test_019_disconnect(self):
hblock = gr.hier_block2("test_block",
- gr.io_signature(0,0,gr.sizeof_int),
- gr.io_signature(0,0,gr.sizeof_int))
- hblock.define_component("src1", gr.null_source(gr.sizeof_int))
+ gr.io_signature(1,1,gr.sizeof_int),
+ gr.io_signature(1,1,gr.sizeof_int))
hblock.define_component("nop1", gr.nop(gr.sizeof_int))
- hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
- hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
- hblock.connect("src1", 0, "nop1", 0)
- hblock.connect("src1", 0, "nop1", 1)
- hblock.connect("nop1", 0, "dst1", 0)
- hblock.connect("nop1", 1, "dst2", 0)
- runtime = gr.runtime(hblock)
- runtime.validate()
-
- def test_022_validate_3(self):
+ hblock.define_component("nop2", gr.nop(gr.sizeof_int))
+ hblock.connect("nop1", 0, "nop2", 0)
+ hblock.disconnect("nop1", 0, "nop2", 0)
+
+ def test_020_disconnect_unknown(self):
hblock = gr.hier_block2("test_block",
- gr.io_signature(0,0,gr.sizeof_int),
- gr.io_signature(0,0,gr.sizeof_int))
- hblock.define_component("src1", gr.null_source(gr.sizeof_int))
+ gr.io_signature(1,1,gr.sizeof_int),
+ gr.io_signature(1,1,gr.sizeof_int))
hblock.define_component("nop1", gr.nop(gr.sizeof_int))
- hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
- hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
- hblock.connect("src1", 0, "nop1", 0)
- hblock.connect("src1", 0, "nop1", 2)
- hblock.connect("nop1", 0, "dst1", 0)
- hblock.connect("nop1", 1, "dst2", 0)
- runtime = gr.runtime(hblock)
- self.assertRaises(RuntimeError,
- lambda: runtime.validate())
-
- def test_023_validate_4(self):
- hblock = gr.hier_block2("test_block",
- gr.io_signature(0,0,gr.sizeof_int),
- gr.io_signature(0,0,gr.sizeof_int))
- hblock.define_component("src1", gr.null_source(gr.sizeof_int))
- hblock.define_component("nop1", gr.nop(gr.sizeof_int))
- hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
- hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
- hblock.connect("src1", 0, "nop1", 0)
- hblock.connect("src1", 0, "nop1", 1)
- hblock.connect("nop1", 0, "dst1", 0)
- hblock.connect("nop1", 2, "dst2", 0)
- runtime = gr.runtime(hblock)
- self.assertRaises(RuntimeError,
- lambda: runtime.validate())
-
- def test_024_validate_5(self):
- hblock = gr.hier_block2("test_block",
- gr.io_signature(0,0,gr.sizeof_int),
- gr.io_signature(0,0,gr.sizeof_int))
- hblock.define_component("src1", gr.null_source(gr.sizeof_int))
- hblock.define_component("nop1", gr.nop(gr.sizeof_int))
- hblock.define_component("dst1", gr.null_sink(gr.sizeof_int))
- hblock.define_component("dst2", gr.null_sink(gr.sizeof_int))
- hblock.connect("src1", 0, "nop1", 0)
- hblock.connect("src1", 0, "nop1", 1)
- hblock.connect("nop1", 0, "dst1", 0)
- hblock.connect("nop1", 1, "dst2", 0)
- runtime = gr.runtime(hblock)
- runtime.validate()
- # Pending implementation of disconnect
- # hblock.disconnect("src1", 0, "nop1", 1)
- # runtime.validate()
- # self.assertRaises(ValueError,
- # lambda: hblock.disconnect("src1", 0, "nop1", 1))
- """
-
+ hblock.define_component("nop2", gr.nop(gr.sizeof_int))
+ hblock.connect("nop1", 0, "nop2", 0)
+ self.assertRaises(ValueError,
+ lambda: hblock.disconnect("nop1", 0, "foo", 0))
+
+ def test_021_run(self):
+ expected = (1.0, 2.0, 3.0, 4.0)
+
+ hblock = gr.hier_block2("test_block",
+ gr.io_signature(0,0,0),
+ gr.io_signature(0,0,0))
+ hblock.define_component("src", gr.vector_source_f(expected, False))
+ sink1 = gr.vector_sink_f()
+ sink2 = gr.vector_sink_f()
+ hblock.define_component("sink1", sink1)
+ hblock.define_component("sink2", sink2)
+ hblock.connect("src", 0, "sink1", 0)
+ hblock.connect("src", 0, "sink2", 0)
+ runtime = gr.runtime(hblock)
+ runtime.run()
+ actual1 = sink1.data()
+ actual2 = sink2.data()
+ self.assertEquals(expected, actual1)
+ self.assertEquals(expected, actual2)
+
+ def test_022_connect_disconnect(self):
+ expected = (1.0, 2.0, 3.0, 4.0)
+ hblock = gr.hier_block2("test_block",
+ gr.io_signature(0,0,0),
+ gr.io_signature(0,0,0))
+ hblock.define_component("src", gr.vector_source_f(expected, False))
+ sink1 = gr.vector_sink_f()
+ sink2 = gr.vector_sink_f()
+ hblock.define_component("sink1", sink1)
+ hblock.define_component("sink2", sink2)
+ hblock.connect("src", 0, "sink1", 0)
+ hblock.connect("src", 0, "sink2", 0)
+ hblock.disconnect("src", 0, "sink2", 0)
+ hblock.connect("NC", 0, "sink2", 0)
+ runtime = gr.runtime(hblock)
+ runtime.run()
+
+ def test_023_run_and_disconnect(self):
+ expected = (1.0, 2.0, 3.0, 4.0)
+ hblock = gr.hier_block2("test_block",
+ gr.io_signature(0,0,0),
+ gr.io_signature(0,0,0))
+ hblock.define_component("src", gr.vector_source_f(expected, False))
+ sink1 = gr.vector_sink_f()
+ sink2 = gr.vector_sink_f()
+ hblock.define_component("sink1", sink1)
+ hblock.define_component("sink2", sink2)
+ hblock.connect("src", 0, "sink1", 0)
+ hblock.connect("src", 0, "sink2", 0)
+ runtime = gr.runtime(hblock)
+ runtime.start()
+ hblock.disconnect("src", 0, "sink2", 0)
+ hblock.connect("NC", 0, "sink2", 0)
+ runtime.restart()
+ runtime.wait()
+ actual1 = sink1.data()
+ actual2 = sink2.data()
+ self.assertEquals(expected, actual1)
+ self.assertEquals((), actual2)
+
if __name__ == "__main__":
gr_unittest.main()
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r4914 - in gnuradio/branches/developers/jcorgan/hier2/gnuradio-core/src: lib/runtime python/gnuradio/gr,
jcorgan <=