diff options
author | jcorgan | 2006-12-12 20:00:39 +0000 |
---|---|---|
committer | jcorgan | 2006-12-12 20:00:39 +0000 |
commit | 76ed4c2fea5f59bfe02bbbb17754ef7eda44feca (patch) | |
tree | c30952925ea02e52f137e1e7f4da658629994936 /gnuradio-core/src/lib | |
parent | 5de36fac220305307d6fb64eabe6f417a26c0982 (diff) | |
download | gnuradio-76ed4c2fea5f59bfe02bbbb17754ef7eda44feca.tar.gz gnuradio-76ed4c2fea5f59bfe02bbbb17754ef7eda44feca.tar.bz2 gnuradio-76ed4c2fea5f59bfe02bbbb17754ef7eda44feca.zip |
Merge jcorgan/hier developer branch into trunk. Enables creation of true hierarchical blocks, from either C++ or Python, as well as creating pure C++ gnuradio applications. EXPERIMENTAL.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@4070 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gnuradio-core/src/lib')
30 files changed, 1992 insertions, 100 deletions
diff --git a/gnuradio-core/src/lib/runtime/Makefile.am b/gnuradio-core/src/lib/runtime/Makefile.am index 2c1ea7eff..47ae07a6b 100644 --- a/gnuradio-core/src/lib/runtime/Makefile.am +++ b/gnuradio-core/src/lib/runtime/Makefile.am @@ -30,8 +30,13 @@ libruntime_la_LIBADD = \ libruntime_la_SOURCES = \ + gr_basic_block.cc \ + gr_simple_flowgraph.cc \ + gr_simple_flowgraph_detail.cc \ gr_block.cc \ gr_block_detail.cc \ + gr_hier_block2.cc \ + gr_hier_block2_detail.cc \ gr_buffer.cc \ gr_dispatcher.cc \ gr_error_handler.cc \ @@ -43,6 +48,8 @@ libruntime_la_SOURCES = \ gr_pagesize.cc \ gr_preferences.cc \ gr_realtime.cc \ + gr_runtime.cc \ + gr_runtime_impl.cc \ gr_single_threaded_scheduler.cc \ gr_tmp_path.cc \ gr_vmcircbuf.cc \ @@ -54,14 +61,20 @@ libruntime_la_SOURCES = \ libruntime_qa_la_SOURCES = \ qa_gr_block.cc \ + qa_gr_hier_block2.cc \ qa_gr_buffer.cc \ qa_gr_io_signature.cc \ qa_gr_vmcircbuf.cc \ qa_runtime.cc grinclude_HEADERS = \ + gr_basic_block.h \ + gr_simple_flowgraph.h \ + gr_simple_flowgraph_detail.h \ gr_block.h \ gr_block_detail.h \ + gr_hier_block2.h \ + gr_hier_block2_detail.h \ gr_buffer.h \ gr_complex.h \ gr_dispatcher.h \ @@ -74,6 +87,8 @@ grinclude_HEADERS = \ gr_pagesize.h \ gr_preferences.h \ gr_realtime.h \ + gr_runtime.h \ + gr_runtime_impl.h \ gr_runtime_types.h \ gr_select_handler.h \ gr_single_threaded_scheduler.h \ @@ -88,14 +103,17 @@ noinst_HEADERS = \ gr_vmcircbuf_sysv_shm.h \ gr_vmcircbuf_createfilemapping.h \ qa_gr_block.h \ + qa_gr_hier_block2.h \ qa_gr_buffer.h \ qa_gr_io_signature.h \ qa_gr_vmcircbuf.h \ qa_runtime.h swiginclude_HEADERS = \ + gr_basic_block.i \ gr_block.i \ gr_block_detail.i \ + gr_hier_block2.i \ gr_buffer.i \ gr_dispatcher.i \ gr_error_handler.i \ @@ -104,6 +122,8 @@ swiginclude_HEADERS = \ gr_msg_handler.i \ gr_msg_queue.i \ gr_realtime.i \ + gr_runtime.i \ + gr_simple_flowgraph.i \ gr_single_threaded_scheduler.i \ gr_swig_block_magic.i \ runtime.i diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc new file mode 100644 index 000000000..a5f1a4f83 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -0,0 +1,59 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_basic_block.h> +#include <stdexcept> + +static long s_next_id = 0; +static long s_ncurrently_allocated = 0; + +long +gr_basic_block_ncurrently_allocated() +{ + return s_ncurrently_allocated; +} + +gr_basic_block::gr_basic_block(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + : d_name(name), + d_input_signature(input_signature), + d_output_signature(output_signature), + d_unique_id(s_next_id++) +{ + s_ncurrently_allocated++; +} + +gr_basic_block::~gr_basic_block() +{ + s_ncurrently_allocated--; +} + +gr_basic_block_sptr +gr_basic_block::basic_block() +{ + return shared_from_this(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h new file mode 100644 index 000000000..583c3241d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -0,0 +1,99 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_BASIC_BLOCK_H +#define INCLUDED_GR_BASIC_BLOCK_H + +#include <gr_runtime_types.h> +#include <boost/enable_shared_from_this.hpp> +#include <string> + +/*! + * \brief The abstract base class for all signal processing blocks. + * \ingroup block + * + * Basic blocks are the bare abstraction of an entity that has a name + * and a set of inputs and outputs. These are never instantiated + * directly; rather, this is the abstract parent class of both gr_hier_block, + * which is a recursive container, and gr_block, which implements actual + * signal processing functions. + */ + +class gr_basic_block : public boost::enable_shared_from_this<gr_basic_block> +{ +protected: + std::string d_name; + gr_io_signature_sptr d_input_signature; + gr_io_signature_sptr d_output_signature; + long d_unique_id; + + //! Protected constructor prevents instantiation by non-derived classes + gr_basic_block(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + //! may only be called during constructor + void set_input_signature(gr_io_signature_sptr iosig) { + d_input_signature = iosig; + } + + //! may only be called during constructor + void set_output_signature(gr_io_signature_sptr iosig) { + d_output_signature = iosig; + } + +public: + virtual ~gr_basic_block(); + long unique_id() const { return d_unique_id; } + std::string name() const { return d_name; } + gr_io_signature_sptr input_signature() const { return d_input_signature; } + gr_io_signature_sptr output_signature() const { return d_output_signature; } + gr_basic_block_sptr basic_block(); // Needed for Python type coercion + + /*! + * \brief Confirm that ninputs and noutputs is an acceptable combination. + * + * \param ninputs number of input streams connected + * \param noutputs number of output streams connected + * + * \returns true if this is a valid configuration for this block. + * + * This function is called by the runtime system whenever the + * topology changes. Most classes do not need to override this. + * This check is in addition to the constraints specified by the input + * and output gr_io_signatures. + */ + virtual bool check_topology(int ninputs, int noutputs) { return true; } +}; + +typedef std::vector<gr_basic_block_sptr> gr_basic_block_vector_t; +typedef std::vector<gr_basic_block_sptr>::iterator gr_basic_block_viter_t; + +long gr_basic_block_ncurrently_allocated(); + +inline std::ostream &operator << (std::ostream &os, gr_basic_block_sptr basic_block) +{ + os << basic_block->name() << "(" << basic_block->unique_id() << ")"; + return os; +} + +#endif /* INCLUDED_GR_BASIC_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i new file mode 100644 index 000000000..33b895d43 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i @@ -0,0 +1,52 @@ +/* -*- 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_basic_block; +typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr; +%template(gr_basic_block_sptr) boost::shared_ptr<gr_basic_block>; + +// support vectors of these... +namespace std { + %template(x_vector_gr_basic_block_sptr) vector<gr_basic_block_sptr>; +}; + +class gr_basic_block +{ +protected: + gr_basic_block(); + +public: + virtual ~gr_basic_block(); + std::string name() const; + gr_io_signature_sptr input_signature() const; + gr_io_signature_sptr output_signature() const; + long unique_id() const; + gr_basic_block_sptr basic_block(); + bool check_topology (int ninputs, int noutputs); +}; + +%rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated; +long gr_basic_block_ncurrently_allocated(); + +%pythoncode %{ +gr_basic_block_sptr.__repr__ = lambda self: "<gr_basic_block %s (%d)>" % (self.name(), self.unique_id ()) +%} diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc index 65e16045a..1b1d35756 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -27,34 +27,21 @@ #include <gr_block.h> #include <gr_block_detail.h> #include <stdexcept> - -static long s_next_id = 0; -static long s_ncurrently_allocated = 0; - -long -gr_block_ncurrently_allocated () -{ - return s_ncurrently_allocated; -} +#include <iostream> gr_block::gr_block (const std::string &name, gr_io_signature_sptr input_signature, gr_io_signature_sptr output_signature) - : d_name (name), - d_input_signature (input_signature), - d_output_signature (output_signature), + : gr_basic_block(name, input_signature, output_signature), d_output_multiple (1), d_relative_rate (1.0), - d_unique_id (s_next_id++), d_history(1), d_fixed_rate(false) { - s_ncurrently_allocated++; } gr_block::~gr_block () { - s_ncurrently_allocated--; } // stub implementation: 1:1 @@ -70,12 +57,6 @@ gr_block::forecast (int noutput_items, gr_vector_int &ninput_items_required) // default implementation bool -gr_block::check_topology (int ninputs, int noutputs) -{ - return true; -} - -bool gr_block::start() { return true; diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h index 9723be108..247238bb0 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.h +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -23,13 +23,17 @@ #ifndef INCLUDED_GR_BLOCK_H #define INCLUDED_GR_BLOCK_H -#include <gr_runtime_types.h> -#include <string> +#include <gr_basic_block.h> /*! - * \brief The abstract base class for all signal processing blocks. + * \brief The abstract base class for all 'terminal' processing blocks. * \ingroup block * + * A signal processing flow is constructed by creating a tree of + * hierarchical blocks, which at any level may also contain terminal nodes + * that actually implement signal processing functions. This is the base + * class for all such leaf nodes. + * Blocks have a set of input streams and output streams. The * input_signature and output_signature define the number of input * streams and output streams respectively, and the type of the data @@ -49,16 +53,11 @@ * It reads the input items and writes the output items. */ -class gr_block { +class gr_block : public gr_basic_block { public: virtual ~gr_block (); - - std::string name () const { return d_name; } - gr_io_signature_sptr input_signature () const { return d_input_signature; } - gr_io_signature_sptr output_signature () const { return d_output_signature; } - long unique_id () const { return d_unique_id; } /*! * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...) @@ -114,21 +113,6 @@ class gr_block { gr_vector_void_star &output_items) = 0; /*! - * \brief Confirm that ninputs and noutputs is an acceptable combination. - * - * \param ninputs number of input streams connected - * \param noutputs number of output streams connected - * - * \returns true if this is a valid configuration for this block. - * - * This function is called by the runtime system whenever the - * topology changes. Most classes do not need to override this. - * This check is in addition to the constraints specified by the input - * and output gr_io_signatures. - */ - virtual bool check_topology (int ninputs, int noutputs); - - /*! * \brief Called to enable drivers, etc for i/o devices. * * This allows a block to enable an associated driver to begin @@ -205,32 +189,17 @@ class gr_block { private: - std::string d_name; - gr_io_signature_sptr d_input_signature; - gr_io_signature_sptr d_output_signature; - int d_output_multiple; - double d_relative_rate; // approx output_rate / input_rate - gr_block_detail_sptr d_detail; // implementation details - long d_unique_id; // convenient for debugging - unsigned d_history; - bool d_fixed_rate; - - + int d_output_multiple; + double d_relative_rate; // approx output_rate / input_rate + gr_block_detail_sptr d_detail; // implementation details + unsigned d_history; + bool d_fixed_rate; + protected: gr_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - - //! may only be called during constructor - void set_input_signature (gr_io_signature_sptr iosig){ - d_input_signature = iosig; - } - - //! may only be called during constructor - void set_output_signature (gr_io_signature_sptr iosig){ - d_output_signature = iosig; - } + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; } @@ -242,6 +211,7 @@ class gr_block { void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } }; -long gr_block_ncurrently_allocated (); +typedef std::vector<gr_block_sptr> gr_block_vector_t; +typedef std::vector<gr_block_sptr>::iterator gr_block_viter_t; #endif /* INCLUDED_GR_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i index 3bfd24367..5d0f5fb1b 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.i +++ b/gnuradio-core/src/lib/runtime/gr_block.i @@ -20,6 +20,8 @@ * Boston, MA 02110-1301, USA. */ +%include <gr_basic_block.i> + class gr_block; typedef boost::shared_ptr<gr_block> gr_block_sptr; %template(gr_block_sptr) boost::shared_ptr<gr_block>; @@ -29,26 +31,21 @@ namespace std { %template(x_vector_gr_block_sptr) vector<gr_block_sptr>; }; -class gr_block { +class gr_block : public gr_basic_block { protected: gr_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); public: virtual ~gr_block (); - std::string name () const; - gr_io_signature_sptr input_signature () const; - gr_io_signature_sptr output_signature () const; - long unique_id () const; unsigned history () const; int output_multiple () const; double relative_rate () const; - bool check_topology (int ninputs, int noutputs); bool start(); bool stop(); @@ -57,9 +54,6 @@ class gr_block { void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } }; -%rename(block_ncurrently_allocated) gr_block_ncurrently_allocated; -long gr_block_ncurrently_allocated (); - %pythoncode %{ gr_block_sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id ()) gr_block_sptr.block = lambda self: self diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc index ed414d472..5feb180f7 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc @@ -38,7 +38,8 @@ gr_block_detail_ncurrently_allocated () gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs) : d_ninputs (ninputs), d_noutputs (noutputs), d_input (ninputs), d_output (noutputs), - d_done (false) + d_done (false), + d_color (gr_block_detail::WHITE) { s_ncurrently_allocated++; } diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h index 8c4615919..d89b7fea1 100644 --- a/gnuradio-core/src/lib/runtime/gr_block_detail.h +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2004 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 detail. - * + * * 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, @@ -75,18 +75,26 @@ class gr_block_detail { void produce_each (int how_many_items); + /*! + * \brief Allow the flowgraph to set for sorting and partitioning + */ + enum vcolor { WHITE, GREY, BLACK }; + void set_color(vcolor color) { d_color = color; } + vcolor color() const { return d_color; } + // ---------------------------------------------------------------------------- private: - unsigned int d_ninputs; - unsigned int d_noutputs; + unsigned int d_ninputs; + unsigned int d_noutputs; std::vector<gr_buffer_reader_sptr> d_input; - std::vector<gr_buffer_sptr> d_output; - bool d_done; - + std::vector<gr_buffer_sptr> d_output; + bool d_done; + vcolor d_color; + gr_block_detail (unsigned int ninputs, unsigned int noutputs); - friend gr_block_detail_sptr + friend gr_block_detail_sptr gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); }; diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc new file mode 100644 index 000000000..65dea95fb --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc @@ -0,0 +1,63 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_hier_block2.h> +#include <gr_io_signature.h> +#include <gr_hier_block2_detail.h> +#include <iostream> + +gr_hier_block2_sptr gr_make_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) +{ + return gr_hier_block2_sptr(new gr_hier_block2(name, input_signature, output_signature)); +} + +gr_hier_block2::gr_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + : gr_basic_block(name, input_signature, output_signature), + d_detail(new gr_hier_block2_detail(this)) +{ +} + +gr_hier_block2::~gr_hier_block2() +{ + delete d_detail; +} + +void +gr_hier_block2::define_component(const std::string &name, gr_basic_block_sptr block) +{ + d_detail->define_component(name, block); +} + +void +gr_hier_block2::connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) +{ + d_detail->connect(src_name, src_port, dst_name, dst_port); +} diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h new file mode 100644 index 000000000..9d2dd3569 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h @@ -0,0 +1,67 @@ +/* -*- 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. + */ +#ifndef INCLUDED_GR_HIER_BLOCK2_H +#define INCLUDED_GR_HIER_BLOCK2_H + +#include <gr_basic_block.h> + +/*! + * \brief public constructor for gr_hier_block2 + */ +gr_hier_block2_sptr gr_make_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + +class gr_hier_block2_detail; + +/*! + * \brief gr_hier_block2 - Hierarchical container class for gr_block's + * + */ +class gr_hier_block2 : public gr_basic_block +{ +private: + friend class gr_hier_block2_detail; + friend class gr_runtime_impl; + friend gr_hier_block2_sptr gr_make_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + /*! + * \brief Private implementation details of gr_hier_block2 + */ + gr_hier_block2_detail *d_detail; + +protected: + gr_hier_block2(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + +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); +}; + +#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 new file mode 100644 index 000000000..c5a676534 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.i @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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. + */ + +%include <gr_basic_block.i> + +class gr_hier_block2; +typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; +%template(gr_hier_block2_sptr) boost::shared_ptr<gr_hier_block2>; + +// Hack to have a Python shim implementation of gr.hier_block2 +// that instantiates one of these and passes through calls +%rename(hier_block2_swig) gr_make_hier_block2; +gr_hier_block2_sptr gr_make_hier_block2(const std::string name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + +class gr_hier_block2 : public gr_basic_block +{ +private: + gr_hier_block2(const std::string name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + +public: + ~gr_hier_block2 (); + + // Add a named block to the container + void define_component(const std::string &name, gr_basic_block_sptr basic_block) + throw (std::invalid_argument); + void connect(const std::string &src_name, int src_port, + const std::string &dst_name, 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 new file mode 100644 index 000000000..545a64bfd --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc @@ -0,0 +1,227 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_hier_block2_detail.h> +#include <gr_simple_flowgraph.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) : +d_owner(owner) +{ +} + +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(); +} + +void +gr_hier_block2_detail::define_component(const std::string &name, gr_basic_block_sptr block) +{ + if (!block) + throw std::invalid_argument("null block passed"); + + if (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"); +} + +void +gr_hier_block2_detail::connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) +{ + gr_io_signature_sptr src_io_signature; + gr_io_signature_sptr dst_io_signature; + + // 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)); +} + +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"); +} + +void +gr_hier_block2_detail::check_dst_not_used(const std::string name, int port) +{ + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if ((*p)->dst_name() == name && (*p)->dst_port() == port) + throw std::invalid_argument("destination port in use"); +} + +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"); +} + +std::string +gr_hier_block2_detail::prepend_prefix(const std::string &prefix, const std::string &str) +{ + return prefix + ((prefix == "") ? "" : ".") + str; +} + +gr_endpoint +gr_hier_block2_detail::match_endpoint(const std::string &name, int port, bool is_input) +{ + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (is_input) { + if ((*p)->src_name() == name && (*p)->src_port() == port) + return resolve_endpoint((*p)->dst_name(), (*p)->dst_port(), "", !is_input); + } + else { + if ((*p)->dst_name() == name && (*p)->dst_port() == port) + return resolve_endpoint((*p)->src_name(), (*p)->src_port(), "", !is_input); + } + } + + // Should never get here + throw std::runtime_error("unable to match endpoint"); +} + +gr_endpoint +gr_hier_block2_detail::resolve_endpoint(const std::string &name, int port, + const std::string &prefix, bool is_input) +{ + gr_basic_block_sptr basic_block = lookup_block(name); + + // 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"); +} + +void +gr_hier_block2_detail::flatten(gr_simple_flowgraph_sptr sfg, const std::string &prefix) +{ + flatten_components(sfg, prefix); + flatten_edges(sfg, prefix); +} + +void +gr_hier_block2_detail::flatten_components(gr_simple_flowgraph_sptr sfg, const std::string &prefix) +{ + // Add my non-hierarchical components to the simple flowgraph, then recurse + for (gr_hier_component_miter_t p = d_components.begin(); p != d_components.end(); p++) { + std::string name = prepend_prefix(prefix, p->first); + + 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); + } +} + +void +gr_hier_block2_detail::flatten_edges(gr_simple_flowgraph_sptr sfg, const std::string &prefix) +{ + // Add my edges to the flow graph, resolving references to actual endpoints + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + // Connections to self get resolved/added by parent if actually connected + if ((*p)->src_name() == "self" || (*p)->dst_name() == "self") + continue; + + 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)); + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h new file mode 100644 index 000000000..095bd40f5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h @@ -0,0 +1,66 @@ +/* + * 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. + */ +#ifndef INCLUDED_GR_HIER_BLOCK2_DETAIL_H +#define INCLUDED_GR_HIER_BLOCK2_DETAIL_H + +#include <gr_hier_block2.h> +#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: + friend class gr_hier_block2; + friend class gr_runtime_impl; + + // Constructor--it's private, only friends can instantiate + gr_hier_block2_detail(gr_hier_block2 *owner); + + // Private implementation data + gr_hier_block2 *d_owner; + gr_hier_component_map_t d_components; + gr_edge_vector_t d_edges; + + // 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); + +public: + ~gr_hier_block2_detail(); +}; + +#endif /* INCLUDED_GR_HIER_BLOCK2_DETAIL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.cc b/gnuradio-core/src/lib/runtime/gr_runtime.cc new file mode 100644 index 000000000..926e87857 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime.cc @@ -0,0 +1,70 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_runtime.h> +#include <gr_runtime_impl.h> +#include <iostream> + +gr_runtime_sptr +gr_make_runtime(gr_hier_block2_sptr 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); +} + +gr_runtime::~gr_runtime() +{ + delete d_impl; +} + +void +gr_runtime::start() +{ + d_impl->start(); +} + +void +gr_runtime::stop() +{ + d_impl->stop(); +} + +void +gr_runtime::wait() +{ + d_impl->wait(); +} + +void +gr_runtime::run() +{ + start(); + wait(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.h b/gnuradio-core/src/lib/runtime/gr_runtime.h new file mode 100644 index 000000000..fc58da456 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime.h @@ -0,0 +1,49 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_RUNTIME_H +#define INCLUDED_GR_RUNTIME_H + +#include <gr_runtime_types.h> + +class gr_runtime_impl; + +gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block); + +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_impl *d_impl; + +public: + ~gr_runtime(); + + void start(); + void stop(); + void wait(); + void run(); +}; + +#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 new file mode 100644 index 000000000..496adff37 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime.i @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 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_runtime; +typedef boost::shared_ptr<gr_runtime> gr_runtime_sptr; +%template(gr_runtime_sptr) boost::shared_ptr<gr_runtime>; + +%rename(runtime) gr_make_runtime; +gr_runtime_sptr gr_make_runtime(gr_hier_block2_sptr top_block); + +class gr_runtime +{ +protected: + gr_runtime(gr_hier_block2_sptr top_block); + +public: + void start() + throw (std::runtime_error); + void stop(); + void wait(); + void run() + throw (std::runtime_error); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc new file mode 100644 index 000000000..2b104cd99 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc @@ -0,0 +1,130 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define GR_RUNTIME_IMPL_DEBUG 0 + +#include <gr_runtime_impl.h> +#include <gr_simple_flowgraph.h> +#include <gr_hier_block2.h> +#include <gr_hier_block2_detail.h> +#include <stdexcept> +#include <iostream> + +gr_runtime_impl::gr_runtime_impl(gr_hier_block2_sptr top_block) : +d_running(false), +d_top_block(top_block), +d_sfg(gr_make_simple_flowgraph()), +d_graphs() +{ +} + +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_sptr thread = gr_make_scheduler_thread(*p); + thread->start(); + d_threads.push_back(thread); + } +} + +void +gr_runtime_impl::stop() +{ + if (!d_running) + return; + + for (gr_scheduler_thread_viter_t p = d_threads.begin(); + p != d_threads.end(); p++) + (*p)->stop(); + + d_running = false; +} + +void +gr_runtime_impl::wait() +{ + for (gr_scheduler_thread_viter_t p = d_threads.begin(); + p != d_threads.end(); p++) { + while(1) { + (*p)->join(NULL); + if (!(*p)->state() == omni_thread::STATE_TERMINATED) + break; + } + } +} + +gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph) +{ + return gr_scheduler_thread_sptr(new gr_scheduler_thread(graph)); +} + +gr_scheduler_thread::gr_scheduler_thread(gr_block_vector_t graph) : + omni_thread(NULL, PRIORITY_NORMAL), + d_sts(gr_make_single_threaded_scheduler(graph)) +{ +} + +gr_scheduler_thread::~gr_scheduler_thread() +{ +} + +void gr_scheduler_thread::start() +{ + start_undetached(); +} + +void *gr_scheduler_thread::run_undetached(void *arg) +{ + d_sts->run(); + return 0; +} + +void gr_scheduler_thread::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 new file mode 100644 index 000000000..54977ef97 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h @@ -0,0 +1,74 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_RUNTIME_IMPL_H +#define INCLUDED_GR_RUNTIME_IMPL_H + +#include <gr_runtime_types.h> +#include <gr_block.h> +#include <omnithread.h> +#include <gr_single_threaded_scheduler.h> + +class gr_scheduler_thread; +typedef boost::shared_ptr<gr_scheduler_thread> gr_scheduler_thread_sptr; +typedef std::vector<gr_scheduler_thread_sptr> gr_scheduler_thread_vector_t; +typedef std::vector<gr_scheduler_thread_sptr>::iterator gr_scheduler_thread_viter_t; + +gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph); + +class gr_scheduler_thread : public omni_thread +{ +private: + gr_scheduler_thread(gr_block_vector_t graph); + friend gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph); + + gr_single_threaded_scheduler_sptr d_sts; + +public: + ~gr_scheduler_thread(); + virtual void *run_undetached(void *arg); + void start(); + void stop(); +}; + +class gr_runtime_impl +{ +private: + 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; + + void start(); + void stop(); + void wait(); + +public: + ~gr_runtime_impl(); + +}; + +#endif /* INCLUDED_GR_RUNTIME_IMPL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_types.h b/gnuradio-core/src/lib/runtime/gr_runtime_types.h index 55cbabe18..dfa0ce94f 100644 --- a/gnuradio-core/src/lib/runtime/gr_runtime_types.h +++ b/gnuradio-core/src/lib/runtime/gr_runtime_types.h @@ -20,8 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_RUNTIME_H -#define INCLUDED_GR_RUNTIME_H +#ifndef INCLUDED_GR_RUNTIME_TYPES_H +#define INCLUDED_GR_RUNTIME_TYPES_H #include <gr_types.h> @@ -29,16 +29,24 @@ * typedefs for smart pointers we use throughout the runtime system */ +class gr_basic_block; class gr_block; class gr_block_detail; +class gr_hier_block2; class gr_io_signature; class gr_buffer; class gr_buffer_reader; +class gr_simple_flowgraph; +class gr_runtime; -typedef boost::shared_ptr<gr_block> gr_block_sptr; -typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr; -typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr; -typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr; -typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr; +typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr; +typedef boost::shared_ptr<gr_block> gr_block_sptr; +typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr; +typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; +typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr; +typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr; +typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr; +typedef boost::shared_ptr<gr_runtime> gr_runtime_sptr; +typedef boost::shared_ptr<gr_simple_flowgraph> gr_simple_flowgraph_sptr; -#endif /* INCLUDED_GR_RUNTIME_H */ +#endif /* INCLUDED_GR_RUNTIME_TYPES_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc new file mode 100644 index 000000000..21aeb587c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.cc @@ -0,0 +1,67 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_simple_flowgraph.h> +#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()); +} + +gr_simple_flowgraph::gr_simple_flowgraph() : +d_detail(new gr_simple_flowgraph_detail()) +{ +} + +gr_simple_flowgraph::~gr_simple_flowgraph() +{ + delete d_detail; +} + +void +gr_simple_flowgraph::define_component(const std::string &name, gr_block_sptr block) +{ + if (GR_SIMPLE_FLOWGRAPH_DEBUG) + std::cout << "Defining block " << block << " as " << name << std::endl; + d_detail->define_component(name, block); +} + +void +gr_simple_flowgraph::connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) +{ + d_detail->connect(src_name, src_port, dst_name, dst_port); +} + +void +gr_simple_flowgraph::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 new file mode 100644 index 000000000..ca2c505e5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.h @@ -0,0 +1,52 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_SIMPLE_FLOWGRAPH_H +#define INCLUDED_GR_SIMPLE_FLOWGRAPH_H + +#include <gr_block.h> +#include <boost/shared_ptr.hpp> +#include <string> + +gr_simple_flowgraph_sptr gr_make_simple_flowgraph(); + +class gr_simple_flowgraph_detail; + +class gr_simple_flowgraph +{ +private: + friend class gr_runtime_impl; + friend gr_simple_flowgraph_sptr gr_make_simple_flowgraph(); + gr_simple_flowgraph(); + + gr_simple_flowgraph_detail *d_detail; + +public: + ~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(); +}; + +#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 new file mode 100644 index 000000000..c3654fe50 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph.i @@ -0,0 +1,45 @@ +/* -*- 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 new file mode 100644 index 000000000..2698bc6d8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc @@ -0,0 +1,471 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_simple_flowgraph.h> +#include <gr_simple_flowgraph_detail.h> +#include <gr_io_signature.h> +#include <gr_block_detail.h> +#include <gr_buffer.h> +#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_edge::~gr_edge() +{ +} + +gr_simple_flowgraph_detail::gr_simple_flowgraph_detail() : +d_components(), +d_edges() +{ +} + +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(); +} + +void +gr_simple_flowgraph_detail::define_component(const std::string &name, gr_block_sptr block) +{ + if (!block) + throw std::invalid_argument("null block passed"); + + if (!lookup_block(name)) + d_components[name] = block; + else + throw std::invalid_argument("name already in use"); +} + +void +gr_simple_flowgraph_detail::connect(const std::string &src_name, int src_port, + const std::string &dst_name, int dst_port) +{ + gr_block_sptr src_block = lookup_block(src_name); + gr_block_sptr dst_block = lookup_block(dst_name); + + 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); + + d_edges.push_back(gr_make_edge(src_name, src_port, dst_name, dst_port)); +} + +void +gr_simple_flowgraph_detail::check_valid_port(gr_io_signature_sptr sig, int port) +{ + if (port < 0) + throw std::invalid_argument("negative port number"); + if (sig->max_streams() >= 0 && port >= sig->max_streams()) + throw std::invalid_argument("port number exceeds max"); +} + +void +gr_simple_flowgraph_detail::check_dst_not_used(const std::string &name, int port) +{ + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if ((*p)->dst_name() == name && (*p)->dst_port() == port) + throw std::invalid_argument("dst already in use"); +} + +void +gr_simple_flowgraph_detail::check_type_match(gr_block_sptr src_block, int src_port, + gr_block_sptr dst_block, int dst_port) +{ + int src_size = src_block->output_signature()->sizeof_stream_item(src_port); + int dst_size = dst_block->input_signature()->sizeof_stream_item(dst_port); + + if (src_size != dst_size) + throw std::invalid_argument("type size mismatch"); +} + +void +gr_simple_flowgraph_detail::validate() +{ + for (gr_component_miter_t p = d_components.begin(); p != d_components.end(); p++) { + std::vector<int> used_ports; + int ninputs, noutputs; + + used_ports = calc_used_ports(p->first, true); // inputs + ninputs = used_ports.size(); + check_contiguity(p->second, used_ports, true); // inputs + + used_ports = calc_used_ports(p->first, false); // outputs + noutputs = used_ports.size(); + check_contiguity(p->second, used_ports, false); // outputs + + if (!(p->second->check_topology(ninputs, noutputs))) + throw std::runtime_error("check topology failed"); + } +} + +std::vector<int> +gr_simple_flowgraph_detail::calc_used_ports(const std::string &name, bool check_inputs) +{ + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "Calculating used " << (check_inputs ? "input " : "output ") + << "ports..."; + + 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); + + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << result.size() << std::endl; + + return result; +} + +gr_edge_vector_t +gr_simple_flowgraph_detail::calc_connections(const std::string &name, 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); + } + } + + return result; // assumes no duplicates +} + +void +gr_simple_flowgraph_detail::check_contiguity(gr_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"); + } + } + + if (used_ports[nports-1]+1 != nports) { + for (int i = 0; i < nports; i++) { + if (used_ports[i] != i) { + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "missing " << (check_inputs ? "input ":"output ") + << i << std::endl; + + throw std::runtime_error("missing input assignment"); + } + } + } + + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "ok." << std::endl; +} + +void +gr_simple_flowgraph_detail::setup_connections() +{ + // Assign block details to component blocks + for (gr_component_miter_t p = d_components.begin(); p != d_components.end(); p++) { + if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG) + std::cout << "Allocating output buffers for " << p->first << "..." << std::endl; + + 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)); + } + } +} + +gr_buffer_sptr +gr_simple_flowgraph_detail::allocate_buffer(const std::string &name, int port) +{ + gr_block_sptr block = lookup_block(name); + int item_size = block->output_signature()->sizeof_stream_item(port); + int nitems = s_fixed_buffer_size/item_size; + + // 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_vector_t +gr_simple_flowgraph_detail::calc_downstream_blocks(const std::string &name, int port) +{ + gr_block_vector_t tmp, result; + std::insert_iterator<gr_block_vector_t> inserter(result, result.begin()); + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if ((*p)->src_name() == name && (*p)->src_port() == port) + tmp.push_back(lookup_block((*p)->dst_name())); + + // Remove duplicates + sort(tmp.begin(), tmp.end()); + unique_copy(tmp.begin(), tmp.end(), inserter); + return result; +} + +gr_edge_vector_t +gr_simple_flowgraph_detail::calc_upstream_edges(const std::string &name) +{ + 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); + + return result; // Assume no duplicates +} + +gr_block_vector_t +gr_simple_flowgraph_detail::calc_used_blocks() +{ + std::vector<std::string> tmp, tmp_unique; + std::insert_iterator<std::vector<std::string> > inserter(tmp_unique, tmp_unique.begin()); + gr_block_vector_t result; + + 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; + + 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; + + 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)); + } + + return result; +} + +gr_block_vector_t +gr_simple_flowgraph_detail::calc_reachable_blocks(gr_block_sptr block, gr_block_vector_t &blocks) +{ + gr_block_vector_t result; + + // Mark all blocks as unvisited + for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + (*p)->detail()->set_color(gr_block_detail::WHITE); + + // Recursively mark all reachable blocks + reachable_dfs_visit(block, blocks); + + // Collect all the blocks that have been visited + for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + if ((*p)->detail()->color() == gr_block_detail::BLACK) + result.push_back(*p); + + return result; +} + +// Recursively mark all reachable blocks from given block and block list +void +gr_simple_flowgraph_detail::reachable_dfs_visit(gr_block_sptr block, gr_block_vector_t &blocks) +{ + // Mark the current one as visited + block->detail()->set_color(gr_block_detail::BLACK); + + // Recurse into adjacent vertices + gr_block_vector_t adjacent = calc_adjacent_blocks(block, blocks); + + for (gr_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++) + if ((*p)->detail()->color() == gr_block_detail::WHITE) + reachable_dfs_visit(*p, blocks); +} + +// Return a list of block adjacent to a given block along any edge +gr_block_vector_t +gr_simple_flowgraph_detail::calc_adjacent_blocks(gr_block_sptr block, gr_block_vector_t &blocks) +{ + gr_block_vector_t tmp, result; + std::insert_iterator<gr_block_vector_t> inserter(result, result.begin()); + + // 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; +} + +gr_block_vector_t +gr_simple_flowgraph_detail::topological_sort(gr_block_vector_t &blocks) +{ + gr_block_vector_t result; + + // NOP for now + result = blocks; + + return result; +} + diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h new file mode 100644 index 000000000..368a0619f --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h @@ -0,0 +1,128 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_SIMPLE_FLOWGRAPH_DETAIL_H +#define INCLUDED_GR_SIMPLE_FLOWGRAPH_DETAIL_H + +#include <gr_block.h> +#include <map> + +#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); + +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); + + 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(); } +}; + +typedef std::vector<gr_edge_sptr> gr_edge_vector_t; +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; + + gr_simple_flowgraph_detail(); + + gr_component_map_t d_components; + gr_edge_vector_t d_edges; + static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE; + + 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); + 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_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); + +public: + ~gr_simple_flowgraph_detail(); +}; + +inline std::ostream& +operator <<(std::ostream& os, const gr_block_sptr p) +{ + os << "<gr_block " << p->name() << " (" << p->unique_id() << ")>"; + return os; +} + +inline std::ostream& +operator <<(std::ostream &os, const gr_endpoint endp) +{ + os << endp.name() << ":" << endp.port(); + return os; +} + +#endif /* INCLUDED_GR_SIMPLE_FLOWGRAPH_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_block.cc index 4773a6eaa..630d72749 100644 --- a/gnuradio-core/src/lib/runtime/qa_gr_block.cc +++ b/gnuradio-core/src/lib/runtime/qa_gr_block.cc @@ -25,7 +25,6 @@ #endif #include <qa_gr_block.h> #include <gr_block.h> -#include <gr_runtime_types.h> #include <gr_io_signature.h> #include <gr_null_sink.h> #include <gr_null_source.h> diff --git a/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.cc new file mode 100644 index 000000000..766ea2f6b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.cc @@ -0,0 +1,46 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qa_gr_hier_block2.h> +#include <gr_hier_block2.h> +#include <gr_io_signature.h> +#include <gr_null_source.h> +#include <gr_null_sink.h> + +void qa_gr_hier_block2::test_make() +{ + gr_hier_block2_sptr src1(gr_make_hier_block2("test", + gr_make_io_signature(1, 1, sizeof(int)), + gr_make_io_signature(1, 1, sizeof(int)))); + + CPPUNIT_ASSERT(src1); + CPPUNIT_ASSERT_EQUAL(std::string("test"), src1->name()); + CPPUNIT_ASSERT_EQUAL(1, src1->input_signature()->max_streams()); + CPPUNIT_ASSERT_EQUAL(1, src1->output_signature()->min_streams()); + CPPUNIT_ASSERT_EQUAL(1, src1->output_signature()->max_streams()); + CPPUNIT_ASSERT_EQUAL(sizeof(int), + src1->output_signature()->sizeof_stream_item(0)); +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.h b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.h new file mode 100644 index 000000000..a6bd8d97b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.h @@ -0,0 +1,43 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_QA_GR_HIER_BLOCK2_H +#define INCLUDED_QA_GR_HIER_BLOCK2_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_gr_hier_block2 : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_gr_hier_block2); + + CPPUNIT_TEST(test_make); + + CPPUNIT_TEST_SUITE_END(); + +private: + void test_make(); + void test_derived(); +}; + +#endif /* INCLUDED_QA_GR_HIER_BLOCK2_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_runtime.cc b/gnuradio-core/src/lib/runtime/qa_runtime.cc index 165a34703..ca0c71d3c 100644 --- a/gnuradio-core/src/lib/runtime/qa_runtime.cc +++ b/gnuradio-core/src/lib/runtime/qa_runtime.cc @@ -33,6 +33,7 @@ #include <qa_gr_vmcircbuf.h> #include <qa_gr_io_signature.h> #include <qa_gr_block.h> +#include <qa_gr_hier_block2.h> #include <qa_gr_buffer.h> CppUnit::TestSuite * @@ -43,6 +44,7 @@ qa_runtime::suite () s->addTest (qa_gr_vmcircbuf::suite ()); s->addTest (qa_gr_io_signature::suite ()); s->addTest (qa_gr_block::suite ()); + s->addTest (qa_gr_hier_block2::suite ()); s->addTest (qa_gr_buffer::suite ()); return s; diff --git a/gnuradio-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i index f2fd36437..8e6c01f9a 100644 --- a/gnuradio-core/src/lib/runtime/runtime.i +++ b/gnuradio-core/src/lib/runtime/runtime.i @@ -26,6 +26,9 @@ #include <gr_buffer.h> #include <gr_block.h> #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> @@ -37,9 +40,12 @@ %include <gr_io_signature.i> %include <gr_buffer.i> +%include <gr_basic_block.i> %include <gr_block.i> %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> @@ -47,3 +53,4 @@ %include <gr_dispatcher.i> %include <gr_error_handler.i> %include <gr_realtime.i> +%include <gr_runtime.i> |