diff options
Diffstat (limited to 'gnuradio-core/src/lib')
17 files changed, 750 insertions, 810 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> |