diff options
author | jcorgan | 2007-04-28 02:20:28 +0000 |
---|---|---|
committer | jcorgan | 2007-04-28 02:20:28 +0000 |
commit | b26ea69676c09f5366a9e2f33b11ae5a7521ffe5 (patch) | |
tree | 0641c1c25d6e827f70941e07f4611d0a2b6b83cd /gnuradio-core/src | |
parent | 00696b9f754338de9362932c1ecfb1e144a38786 (diff) | |
download | gnuradio-b26ea69676c09f5366a9e2f33b11ae5a7521ffe5.tar.gz gnuradio-b26ea69676c09f5366a9e2f33b11ae5a7521ffe5.tar.bz2 gnuradio-b26ea69676c09f5366a9e2f33b11ae5a7521ffe5.zip |
Merged -r 5137:5174 from developer branch jcorgan/hb. Trunk passes distcheck. Converts gr.hier_block2 API to not use 'define_component' methodology anymore.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5177 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gnuradio-core/src')
25 files changed, 968 insertions, 1379 deletions
diff --git a/gnuradio-core/src/lib/runtime/Makefile.am b/gnuradio-core/src/lib/runtime/Makefile.am index 91d3c144b..ee71fcdbc 100644 --- a/gnuradio-core/src/lib/runtime/Makefile.am +++ b/gnuradio-core/src/lib/runtime/Makefile.am @@ -129,7 +129,6 @@ swiginclude_HEADERS = \ gr_msg_queue.i \ gr_realtime.i \ gr_runtime.i \ - gr_simple_flowgraph.i \ gr_single_threaded_scheduler.i \ gr_sync_block.i \ gr_sync_decimator.i \ diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc index 65dea95fb..d5ed4ccc9 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc @@ -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 * @@ -50,14 +50,15 @@ gr_hier_block2::~gr_hier_block2() } void -gr_hier_block2::define_component(const std::string &name, gr_basic_block_sptr block) +gr_hier_block2::connect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) { - d_detail->define_component(name, block); + d_detail->connect(src, src_port, dst, dst_port); } void -gr_hier_block2::connect(const std::string &src_name, int src_port, - const std::string &dst_name, int dst_port) +gr_hier_block2::disconnect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) { - d_detail->connect(src_name, src_port, dst_name, dst_port); + d_detail->disconnect(src, src_port, dst, dst_port); } diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h index 9d2dd3569..53a23bb47 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.h +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h @@ -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 * @@ -59,9 +59,10 @@ protected: public: virtual ~gr_hier_block2(); - 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 connect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port); + void disconnect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port); }; #endif /* INCLUDED_GR_HIER_BLOCK2_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.i b/gnuradio-core/src/lib/runtime/gr_hier_block2.i index c5a676534..f9a126fe2 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.i +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.i @@ -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 * @@ -44,9 +44,10 @@ public: ~gr_hier_block2 (); // Add a named block to the container - void define_component(const std::string &name, gr_basic_block_sptr basic_block) + void connect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) throw (std::invalid_argument); - void connect(const std::string &src_name, int src_port, - const std::string &dst_name, int dst_port) + void disconnect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) throw (std::invalid_argument); }; diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc index 545a64bfd..b41d0c65c 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc @@ -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,157 @@ #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), + d_fg(gr_make_simple_flowgraph()), + d_inputs(owner->input_signature()->max_streams()), + d_outputs(owner->output_signature()->max_streams()) { } gr_hier_block2_detail::~gr_hier_block2_detail() { - 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(); + d_owner = 0; // Don't use delete, we didn't allocate } void -gr_hier_block2_detail::define_component(const std::string &name, gr_basic_block_sptr block) +gr_hier_block2_detail::connect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) { - if (!block) - throw std::invalid_argument("null block passed"); - - if (name == "self") - 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 (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connecting: " << gr_endpoint(src, src_port) + << " -> " << gr_endpoint(dst, dst_port) << std::endl; + + if (src.get() == dst.get()) + throw std::invalid_argument("src and destination blocks cannot be the same"); + + // Assignments to block inputs or outputs + int max_port; + if (src.get() == d_owner) { + max_port = src->input_signature()->max_streams(); + if ((max_port != -1 && (src_port >= max_port)) || src_port < 0) + throw std::invalid_argument("source port out of range"); + return assign_input(src_port, dst_port, dst); + } + + if (dst.get() == d_owner) { + max_port = dst->output_signature()->max_streams(); + if ((max_port != -1 && (dst_port >= max_port)) || dst_port < 0) + throw std::invalid_argument("source port out of range"); + return assign_output(dst_port, src_port, src); + } + + // Internal connections + d_fg->connect(src, src_port, dst, dst_port); + + // TODO: connects to NC } void -gr_hier_block2_detail::connect(const std::string &src_name, int src_port, - const std::string &dst_name, int dst_port) +gr_hier_block2_detail::disconnect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) { - 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 - if (src_name == "self") - 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(); - } - - // Check against our *output_signature* if we're wiring to one of our external outputs - if (dst_name == "self") - 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(); - } - - // 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_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)); -} + // Handle disconnecting inputs and outputs -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 (sig->max_streams() >= 0 && port >= sig->max_streams()) - throw std::invalid_argument("port number exceeds max streams"); + d_fg->disconnect(src, src_port, dst, dst_port); } -void -gr_hier_block2_detail::check_dst_not_used(const std::string name, int port) +void +gr_hier_block2_detail::assign_input(int my_port, int port, gr_basic_block_sptr block) { - 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"); -} + if (my_port < 0 || my_port >= (signed)d_inputs.size()) + throw std::invalid_argument("input port number out of range"); -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 (d_inputs[my_port].block()) + throw std::invalid_argument("input port in use"); -std::string -gr_hier_block2_detail::prepend_prefix(const std::string &prefix, const std::string &str) -{ - return prefix + ((prefix == "") ? "" : ".") + str; + d_inputs[my_port] = gr_endpoint(block, port); } -gr_endpoint -gr_hier_block2_detail::match_endpoint(const std::string &name, int port, bool is_input) +void +gr_hier_block2_detail::assign_output(int my_port, int port, gr_basic_block_sptr block) { - 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"); -} + if (my_port < 0 || my_port >= (signed)d_outputs.size()) + throw std::invalid_argument("output port number out of range"); -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); - - // 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()); - } - - // Shouldn't ever get here - throw std::runtime_error("unable to resolve endpoint"); + if (d_outputs[my_port].block()) + throw std::invalid_argument("output port in use"); + + d_outputs[my_port] = gr_endpoint(block, port); } -void -gr_hier_block2_detail::flatten(gr_simple_flowgraph_sptr sfg, const std::string &prefix) +gr_endpoint +gr_hier_block2_detail::resolve_port(int port, bool is_input) { - flatten_components(sfg, prefix); - flatten_edges(sfg, prefix); + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Resolving port " << port << " as an " + << (is_input ? "input" : "output") + << " of " << d_owner->name() << std::endl; + + gr_endpoint result; + + if (is_input) { + if (port < 0 || port >= (signed)d_inputs.size()) + throw std::runtime_error("input port number out of range"); + result = resolve_endpoint(d_inputs[port], true); + } + else { + if (port < 0 || port >= (signed)d_outputs.size()) + throw std::runtime_error("output port number out of range"); + result = resolve_endpoint(d_outputs[port], false); + } + + if (!result.block()) + throw std::runtime_error("unable to resolve port"); + + return result; } -void -gr_hier_block2_detail::flatten_components(gr_simple_flowgraph_sptr sfg, const std::string &prefix) +gr_endpoint +gr_hier_block2_detail::resolve_endpoint(const gr_endpoint &endp, bool is_input) { - // 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); - - 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); - - 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); - } + // Check if endpoint is a leaf node + if (boost::dynamic_pointer_cast<gr_block, gr_basic_block>(endp.block())) + return endp; + + // Check if endpoint is a hierarchical block + gr_hier_block2_sptr hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, gr_basic_block>(endp.block())); + if (hier_block2) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Resolving endpoint " << endp << " as an " + << (is_input ? "input" : "output") + << ", recursing" << std::endl; + return hier_block2->d_detail->resolve_port(endp.port(), is_input); + } + + // Shouldn't ever get here + throw std::runtime_error("block is not a valid gr_block or gr_hier_block2!"); } void -gr_hier_block2_detail::flatten_edges(gr_simple_flowgraph_sptr sfg, const std::string &prefix) +gr_hier_block2_detail::flatten(gr_simple_flowgraph_sptr sfg) { - // 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()); - } - - // 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)); - } + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "flattening " << d_owner->name() << std::endl; + + // Add my edges to the flow graph, resolving references to actual endpoints + for (gr_edge_viter_t p = d_fg->d_detail->d_edges.begin(); p != d_fg->d_detail->d_edges.end(); p++) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Flattening edge " << (*p) << std::endl; + + gr_endpoint src_endp = resolve_endpoint((*p)->src(), false); + gr_endpoint dst_endp = resolve_endpoint((*p)->dst(), true); + sfg->connect(src_endp, dst_endp); + } + + gr_basic_block_vector_t blocks = d_fg->d_detail->calc_used_blocks(); + + // Recurse hierarchical children + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + gr_hier_block2_sptr hier_block2(boost::dynamic_pointer_cast<gr_hier_block2, gr_basic_block>(*p)); + if (hier_block2) + hier_block2->d_detail->flatten(sfg); + } } diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h index 095bd40f5..f0e7b7e82 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h @@ -1,5 +1,5 @@ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -25,9 +25,6 @@ #include <gr_simple_flowgraph_detail.h> #include <boost/utility.hpp> -typedef std::map<std::string, gr_basic_block_sptr> gr_hier_component_map_t; -typedef std::map<std::string, gr_basic_block_sptr>::iterator gr_hier_component_miter_t; - class gr_hier_block2_detail : boost::noncopyable { private: @@ -39,26 +36,21 @@ private: // Private implementation data gr_hier_block2 *d_owner; - gr_hier_component_map_t d_components; - gr_edge_vector_t d_edges; + gr_simple_flowgraph_sptr d_fg; + gr_endpoint_vector_t d_inputs; + gr_endpoint_vector_t d_outputs; // Private implementation methods - void define_component(const std::string &name, gr_basic_block_sptr block); - 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 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, - gr_io_signature_sptr dst_sig, int dst_port); - std::string prepend_prefix(const std::string &prefix, const std::string &str); - void flatten(gr_simple_flowgraph_sptr sfg, const std::string &prefix = ""); - void flatten_components(gr_simple_flowgraph_sptr sfg, const std::string &prefix); - void flatten_edges(gr_simple_flowgraph_sptr sfg, const std::string &prefix); - 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); - + void connect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port); + void disconnect(gr_basic_block_sptr, int src_port, + gr_basic_block_sptr, int dst_port); + void assign_input(int my_port, int port, gr_basic_block_sptr block); + void assign_output(int my_port, int port, gr_basic_block_sptr block); + void flatten(gr_simple_flowgraph_sptr sfg); + gr_endpoint resolve_port(int port, bool is_input); + gr_endpoint resolve_endpoint(const gr_endpoint &endp, bool is_input); + public: ~gr_hier_block2_detail(); }; diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.cc b/gnuradio-core/src/lib/runtime/gr_runtime.cc index aab8ea5ab..a8b932f21 100644 --- a/gnuradio-core/src/lib/runtime/gr_runtime.cc +++ b/gnuradio-core/src/lib/runtime/gr_runtime.cc @@ -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 @@ static gr_runtime *s_runtime = 0; 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(); +} + +void +gr_runtime::restart() +{ + gr_local_sighandler sigint(SIGINT, runtime_sigint_handler); - d_impl->start(); - d_impl->wait(); + d_impl->restart(); } diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.h b/gnuradio-core/src/lib/runtime/gr_runtime.h index fc58da456..5aec6dcf0 100644 --- a/gnuradio-core/src/lib/runtime/gr_runtime.h +++ b/gnuradio-core/src/lib/runtime/gr_runtime.h @@ -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 @@ class gr_runtime_impl; 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(); + + /*! + * 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(); - void start(); - void stop(); - void wait(); - 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 */ diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.i b/gnuradio-core/src/lib/runtime/gr_runtime.i index 3a8b7e0b6..10e757baa 100644 --- a/gnuradio-core/src/lib/runtime/gr_runtime.i +++ b/gnuradio-core/src/lib/runtime/gr_runtime.i @@ -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 @@ public: 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 @@ void runtime_wait_unlocked(gr_runtime_sptr r) throw (std::runtime_error) r->wait(); } +void runtime_restart_unlocked(gr_runtime_sptr r) throw (std::runtime_error) +{ + ensure_py_gil_state2 _lock; + r->restart(); +} + %} diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc index f8d65261e..5cd75f3ce 100644 --- a/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc +++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc @@ -36,8 +36,6 @@ #include <stdexcept> #include <iostream> -#define GR_RUNTIME_IMPL_DEBUG 0 - gr_runtime_impl::gr_runtime_impl(gr_hier_block2_sptr top_block) : d_running(false), d_top_block(top_block), @@ -52,56 +50,82 @@ gr_runtime_impl::~gr_runtime_impl() void gr_runtime_impl::start() { - 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(); - - 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); - } + if (d_running) + throw std::runtime_error("already running"); + else + d_running = true; + + // Create new simple flow graph by flattening hierarchical block + d_sfg->d_detail->reset(); + d_top_block->d_detail->flatten(d_sfg); + + // Validate new simple flow graph and wire it up + d_sfg->d_detail->validate(); + d_sfg->d_detail->setup_connections(); + + // Execute scheduler threads + start_threads(); +} + +void +gr_runtime_impl::start_threads() +{ + d_graphs = d_sfg->d_detail->partition(); + 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 +135,29 @@ gr_scheduler_thread::~gr_scheduler_thread() 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(); } diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.h b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h index e69446719..bb2a08334 100644 --- a/gnuradio-core/src/lib/runtime/gr_runtime_impl.h +++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h @@ -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 @@ class gr_scheduler_thread; 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(); }; diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc index 21aeb587c..780d51d78 100644 --- a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc @@ -28,11 +28,9 @@ #include <gr_simple_flowgraph_detail.h> #include <iostream> -#define GR_SIMPLE_FLOWGRAPH_DEBUG 0 - gr_simple_flowgraph_sptr gr_make_simple_flowgraph() { - return gr_simple_flowgraph_sptr(new gr_simple_flowgraph()); + return gr_simple_flowgraph_sptr(new gr_simple_flowgraph()); } gr_simple_flowgraph::gr_simple_flowgraph() : @@ -42,26 +40,31 @@ d_detail(new gr_simple_flowgraph_detail()) gr_simple_flowgraph::~gr_simple_flowgraph() { - delete d_detail; + delete d_detail; +} + +void +gr_simple_flowgraph::connect(gr_basic_block_sptr src_block, int src_port, + gr_basic_block_sptr dst_block, int dst_port) +{ + d_detail->connect(gr_endpoint(src_block, src_port), gr_endpoint(dst_block, dst_port)); } void -gr_simple_flowgraph::define_component(const std::string &name, gr_block_sptr block) +gr_simple_flowgraph::connect(const gr_endpoint &src, const gr_endpoint &dst) { - if (GR_SIMPLE_FLOWGRAPH_DEBUG) - std::cout << "Defining block " << block << " as " << name << std::endl; - d_detail->define_component(name, block); + d_detail->connect(src, dst); } void -gr_simple_flowgraph::connect(const std::string &src_name, int src_port, - const std::string &dst_name, int dst_port) +gr_simple_flowgraph::disconnect(gr_basic_block_sptr src_block, int src_port, + gr_basic_block_sptr dst_block, int dst_port) { - d_detail->connect(src_name, src_port, dst_name, dst_port); + d_detail->disconnect(gr_endpoint(src_block, src_port), gr_endpoint(dst_block, dst_port)); } void gr_simple_flowgraph::validate() { - d_detail->validate(); + d_detail->validate(); } diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h index ca2c505e5..a22e558ff 100644 --- a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h @@ -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,52 @@ gr_simple_flowgraph_sptr gr_make_simple_flowgraph(); class gr_simple_flowgraph_detail; +class gr_endpoint +{ +private: + friend class gr_hier_block2_detail; + gr_basic_block_sptr d_block; + int d_port; + +public: + gr_endpoint() : d_block(), d_port(0) { } // Internal use only + gr_endpoint(gr_basic_block_sptr block, int port) { d_block = block; d_port = port; } + gr_basic_block_sptr block() const { return d_block; } + int port() const { return d_port; } +}; + +typedef std::vector<gr_endpoint> gr_endpoint_vector_t; + +/*! + *\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 class gr_hier_block2_detail; + 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 connect(gr_basic_block_sptr src_block, int src_port, + gr_basic_block_sptr dst_block, int dst_port); + void connect(const gr_endpoint &src, const gr_endpoint &dst); + void disconnect(gr_basic_block_sptr src_block, int src_port, + gr_basic_block_sptr dst_block, int dst_port); + void validate(); }; #endif /* INCLUDED_GR_SIMPLE_FLOWGRAPH_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.i b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.i deleted file mode 100644 index c3654fe50..000000000 --- a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.i +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -class gr_simple_flowgraph; -typedef boost::shared_ptr<gr_simple_flowgraph> gr_simple_flowgraph_sptr; -%template(gr_simple_flowgraph_sptr) boost::shared_ptr<gr_simple_flowgraph>; -%rename(simple_flowgraph) gr_make_simple_flowgraph; -%ignore gr_simple_flowgraph; - -gr_simple_flowgraph_sptr gr_make_simple_flowgraph(); - -class gr_simple_flowgraph -{ -private: - gr_simple_flowgraph(); - -public: - ~gr_simple_flowgraph(); - void define_component(const std::string name, gr_block_sptr block) - throw (std::invalid_argument); - void connect(const std::string &src, int src_port, - const std::string &dst, int dst_port) - throw (std::invalid_argument); - void validate() - throw (std::runtime_error); -}; diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc index 0c9c9b707..13d23efe5 100644 --- a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc @@ -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,31 +32,16 @@ #include <iostream> #include <stdexcept> -#define GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG 0 - 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)); -} - -gr_edge::gr_edge(const std::string &src_name, int src_port, const std::string &dst_name, int dst_port) - : d_src(src_name, src_port), - d_dst(dst_name, dst_port) +gr_make_edge(const gr_endpoint &src, const gr_endpoint &dst) { + return gr_edge_sptr(new gr_edge(src, dst)); } gr_edge::~gr_edge() { } -gr_simple_flowgraph_detail::gr_simple_flowgraph_detail() : -d_components(), -d_edges() -{ -} - gr_simple_flowgraph_detail::~gr_simple_flowgraph_detail() { } @@ -64,498 +49,435 @@ gr_simple_flowgraph_detail::~gr_simple_flowgraph_detail() void gr_simple_flowgraph_detail::reset() { - // 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(); -} - -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; - } - - return std::string(""); // Not found + // Boost shared pointers will deallocate as needed + d_edges.clear(); + d_blocks.clear(); } void -gr_simple_flowgraph_detail::define_component(const std::string &name, gr_block_sptr block) +gr_simple_flowgraph_detail::connect(const gr_endpoint &src, const gr_endpoint &dst) { - 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"); + check_valid_port(src.block()->output_signature(), src.port()); + check_valid_port(dst.block()->input_signature(), dst.port()); + check_dst_not_used(dst); + check_type_match(src, dst); + d_edges.push_back(gr_make_edge(src,dst)); } void -gr_simple_flowgraph_detail::connect(const std::string &src_name, int src_port, - const std::string &dst_name, int dst_port) +gr_simple_flowgraph_detail::disconnect(const gr_endpoint &src, const gr_endpoint &dst) { - 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 (!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); + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (src.block() == (*p)->src().block() && src.port() == (*p)->src().port() && + dst.block() == (*p)->dst().block() && dst.port() == (*p)->dst().port()) { + d_edges.erase(p); + return; + } + } - d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port)); + throw std::invalid_argument("edge to disconnect not found"); } 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) +gr_simple_flowgraph_detail::check_dst_not_used(const gr_endpoint &dst) { - 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().block() == dst.block() && + (*p)->dst().port() == dst.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) +gr_simple_flowgraph_detail::check_type_match(const gr_endpoint &src, const gr_endpoint &dst) { - 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 while attempting to connect"); } 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; + d_blocks = calc_used_blocks(); - used_ports = calc_used_ports(p->first, true); // inputs - ninputs = used_ports.size(); - check_contiguity(p->second, used_ports, true); // inputs + for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + std::vector<int> used_ports; + int ninputs, noutputs; - 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, true); // inputs + ninputs = used_ports.size(); + check_contiguity(*p, used_ports, true); // inputs - if (!(p->second->check_topology(ninputs, noutputs))) - throw std::runtime_error("check topology failed"); - } + used_ports = calc_used_ports(*p, false); // outputs + noutputs = used_ports.size(); + check_contiguity(*p, used_ports, false); // outputs + + if (!((*p)->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) +gr_simple_flowgraph_detail::calc_used_ports(gr_basic_block_sptr block, bool check_inputs) { - 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()); - - 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()); - } - - // remove duplicates - std::sort(tmp.begin(), tmp.end()); - std::unique_copy(tmp.begin(), tmp.end(), inserter); + std::vector<int> tmp, result; + std::insert_iterator<std::vector<int> > inserter(result, result.begin()); - if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) - std::cout << result.size() << std::endl; + gr_edge_vector_t edges = calc_connections(block, 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()); + } - return result; + // remove duplicates + std::sort(tmp.begin(), tmp.end()); + std::unique_copy(tmp.begin(), tmp.end(), inserter); + return result; } gr_edge_vector_t -gr_simple_flowgraph_detail::calc_connections(const std::string &name, bool check_inputs) +gr_simple_flowgraph_detail::calc_connections(gr_basic_block_sptr block, bool check_inputs) { - 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); - } + 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().block() == block) + result.push_back(*p); } + else { + if ((*p)->src().block() == block) + result.push_back(*p); + } + } - return result; // assumes no duplicates + return result; // assumes no duplicates } void -gr_simple_flowgraph_detail::check_contiguity(gr_block_sptr block, +gr_simple_flowgraph_detail::check_contiguity(gr_basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs) { - 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(); - - 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"); - } - } + gr_io_signature_sptr sig = + check_inputs ? block->input_signature() : block->output_signature(); - 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; + int nports = used_ports.size(); + int min_ports = sig->min_streams(); - throw std::runtime_error("missing input assignment"); - } - } - } - - if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) - std::cout << "ok." << std::endl; + if (nports == 0) { + if (min_ports == 0) + return; + else + 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) + throw std::runtime_error("missing input assignment"); + } } 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; - - 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); - - 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); - - 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)); - } + // Assign block details to blocks + for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + int ninputs = calc_used_ports(*p, true).size(); + int noutputs = calc_used_ports(*p, 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, i)); + + boost::dynamic_pointer_cast<gr_block, gr_basic_block>(*p)->set_detail(detail); + } + + // Connect inputs to outputs for each block + for(gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + gr_block_sptr grblock(boost::dynamic_pointer_cast<gr_block, gr_basic_block>(*p)); + if (!grblock) + throw std::runtime_error("setup_connections found non-gr_block"); + + // Get its detail and edges that feed into it + gr_block_detail_sptr detail = grblock->detail(); + gr_edge_vector_t in_edges = calc_upstream_edges(*p); + + // 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_basic_block_sptr src_block = (*e)->src().block(); + gr_block_sptr src_grblock(boost::dynamic_pointer_cast<gr_block, gr_basic_block>(src_block)); + if (!grblock) + throw std::runtime_error("setup_connections found non-gr_block"); + gr_buffer_sptr src_buffer = src_grblock->detail()->output(src_port); + + detail->set_input(dst_port, gr_buffer_add_reader(src_buffer, grblock->history()-1)); } + } } gr_buffer_sptr -gr_simple_flowgraph_detail::allocate_buffer(const std::string &name, int port) +gr_simple_flowgraph_detail::allocate_buffer(gr_basic_block_sptr block, 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; - - // 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 (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); + gr_block_sptr grblock(boost::dynamic_pointer_cast<gr_block, gr_basic_block>(block)); + if (!grblock) + throw std::runtime_error("allocate_buffer found non-gr_block"); + 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*grblock->output_multiple()) // Note: this means output_multiple() + nitems = 2*grblock->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_basic_block_vector_t blocks = calc_downstream_blocks(block, port); + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + gr_block_sptr dgrblock(boost::dynamic_pointer_cast<gr_block, gr_basic_block>(*p)); + if (!dgrblock) + throw std::runtime_error("allocate_buffer found non-gr_block"); + int decimation = (int)(1.0/dgrblock->relative_rate()); + int multiple = dgrblock->output_multiple(); + int history = dgrblock->history(); + nitems = std::max(nitems, 2*(decimation*multiple+history)); + } + + 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_basic_block_vector_t +gr_simple_flowgraph_detail::calc_downstream_blocks(gr_basic_block_sptr block, int port) { - gr_block_vector_t tmp, result; - std::insert_iterator<gr_block_vector_t> inserter(result, result.begin()); + gr_basic_block_vector_t tmp, result; + std::insert_iterator<gr_basic_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().block() == block && (*p)->src().port() == port) + tmp.push_back((*p)->dst().block()); - // 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_basic_block_vector_t +gr_simple_flowgraph_detail::calc_downstream_blocks(gr_basic_block_sptr block) { - gr_block_vector_t tmp, result; - std::insert_iterator<gr_block_vector_t> inserter(result, result.begin()); + gr_basic_block_vector_t tmp, result; + std::insert_iterator<gr_basic_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().block() == block) + tmp.push_back((*p)->dst().block()); - // 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_simple_flowgraph_detail::calc_upstream_edges(gr_basic_block_sptr block) { - 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().block() == block) + result.push_back(*p); - return result; // Assume no duplicates + return result; // Assume no duplicates } -gr_block_vector_t +gr_basic_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; + gr_basic_block_vector_t tmp, result; + std::insert_iterator<gr_basic_block_vector_t> inserter(result, result.begin()); - 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); - - 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; + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + tmp.push_back((*p)->src().block()); + tmp.push_back((*p)->dst().block()); + } - return result; + sort(tmp.begin(), tmp.end()); + unique_copy(tmp.begin(), tmp.end(), inserter); + 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_basic_block_vector_t blocks = calc_used_blocks(); + gr_basic_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_basic_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_basic_block_vector_t +gr_simple_flowgraph_detail::calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) { - gr_block_vector_t result; + gr_basic_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_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + boost::dynamic_pointer_cast<gr_block, gr_basic_block>(*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_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + if ((boost::dynamic_pointer_cast<gr_block, gr_basic_block>(*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) +gr_simple_flowgraph_detail::reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) { - // Mark the current one as visited - block->detail()->set_color(gr_block_detail::BLACK); + // Mark the current one as visited + boost::dynamic_pointer_cast<gr_block, gr_basic_block>(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_basic_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_basic_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++) + if (boost::dynamic_pointer_cast<gr_block, gr_basic_block>(*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_basic_block_vector_t +gr_simple_flowgraph_detail::calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) { - gr_block_vector_t tmp, result; - std::insert_iterator<gr_block_vector_t> inserter(result, result.begin()); + gr_basic_block_vector_t tmp, result; + std::insert_iterator<gr_basic_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())); - } - - // Remove duplicates - sort(tmp.begin(), tmp.end()); - unique_copy(tmp.begin(), tmp.end(), inserter); - return result; + // Find any blocks that are inputs or outputs + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + + if ((*p)->src().block() == block) + tmp.push_back((*p)->dst().block()); + if ((*p)->dst().block() == block) + tmp.push_back((*p)->src().block()); + } + + // 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_simple_flowgraph_detail::topological_sort(gr_basic_block_vector_t &blocks) { - gr_block_vector_t result, tmp; - tmp = sort_sources_first(blocks); + gr_basic_block_vector_t tmp; + gr_block_vector_t result; + 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_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) + boost::dynamic_pointer_cast<gr_block, gr_basic_block>(*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_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) { + if (boost::dynamic_pointer_cast<gr_block, gr_basic_block>(*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) +gr_simple_flowgraph_detail::source_p(gr_basic_block_sptr block) { - return (calc_upstream_edges(lookup_name(block)).size() == 0); + return (calc_upstream_edges(block).size() == 0); } -gr_block_vector_t -gr_simple_flowgraph_detail::sort_sources_first(gr_block_vector_t &blocks) +gr_basic_block_vector_t +gr_simple_flowgraph_detail::sort_sources_first(gr_basic_block_vector_t &blocks) { - gr_block_vector_t sources, nonsources, result; + gr_basic_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_basic_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_basic_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_basic_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) +gr_simple_flowgraph_detail::topological_dfs_visit(gr_basic_block_sptr block, gr_block_vector_t &output) { - block->detail()->set_color(gr_block_detail::GREY); + boost::dynamic_pointer_cast<gr_block, gr_basic_block>(block)->detail()->set_color(gr_block_detail::GREY); - gr_block_vector_t blocks(calc_downstream_blocks(lookup_name(block))); + gr_basic_block_vector_t blocks(calc_downstream_blocks(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_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + switch (boost::dynamic_pointer_cast<gr_block, gr_basic_block>(*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); + gr_block_sptr result_block(boost::dynamic_pointer_cast<gr_block, gr_basic_block>(block)); + + result_block->detail()->set_color(gr_block_detail::BLACK); + output.push_back(result_block); +} + +void +gr_simple_flowgraph_detail::merge_connections(gr_simple_flowgraph_sptr sfg) +{ + // NOT IMPLEMENTED } diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h index 2df1575ad..6e9058bba 100644 --- a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h @@ -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 * @@ -23,48 +23,30 @@ #ifndef INCLUDED_GR_SIMPLE_FLOWGRAPH_DETAIL_H #define INCLUDED_GR_SIMPLE_FLOWGRAPH_DETAIL_H -#include <gr_block.h> -#include <map> +#include <gr_basic_block.h> +#include <gr_simple_flowgraph.h> +#include <iostream> #define GR_FIXED_BUFFER_SIZE (32*(1L<<10)) -typedef std::map<std::string, gr_block_sptr> gr_component_map_t; -typedef std::map<std::string, gr_block_sptr>::iterator gr_component_miter_t; - -class gr_endpoint -{ -private: - 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; } -}; - class gr_edge; typedef boost::shared_ptr<gr_edge> gr_edge_sptr; -gr_edge_sptr gr_make_edge(const std::string &src_name, int src_port, - const std::string &dst_name, int dst_port); +gr_edge_sptr gr_make_edge(const gr_endpoint &src, const gr_endpoint &dst); 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 gr_endpoint &src, const gr_endpoint &dst); + gr_edge(const gr_endpoint &src, const gr_endpoint &dst) : d_src(src), d_dst(dst) { } - 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(); + + const gr_endpoint &src() const { return d_src; } + const gr_endpoint &dst() const { return d_dst; } }; typedef std::vector<gr_edge_sptr> gr_edge_vector_t; @@ -73,63 +55,68 @@ typedef std::vector<gr_edge_sptr>::iterator gr_edge_viter_t; 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 gr_hier_block2_detail; + friend class topo_block_cmp; - gr_simple_flowgraph_detail(); + gr_simple_flowgraph_detail() : d_blocks(), d_edges() { } - 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_basic_block_vector_t d_blocks; + 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 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 reset(); + void connect(const gr_endpoint &src, const gr_endpoint &dst); + void disconnect(const gr_endpoint &src, const gr_endpoint &dst); + void check_valid_port(gr_io_signature_sptr sig, int port); + void check_dst_not_used(const gr_endpoint &dst); + void check_type_match(const gr_endpoint &src, const gr_endpoint &dst); + void validate(); + gr_edge_vector_t calc_connections(gr_basic_block_sptr block, bool check_inputs); // false=use outputs + std::vector<int> calc_used_ports(gr_basic_block_sptr block, bool check_inputs); + void check_contiguity(gr_basic_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(gr_basic_block_sptr block, int port); + gr_basic_block_vector_t calc_downstream_blocks(gr_basic_block_sptr block, int port); + gr_basic_block_vector_t calc_downstream_blocks(gr_basic_block_sptr block); + gr_edge_vector_t calc_upstream_edges(gr_basic_block_sptr block); + gr_basic_block_vector_t calc_used_blocks(); + std::vector<gr_block_vector_t> partition(); + gr_basic_block_vector_t calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks); + gr_block_vector_t topological_sort(gr_basic_block_vector_t &blocks); + void reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks); + gr_basic_block_vector_t calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks); + bool source_p(gr_basic_block_sptr block); + gr_basic_block_vector_t sort_sources_first(gr_basic_block_vector_t &blocks); + void topological_dfs_visit(gr_basic_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) +operator <<(std::ostream &os, const gr_endpoint endp) { - os << "<gr_block " << p->name() << " (" << p->unique_id() << ")>"; - return os; + os << endp.block()->name() << ":" << endp.port(); + return os; } inline std::ostream& -operator <<(std::ostream &os, const gr_endpoint endp) +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) { - os << endp.name() << ":" << endp.port(); - return os; + 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 */ diff --git a/gnuradio-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i index cab338630..caa2166e0 100644 --- a/gnuradio-core/src/lib/runtime/runtime.i +++ b/gnuradio-core/src/lib/runtime/runtime.i @@ -28,7 +28,6 @@ #include <gr_block_detail.h> #include <gr_hier_block2.h> #include <gr_runtime.h> -#include <gr_simple_flowgraph.h> #include <gr_single_threaded_scheduler.h> #include <gr_message.h> #include <gr_msg_handler.h> @@ -48,7 +47,6 @@ %include <gr_block_detail.i> %include <gr_hier_block2.i> %include <gr_swig_block_magic.i> -%include <gr_simple_flowgraph.i> %include <gr_single_threaded_scheduler.i> %include <gr_message.i> %include <gr_msg_handler.i> diff --git a/gnuradio-core/src/python/gnuradio/blksimpl2/d8psk.py b/gnuradio-core/src/python/gnuradio/blksimpl2/d8psk.py index b499b8fa3..2760eb77b 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl2/d8psk.py +++ b/gnuradio-core/src/python/gnuradio/blksimpl2/d8psk.py @@ -1,5 +1,5 @@ # -# Copyright 2005,2006 Free Software Foundation, Inc. +# Copyright 2005,2006,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -115,21 +115,9 @@ class d8psk_mod(gr.hier_block2): self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) - # Define components from objects - self.define_component("bytes2chunks", self.bytes2chunks) - self.define_component("symbol_mapper", self.symbol_mapper) -# self.define_component("diffenc", self.diffenc) - self.define_component("chunks2symbols", self.chunks2symbols) - self.define_component("rrc_filter", self.rrc_filter) - # Connect components - self.connect("self", 0, "bytes2chunks", 0) - self.connect("bytes2chunks", 0, "symbol_mapper", 0) -# self.connect("symbol_mapper", 0, "diffenc", 0) -# self.connect("diffenc", 0, "chunks2symbols", 0) - self.connect("symbol_mapper", 0, "chunks2symbols", 0) - self.connect("chunks2symbols", 0, "rrc_filter", 0) - self.connect("rrc_filter", 0, "self", 0) + self.connect(self, self.bytes2chunks, self.symbol_mapper, self.chunks2symbols, + self.rrc_filter, self) if verbose: self._print_verbage() @@ -153,17 +141,10 @@ class d8psk_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." - self.define_component("bytes2chunks_dat", gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) - self.define_component("symbol_mapper_dat", gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.dat")) -# self.define_component("diffenc_dat", gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) - self.define_component("chunks2symbols_dat", gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) - self.define_component("rrc_filter_dat", gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) - - self.connect("bytes2chunks", 0, "bytes2chunks_dat", 0) - self.connect("symbol_mapper", 0, "symbol_mapper_dat", 0) -# self.connect("diffenc", 0, "diffenc_dat", 0) - self.connect("chunks2symbols", 0, "chunks2symbols_dat", 0) - self.connect("rrc_filter", 0, "rrc_filter_dat", 0) + self.connect(self.bytes2chunks, gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) + self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.dat")) + self.connect(self.chunks2symbols, gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) + self.connect(self.rrc_filter, gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) def add_options(parser): """ @@ -295,27 +276,9 @@ class d8psk_demod(gr.hier_block2): self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) - # Define components - self.define_component("pre_scaler", self.pre_scaler) - self.define_component("agc", self.agc) - self.define_component("rrc_filter", self.rrc_filter) - self.define_component("receiver", self.receiver) - self.define_component("slicer", self.slicer) - #self.define_component("diffdec", self.diffdec) - self.define_component("symbol_mapper", self.symbol_mapper) - self.define_component("unpack", self.unpack) - # Connect and Initialize base class - self.connect("self", 0, "pre_scaler", 0) - self.connect("pre_scaler", 0, "agc", 0) - self.connect("agc", 0, "rrc_filter", 0) - self.connect("rrc_filter", 0, "receiver", 0) - self.connect("receiver", 0, "slicer", 0) - #self.connect("slicer", 0, "diffdec", 0) - #self.connect("diffdec", 0, "symbol_mapper", 0) - self.connect("slicer", 0, "symbol_mapper", 0) - self.connect("symbol_mapper", 0, "unpack", 0) - self.connect("unpack", 0, "self", 0) + self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver, + self.slicer, self.symbol_mapper, self.unpack, self) if verbose: self._print_verbage() @@ -347,31 +310,13 @@ class d8psk_demod(gr.hier_block2): def _setup_logging(self): print "Demodulation logging turned on." - self.define_component("prescaler_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) - self.define_component("agc_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) - self.define_component("rrc_filter_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) - self.define_component("receiver_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) - self.define_component("slicer_dat", - gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) -# self.define_component("diffdec_dat", -# gr.file_sink(gr.sizeof_char, "rx_diffdec.dat")) - self.define_component("symbol_mapper_dat", - gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) - self.define_component("unpack_dat", - gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) - - self.connect("pre_scaler", 0, "prescaler_dat", 0) - self.connect("agc", 0, "agc_dat", 0) - self.connect("rrc_filter", 0, "rrc_filter_dat", 0) - self.connect("receiver", 0, "receiver_dat", 0) - self.connect("slicer", 0, "slicer_dat", 0) -# self.connect("diffdec", 0, "diffdec_dat", 0) - self.connect("symbol_mapper", 0, "symbol_mapper_dat", 0) - self.connect("unpack", 0, "unpack_dat", 0) + self.connect(self.pre_scaler, gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) + self.connect(self.agc, gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) + self.connect(self.rrc_filter, gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) + self.connect(self.receiver, gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) + self.connect(self.slicer, gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) + self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) + self.connect(self.unpack, gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) def add_options(parser): """ diff --git a/gnuradio-core/src/python/gnuradio/blksimpl2/dbpsk.py b/gnuradio-core/src/python/gnuradio/blksimpl2/dbpsk.py index 36a2ea8af..380fa54f2 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl2/dbpsk.py +++ b/gnuradio-core/src/python/gnuradio/blksimpl2/dbpsk.py @@ -1,5 +1,5 @@ # -# Copyright 2005,2006 Free Software Foundation, Inc. +# Copyright 2005,2006,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -113,19 +113,9 @@ class dbpsk_mod(gr.hier_block2): self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) - self.define_component("bytes2chunks", self.bytes2chunks) - self.define_component("symbol_mapper", self.symbol_mapper) - self.define_component("diffenc", self.diffenc) - self.define_component("chunks2symbols", self.chunks2symbols) - self.define_component("rrc_filter", self.rrc_filter) - # Connect components - self.connect("self", 0, "bytes2chunks", 0) - self.connect("bytes2chunks", 0, "symbol_mapper", 0) - self.connect("symbol_mapper", 0, "diffenc", 0) - self.connect("diffenc", 0, "chunks2symbols", 0) - self.connect("chunks2symbols", 0, "rrc_filter", 0) - self.connect("rrc_filter", 0, "self", 0) + self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, + self.chunks2symbols, self.rrc_filter, self) if verbose: self._print_verbage() @@ -168,22 +158,11 @@ class dbpsk_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." - self.define_component("bytes2chunks_dat", - gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) - self.define_component("symbol_mapper_dat", - gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.dat")) - self.define_component("diffenc_dat", - gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) - self.define_component("chunks2symbols_dat", - gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) - self.define_component("rrc_filter_dat", - gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) - - self.connect("bytes2chunks", 0, "bytes2chunks_dat", 0) - self.connect("symbol_mapper", 0, "symbol_mapper_dat", 0) - self.connect("diffenc", 0, "diffenc_dat", 0) - self.connect("chunks2symbols", 0, "chunks2symbols_dat", 0) - self.connect("rrc_filter", 0, "rrc_filter_dat", 0) + self.connect(self.bytes2chunks, gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) + self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.dat")) + self.connect(self.diffenc, gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) + self.connect(self.chunks2symbols, gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) + self.connect(self.rrc_filter, gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) # ///////////////////////////////////////////////////////////////////////////// @@ -295,27 +274,10 @@ class dbpsk_demod(gr.hier_block2): # unpack the k bit vector into a stream of bits self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) - # Define components - self.define_component("pre_scaler", self.pre_scaler) - self.define_component("agc", self.agc) - self.define_component("rrc_filter", self.rrc_filter) - self.define_component("receiver", self.receiver) - self.define_component("slicer", self.slicer) - self.define_component("diffdec", self.diffdec) - self.define_component("symbol_mapper", self.symbol_mapper) - self.define_component("unpack", self.unpack) - # Connect and Initialize base class - self.connect("self", 0, "pre_scaler", 0) - self.connect("pre_scaler", 0, "agc", 0) - self.connect("agc", 0, "rrc_filter", 0) - self.connect("rrc_filter", 0, "receiver", 0) - self.connect("receiver", 0, "diffdec", 0) - self.connect("diffdec", 0, "slicer", 0) - self.connect("slicer", 0, "symbol_mapper", 0) - self.connect("symbol_mapper", 0, "unpack", 0) - self.connect("unpack", 0, "self", 0) - + self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver, + self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self) + if verbose: self._print_verbage() @@ -344,32 +306,14 @@ class dbpsk_demod(gr.hier_block2): def _setup_logging(self): print "Demodulation logging turned on." - self.define_component("prescaler_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) - self.define_component("agc_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) - self.define_component("rrc_filter_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) - self.define_component("receiver_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) - self.define_component("diffdec_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) - self.define_component("slicer_dat", - gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) - self.define_component("symbol_mapper_dat", - gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) - self.define_component("unpack_dat", - gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) - - self.connect("pre_scaler", 0, "prescaler_dat", 0) - self.connect("agc", 0, "agc_dat", 0) - self.connect("rrc_filter", 0, "rrc_filter_dat", 0) - self.connect("receiver", 0, "receiver_dat", 0) - self.connect("diffdec", 0, "diffdec_dat", 0) - self.connect("slicer", 0, "slicer_dat", 0) - self.connect("symbol_mapper", 0, "symbol_mapper_dat", 0) - self.connect("unpack", 0, "unpack_dat", 0) - + self.connect(self.pre_scaler, gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) + self.connect(self.agc, gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) + self.connect(self.rrc_filter, gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) + self.connect(self.receiver, gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) + self.connect(self.diffdec, gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) + self.connect(self.slicer, gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) + self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) + self.connect(self.unpack, gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) def add_options(parser): """ diff --git a/gnuradio-core/src/python/gnuradio/blksimpl2/dqpsk.py b/gnuradio-core/src/python/gnuradio/blksimpl2/dqpsk.py index 04623c93e..e9fc2092d 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl2/dqpsk.py +++ b/gnuradio-core/src/python/gnuradio/blksimpl2/dqpsk.py @@ -1,5 +1,5 @@ # -# Copyright 2005,2006 Free Software Foundation, Inc. +# Copyright 2005,2006,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -114,20 +114,9 @@ class dqpsk_mod(gr.hier_block2): self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol, self.rrc_taps) - # Define components from objects - self.define_component("bytes2chunks", self.bytes2chunks) - self.define_component("symbol_mapper", self.symbol_mapper) - self.define_component("diffenc", self.diffenc) - self.define_component("chunks2symbols", self.chunks2symbols) - self.define_component("rrc_filter", self.rrc_filter) - # Connect components - self.connect("self", 0, "bytes2chunks", 0) - self.connect("bytes2chunks", 0, "symbol_mapper", 0) - self.connect("symbol_mapper", 0, "diffenc", 0) - self.connect("diffenc", 0, "chunks2symbols", 0) - self.connect("chunks2symbols", 0, "rrc_filter", 0) - self.connect("rrc_filter", 0, "self", 0) + self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc, + self.chunks2symbols, self.rrc_filter, self) if verbose: self._print_verbage() @@ -150,17 +139,11 @@ class dqpsk_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." - self.define_component("bytes2chunks_dat", gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) - self.define_component("symbol_mapper_dat", gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.dat")) - self.define_component("diffenc_dat", gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) - self.define_component("chunks2symbols_dat", gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) - self.define_component("rrc_filter_dat", gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) - - self.connect("bytes2chunks", 0, "bytes2chunks_dat", 0) - self.connect("symbol_mapper", 0, "symbol_mapper_dat", 0) - self.connect("diffenc", 0, "diffenc_dat", 0) - self.connect("chunks2symbols", 0, "chunks2symbols_dat", 0) - self.connect("rrc_filter", 0, "rrc_filter_dat", 0) + self.connect(self.bytes2chunks, gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.dat")) + self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.dat")) + self.connect(self.diffenc, gr.file_sink(gr.sizeof_char, "tx_diffenc.dat")) + self.connect(self.chunks2symbols, gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.dat")) + self.connect(self.rrc_filter, gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.dat")) def add_options(parser): """ @@ -288,27 +271,10 @@ class dqpsk_demod(gr.hier_block2): # unpack the k bit vector into a stream of bits self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) - - # Define components - self.define_component("pre_scaler", self.pre_scaler) - self.define_component("agc", self.agc) - self.define_component("rrc_filter", self.rrc_filter) - self.define_component("receiver", self.receiver) - self.define_component("diffdec", self.diffdec) - self.define_component("slicer", self.slicer) - self.define_component("symbol_mapper", self.symbol_mapper) - self.define_component("unpack", self.unpack) # Connect and Initialize base class - self.connect("self", 0, "pre_scaler", 0) - self.connect("pre_scaler", 0, "agc", 0) - self.connect("agc", 0, "rrc_filter", 0) - self.connect("rrc_filter", 0, "receiver", 0) - self.connect("receiver", 0, "diffdec", 0) - self.connect("diffdec", 0, "slicer", 0) - self.connect("slicer", 0, "symbol_mapper", 0) - self.connect("symbol_mapper", 0, "unpack", 0) - self.connect("unpack", 0, "self", 0) + self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver, self.diffdec, + self.slicer, self.symbol_mapper, self.unpack, self) if verbose: self._print_verbage() @@ -338,31 +304,14 @@ class dqpsk_demod(gr.hier_block2): def _setup_logging(self): print "Demodulation logging turned on." - self.define_component("prescaler_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) - self.define_component("agc_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) - self.define_component("rrc_filter_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) - self.define_component("receiver_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) - self.define_component("diffdec_dat", - gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) - self.define_component("slicer_dat", - gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) - self.define_component("symbol_mapper_dat", - gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) - self.define_component("unpack_dat", - gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) - - self.connect("pre_scaler", 0, "prescaler_dat", 0) - self.connect("agc", 0, "agc_dat", 0) - self.connect("rrc_filter", 0, "rrc_filter_dat", 0) - self.connect("receiver", 0, "receiver_dat", 0) - self.connect("diffdec", 0, "diffdec_dat", 0) - self.connect("slicer", 0, "slicer_dat", 0) - self.connect("symbol_mapper", 0, "symbol_mapper_dat", 0) - self.connect("unpack", 0, "unpack_dat", 0) + self.connect(self.pre_scaler, gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat")) + self.connect(self.agc, gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat")) + self.connect(self.rrc_filter, gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat")) + self.connect(self.receiver, gr.file_sink(gr.sizeof_gr_complex, "rx_receiver.dat")) + self.connect(self.diffdec, gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat")) + self.connect(self.slicer, gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) + self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat")) + self.connect(self.unpack, gr.file_sink(gr.sizeof_char, "rx_unpack.dat")) def add_options(parser): """ diff --git a/gnuradio-core/src/python/gnuradio/blksimpl2/gmsk.py b/gnuradio-core/src/python/gnuradio/blksimpl2/gmsk.py index e852b3c11..bc601e679 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl2/gmsk.py +++ b/gnuradio-core/src/python/gnuradio/blksimpl2/gmsk.py @@ -2,7 +2,7 @@ # GMSK modulation and demodulation. # # -# Copyright 2005,2006 Free Software Foundation, Inc. +# Copyright 2005,2006,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -103,16 +103,8 @@ class gmsk_mod(gr.hier_block2): # FM modulation self.fmmod = gr.frequency_modulator_fc(sensitivity) - # Define components from objects - self.define_component("nrz", self.nrz) - self.define_component("gaussian_filter", self.gaussian_filter) - self.define_component("fmmod", self.fmmod) - # Connect components - self.connect("self", 0, "nrz", 0) - self.connect("nrz", 0, "gaussian_filter", 0) - self.connect("gaussian_filter", 0, "fmmod", 0) - self.connect("fmmod", 0, "self", 0) + self.connect(self, self.nrz, self.gaussian_filter, self.fmmod, self) if verbose: self._print_verbage() @@ -135,13 +127,9 @@ class gmsk_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." - self.define_component("nrz_dat", gr.file_sink(gr.sizeof_float, "tx_nrz.dat")) - self.define_component("gaussian_filter_dat", gr.file_sink(gr.sizeof_float, "tx_gaussian_filter.dat")) - self.define_component("fmmod_dat", gr.file_sink(gr.sizeof_gr_complex, "tx_fmmod.dat")) - - self.connect("nrz", 0, "nrz_dat", 0) - self.connect("gaussian_filter", 0, "gaussian_filter_dat", 0) - self.connect("fmmod", 0, "fmmod_dat", 0) + self.connect(self.nrz, gr.file_sink(gr.sizeof_float, "tx_nrz.dat")) + self.connect(self.gaussian_filter, gr.file_sink(gr.sizeof_float, "tx_gaussian_filter.dat")) + self.connect(self.fmmod, gr.file_sink(gr.sizeof_gr_complex, "tx_fmmod.dat")) def add_options(parser): """ @@ -232,16 +220,8 @@ class gmsk_demod(gr.hier_block2): # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample self.slicer = gr.binary_slicer_fb() - # Define components from objects - self.define_component("fmdemod", self.fmdemod) - self.define_component("clock_recovery", self.clock_recovery) - self.define_component("slicer", self.slicer) - # Connect components - self.connect("self", 0, "fmdemod", 0) - self.connect("fmdemod", 0, "clock_recovery", 0) - self.connect("clock_recovery", 0, "slicer", 0) - self.connect("slicer", 0, "self", 0) + self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self) if verbose: self._print_verbage() @@ -267,13 +247,9 @@ class gmsk_demod(gr.hier_block2): def _setup_logging(self): print "Demodulation logging turned on." - self.define_component("fmdemod_dat", gr.file_sink(gr.sizeof_float, "rx_fmdemod.dat")) - self.define_component("clock_recovery_dat", gr.file_sink(gr.sizeof_float, "rx_clock_recovery.dat")) - self.define_component("slicer_dat", gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) - - self.connect("fmdemod", 0, "fmdemod_dat", 0) - self.connect("clock_recovery", 0, "clock_recovery_dat", 0) - self.connect("slicer", 0, "slicer_dat", 0) + self.connect(self.fmdemod, gr.file_sink(gr.sizeof_float, "rx_fmdemod.dat")) + self.connect(self.clock_recovery, gr.file_sink(gr.sizeof_float, "rx_clock_recovery.dat")) + self.connect(self.slicer, gr.file_sink(gr.sizeof_char, "rx_slicer.dat")) def add_options(parser): """ diff --git a/gnuradio-core/src/python/gnuradio/blksimpl2/pkt.py b/gnuradio-core/src/python/gnuradio/blksimpl2/pkt.py index 1e1dae17a..c94c27338 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl2/pkt.py +++ b/gnuradio-core/src/python/gnuradio/blksimpl2/pkt.py @@ -1,5 +1,5 @@ # -# Copyright 2005,2006 Free Software Foundation, Inc. +# Copyright 2005,2006,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -67,11 +67,7 @@ class mod_pkts(gr.hier_block2): # accepts messages from the outside world self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit) - self.define_component("packet_source", self._pkt_input) - self.define_component("modulator", self._modulator) - - self.connect("packet_source", 0, "modulator", 0) - self.connect("modulator", 0, "self", 0) + self.connect(self._pkt_input, self._modulator, self) def send_pkt(self, payload='', eof=False): """ @@ -136,13 +132,9 @@ class demod_pkts(gr.hier_block2): self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY - self.define_component("demodulator", self._demodulator) - self.define_component("correlator", gr.correlate_access_code_bb(access_code, threshold)) - self.define_component("framer_sink", gr.framer_sink_1(self._rcvd_pktq)) - - self.connect("self", 0, "demodulator",0) - self.connect("demodulator", 0, "correlator", 0) - self.connect("correlator", 0, "framer_sink", 0) + self._correlator = gr.correlate_access_code_bb(access_code, threshold) + self._framer_sink = gr.framer_sink_1(self._rcvd_pktq) + self.connect(self, self._demodulator, self._correlator, self._framer_sink) self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) diff --git a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py index 5877401b5..4abe9d14f 100644 --- a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py +++ b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py @@ -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, io_signature # # This hack forces a 'has-a' relationship to look like an 'is-a' one. @@ -38,9 +38,55 @@ class hier_block2(object): def __getattr__(self, name): return getattr(self._hb, name) - def define_component(self, name, comp): - return self._hb.define_component(name, comp.basic_block()) + def connect(self, *points): + '''connect requires two or more arguments that can be coerced to endpoints. + If more than two arguments are provided, they are connected together successively. + ''' + if len (points) < 2: + raise ValueError, ("connect requires at least two endpoints; %d provided." % (len (points),)) + for i in range (1, len (points)): + self._connect(points[i-1], points[i]) + def _connect(self, src, dst): + (src_block, src_port) = self._coerce_endpoint(src) + (dst_block, dst_port) = self._coerce_endpoint(dst) + self._hb.connect(src_block.basic_block(), src_port, + dst_block.basic_block(), dst_port) + + def _coerce_endpoint(self, endp): + if hasattr(endp, 'basic_block'): + return (endp, 0) + else: + if hasattr(endp, "__getitem__") and len(endp) == 2: + return endp # Assume user put (block, port) + else: + raise ValueError("unable to coerce endpoint") + + def disconnect(self, *points): + '''connect requires two or more arguments that can be coerced to endpoints. + If more than two arguments are provided, they are disconnected successively. + ''' + if len (points) < 2: + raise ValueError, ("disconnect requires at least two endpoints; %d provided." % (len (points),)) + for i in range (1, len (points)): + self._disconnect(points[i-1], points[i]) + + def _disconnect(self, src, dst): + (src_block, src_port) = self._coerce_endpoint(src) + (dst_block, dst_port) = self._coerce_endpoint(dst) + self._hb.disconnect(src_block.basic_block(), src_port, + dst_block.basic_block(), dst_port) + +# Convenience class to create a no input, no output block for runtime top block +class top_block(hier_block2): + def __init__(self, name): + hier_block2.__init__(self, name, io_signature(0,0,0), io_signature(0,0,0)) + +# 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 +# +# This probably should be elsewhere but it works here class runtime(object): def __init__(self, top_block): if (isinstance(top_block, hier_block2)): @@ -59,3 +105,6 @@ class runtime(object): def wait(self): runtime_wait_unlocked(self._r) + + def restart(self): + runtime_restart_unlocked(self._r) diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py b/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py index 9253b892a..98691cfb5 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py @@ -6,10 +6,10 @@ class test_hier_block2(gr_unittest.TestCase): 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), @@ -20,219 +20,155 @@ class test_hier_block2(gr_unittest.TestCase): self.assertEqual(1, hblock.output_signature().max_streams()) self.assertEqual(gr.sizeof_int, hblock.output_signature().sizeof_stream_item(0)) - def test_002_define_component(self): + def test_001_connect_internal(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)) - hblock.define_component("dst", gr.null_sink(gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, nop2) - def test_003_define_component_reserved_input(self): + def test_002_connect_input(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("self", gr.nop(gr.sizeof_int))) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) - def test_004_define_component_name_in_use(self): + def test_002a_connect_input_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))) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) + self.assertRaises(ValueError, + lambda: hblock.connect(hblock, nop2)) - def test_006_connect_internal(self): + def test_003_connect_output(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("nop1", gr.nop(gr.sizeof_int)) - hblock.define_component("nop2", gr.nop(gr.sizeof_int)) - hblock.connect("nop1", 0, "nop2", 0) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) - def test_007_connect_input(self): + def test_003a_connect_output_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("nop1", gr.nop(gr.sizeof_int)) - hblock.connect("self", 0, "nop1", 0) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) + self.assertRaises(ValueError, + lambda: hblock.connect(nop2, hblock)) - def test_008_connect_output(self): + def test_004_connect_invalid_src_port_neg(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("nop1", gr.nop(gr.sizeof_int)) - hblock.connect("nop1", 0, "self", 0) + nop1 = gr.nop(gr.sizeof_int) + self.assertRaises(ValueError, + lambda: hblock.connect((hblock, -1), nop1)) - def test_009_connect_unknown_src(self): + def test_005_connect_invalid_src_port_exceeds(self): hblock = gr.hier_block2("test_block", gr.io_signature(1,1,gr.sizeof_int), gr.io_signature(1,1,gr.sizeof_int)) nop1 = gr.nop(gr.sizeof_int) - hblock.define_component("nop1", nop1) self.assertRaises(ValueError, - lambda: hblock.connect("nop2", 0, "self", 0)) - - def test_010_connect_unknown_dst(self): + lambda: hblock.connect((hblock, 1), nop1)) + + def test_006_connect_invalid_dst_port_neg(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("nop1", gr.nop(gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) self.assertRaises(ValueError, - lambda: hblock.connect("self", 0, "nop2", 0)) + lambda: hblock.connect(nop1, (nop2, -1))) - def test_011_connect_invalid_src_port_neg(self): + def test_007_connect_invalid_dst_port_exceeds(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("nop1", gr.nop(gr.sizeof_int)) + nop1 = gr.null_sink(gr.sizeof_int) + nop2 = gr.null_sink(gr.sizeof_int) self.assertRaises(ValueError, - lambda: hblock.connect("self", -1, "nop1", 0)) + lambda: hblock.connect(nop1, (nop2, 1))) - def test_012_connect_invalid_src_port_exceeds(self): + def test_008_connect_dst_port_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("nop1", gr.nop(gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, nop2); 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), - gr.io_signature(1,1,gr.sizeof_int)) - hblock.define_component("nop1", gr.nop(gr.sizeof_int)) + lambda: hblock.connect(nop1, nop2)) + + def test_009_connect_one_src_two_dst(self): + hblock = gr.top_block("test_block") + src = gr.null_source(gr.sizeof_int) + dst1 = gr.null_sink(gr.sizeof_int) + dst2 = gr.null_sink(gr.sizeof_int) + hblock.connect(src, dst1) + hblock.connect(src, dst2) + + def test_010_connect_type_mismatch(self): + hblock = gr.top_block("test_block") + nop1 = gr.nop(gr.sizeof_char) + nop2 = gr.nop(gr.sizeof_int) self.assertRaises(ValueError, - lambda: hblock.connect("self", -1, "nop1", 0)) + lambda: hblock.connect(nop1, nop2)) - def test_014_connect_invalid_dst_port_exceeds(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("nop1", gr.nop(gr.sizeof_int)) - self.assertRaises(ValueError, - lambda: hblock.connect("self", 1, "nop1", 0)) + def test_011_check_topology(self): + hblock = gr.top_block("test_block") + hblock.check_topology(0, 0) - def test_015_connect_dst_port_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)) + def test_012_disconnect(self): + hblock = gr.top_block("test_block") nop1 = gr.nop(gr.sizeof_int) - hblock.define_component("nop1", nop1) - 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), - gr.io_signature(1,1,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) + nop2 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, nop2) + hblock.disconnect(nop1, nop2) - def test_017_connect_type_mismatch(self): + def test_013_disconnect_not_connected(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("nop1", gr.nop(gr.sizeof_char)) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) + nop3 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, nop2) self.assertRaises(ValueError, - lambda: hblock.connect("nop1", 0, "self", 0)) - - def test_018_check_topology(self): - hblock = gr.hier_block2("test_block", - 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() + lambda: hblock.disconnect(nop1, nop3)) + + def test_014_run(self): + expected = (1.0, 2.0, 3.0, 4.0) + hblock = gr.top_block("test_block") + src = gr.vector_source_f(expected, False) + sink1 = gr.vector_sink_f() + sink2 = gr.vector_sink_f() + hblock.connect(src, sink1) + hblock.connect(src, sink2) + runtime = gr.runtime(hblock) + runtime.run() + actual1 = sink1.data() + actual2 = sink2.data() + self.assertEquals(expected, actual1) + self.assertEquals(expected, actual2) + + def test_015_connect_disconnect(self): + expected = (1.0, 2.0, 3.0, 4.0) + hblock = gr.top_block("test_block") + src = gr.vector_source_f(expected, False) + sink1 = gr.vector_sink_f() + sink2 = gr.vector_sink_f() + hblock.connect(src, sink1) + hblock.connect(src, sink2) + hblock.disconnect(src, sink2) + runtime = gr.runtime(hblock) + runtime.run() - 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): - 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() - - def test_022_validate_3(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", 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)) - """ - if __name__ == "__main__": gr_unittest.main() diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_simple_flowgraph.py b/gnuradio-core/src/python/gnuradio/gr/qa_simple_flowgraph.py deleted file mode 100755 index 939f5855f..000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_simple_flowgraph.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest - -class test_simple_flowgraph(gr_unittest.TestCase): - - def setUp(self): - pass - - def tearDown(self): - pass - - def test_001_define_component(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) - - def test_002_define_component_name_in_use(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - self.assertRaises(ValueError, - lambda: sfg.define_component("src", gr.null_sink(gr.sizeof_int))) - - def test_003_connect(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) - sfg.connect("src", 0, "dst", 0) - - def test_004connect_unknown_src(self): - sfg = gr.simple_flowgraph() - sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) - self.assertRaises(ValueError, - lambda: sfg.connect("src", 0, "dst", 0)) - - def test_005_connect_unknown_dst(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - self.assertRaises(ValueError, - lambda: sfg.connect("src", 0, "dst", 0)) - - def test_006_connect_invalid_src_port_neg(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) - self.assertRaises(ValueError, - lambda: sfg.connect("src", -1, "dst", 0)) - - def test_007_connect_invalid_src_port_exceeds(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) - self.assertRaises(ValueError, - lambda: sfg.connect("src", 1, "dst", 0)) - - def test_008_connect_invalid_dst_port_neg(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) - self.assertRaises(ValueError, - lambda: sfg.connect("src", 0, "dst", -1)) - - def test_009_connect_invalid_dst_port_exceeds(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) - self.assertRaises(ValueError, - lambda: sfg.connect("src", 0, "dst", 1)) - - def test_010_connect_invalid_dst_port_in_use(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src1", gr.null_source(gr.sizeof_int)) - sfg.define_component("src2", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst", gr.null_sink(gr.sizeof_int)) - sfg.connect("src1", 0, "dst", 0) - self.assertRaises(ValueError, - lambda: sfg.connect("src2", 0, "dst", 0)) - - def test_011_connect_one_src_two_dst(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst1", gr.null_sink(gr.sizeof_int)) - sfg.define_component("dst2", gr.null_sink(gr.sizeof_int)) - sfg.connect("src", 0, "dst1", 0) - sfg.connect("src", 0, "dst2", 0) - - def test_012_connect_type_mismatch(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst", gr.null_sink(gr.sizeof_char)) - self.assertRaises(ValueError, - lambda: sfg.connect("src", 0, "dst", 0)) - - def test_013_validate(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src", gr.null_source(gr.sizeof_int)) - sfg.define_component("dst1", gr.null_sink(gr.sizeof_int)) - sfg.define_component("dst2", gr.null_sink(gr.sizeof_int)) - sfg.connect("src", 0, "dst1", 0) - sfg.connect("src", 0, "dst2", 0) - sfg.validate() - - def test_014_validate(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src1", gr.null_source (gr.sizeof_int)) - sfg.define_component("nop1", gr.nop (gr.sizeof_int)) - sfg.define_component("dst1", gr.null_sink (gr.sizeof_int)) - sfg.define_component("dst2", gr.null_sink (gr.sizeof_int)) - sfg.connect("src1", 0, "nop1", 0) - sfg.connect("src1", 0, "nop1", 1) - sfg.connect("nop1", 0, "dst1", 0) - sfg.connect("nop1", 1, "dst2", 0) - sfg.validate () - - def test_015_validate(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src1", gr.null_source (gr.sizeof_int)) - sfg.define_component("nop1", gr.nop (gr.sizeof_int)) - sfg.define_component("dst1", gr.null_sink (gr.sizeof_int)) - sfg.define_component("dst2", gr.null_sink (gr.sizeof_int)) - sfg.connect("src1", 0, "nop1", 0) - sfg.connect("src1", 0, "nop1", 2) - sfg.connect("nop1", 0, "dst1", 0) - sfg.connect("nop1", 1, "dst2", 0) - self.assertRaises(RuntimeError, - lambda: sfg.validate ()) - - def test_016_validate(self): - sfg = gr.simple_flowgraph() - sfg.define_component("src1", gr.null_source (gr.sizeof_int)) - sfg.define_component("nop1", gr.nop (gr.sizeof_int)) - sfg.define_component("dst1", gr.null_sink (gr.sizeof_int)) - sfg.define_component("dst2", gr.null_sink (gr.sizeof_int)) - sfg.connect("src1", 0, "nop1", 0) - sfg.connect("src1", 0, "nop1", 1) - sfg.connect("nop1", 0, "dst1", 0) - sfg.connect("nop1", 2, "dst2", 0) - self.assertRaises(RuntimeError, - lambda: sfg.validate ()) - -if __name__ == "__main__": - gr_unittest.main() |