diff options
Diffstat (limited to 'gnuradio-core/src/lib')
19 files changed, 1475 insertions, 1648 deletions
diff --git a/gnuradio-core/src/lib/CMakeLists.txt b/gnuradio-core/src/lib/CMakeLists.txt index 89a1bad88..c061a5723 100644 --- a/gnuradio-core/src/lib/CMakeLists.txt +++ b/gnuradio-core/src/lib/CMakeLists.txt @@ -101,6 +101,6 @@ include_directories(${CPPUNIT_INCLUDE_DIRS}) link_directories(${CPPUNIT_LIBRARY_DIRS}) add_library(test-gnuradio-core SHARED ${test_gnuradio_core_sources}) -target_link_libraries(test-gnuradio-core gnuradio-core ${CPPUNIT_LIBRARIES} ${Boost_LIBRARIES}) +target_link_libraries(test-gnuradio-core ${GR_TEST_TARGET_DEPS} ${CPPUNIT_LIBRARIES} ${Boost_LIBRARIES}) endif(ENABLE_TESTING) diff --git a/gnuradio-core/src/lib/runtime/CMakeLists.txt b/gnuradio-core/src/lib/runtime/CMakeLists.txt index 70938a0f1..6092c4f4e 100644 --- a/gnuradio-core/src/lib/runtime/CMakeLists.txt +++ b/gnuradio-core/src/lib/runtime/CMakeLists.txt @@ -48,40 +48,40 @@ # Append gnuradio-core library sources ######################################################################## list(APPEND gnuradio_core_sources - ${CMAKE_CURRENT_SOURCE_DIR}/gr_basic_block.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_flowgraph.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_flat_flowgraph.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_basic_block.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_flowgraph.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_flat_flowgraph.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_block.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_detail.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_executor.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_registry.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_block_detail.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_block_executor.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_block_registry.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2_detail.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2_detail.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_buffer.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_dispatcher.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_error_handler.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_io_signature.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_io_signature.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_local_sighandler.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_message.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_accepter.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_accepter.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_handler.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_queue.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_pagesize.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_preferences.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_realtime.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler_sts.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler_tpb.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_single_threaded_scheduler.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_sptr_magic.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler_sts.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler_tpb.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_single_threaded_scheduler.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_sptr_magic.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_block.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_decimator.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_interpolator.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_sys_paths.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block_impl.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_detail.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_thread_body.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block_impl.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_detail.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_thread_body.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_vmcircbuf.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_vmcircbuf_mmap_shm_open.cc ${CMAKE_CURRENT_SOURCE_DIR}/gr_vmcircbuf_mmap_tmpfile.cc @@ -98,13 +98,13 @@ list(APPEND test_gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_hier_block2.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_hier_block2_derived.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_buffer.cc - ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_flowgraph.cc + #${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_flowgraph.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_top_block.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_io_signature.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_vmcircbuf.cc - ${CMAKE_CURRENT_SOURCE_DIR}/qa_block_tags.cc + #${CMAKE_CURRENT_SOURCE_DIR}/qa_block_tags.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_runtime.cc - ${CMAKE_CURRENT_SOURCE_DIR}/qa_set_msg_handler.cc + #${CMAKE_CURRENT_SOURCE_DIR}/qa_set_msg_handler.cc ) ######################################################################## diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc index 43aebf0bf..ed390e71f 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -1,262 +1,486 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2009,2010 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 3, 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 - +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "pmx_helper.hpp" #include <gr_block.h> -#include <gr_block_detail.h> -#include <stdexcept> +#include <boost/foreach.hpp> #include <iostream> -#include <gr_block_registry.h> -gr_block::gr_block (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_output_multiple (1), - d_output_multiple_set(false), - d_unaligned(0), - d_is_unaligned(false), - d_relative_rate (1.0), - d_history(1), - d_fixed_rate(false), - d_max_noutput_items_set(false), - d_max_noutput_items(0), - d_tag_propagation_policy(TPP_ALL_TO_ALL), - d_max_output_buffer(std::max(output_signature->max_streams(),1), -1), - d_min_output_buffer(std::max(output_signature->max_streams(),1), -1) +gr_block::gr_block(void) +{ + //NOP +} + +gr_block::gr_block( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature +): + gras::Block(name) +{ + //this initializes private vars, order matters + this->set_fixed_rate(false); + this->set_output_multiple(1); + this->set_history(1); + this->set_relative_rate(1.0); + this->set_decimation(1); + this->set_interpolation(1); + this->set_tag_propagation_policy(TPP_ALL_TO_ALL); + this->set_input_signature(input_signature); + this->set_output_signature(output_signature); +} + +gr_block::~gr_block(void) { - global_block_registry.register_primitive(alias(), this); + //NOP } -gr_block::~gr_block () +void gr_block::notify_active(void) { - global_block_registry.unregister_primitive(alias()); + this->start(); } -// stub implementation: 1:1 +bool gr_block::start(void) +{ + return true; +} -void -gr_block::forecast (int noutput_items, gr_vector_int &ninput_items_required) +void gr_block::notify_inactive(void) { - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = noutput_items + history() - 1; + this->stop(); } -// default implementation +bool gr_block::stop(void) +{ + return true; +} -bool -gr_block::start() +void gr_block::notify_topology(const size_t num_inputs, const size_t num_outputs) { - return true; + _fcast_ninput_items.resize(num_inputs); + _work_ninput_items.resize(num_inputs); + _work_input_items.resize(num_inputs); + _work_output_items.resize(num_outputs); + this->check_topology(num_inputs, num_outputs); } -bool -gr_block::stop() +bool gr_block::check_topology(int, int) { - return true; + return true; +} + +void gr_block::work( + const InputItems &input_items, + const OutputItems &output_items +){ + _work_io_ptr_mask = 0; + #define REALLY_BIG size_t(1 << 30) + const size_t num_inputs = input_items.size(); + const size_t num_outputs = output_items.size(); + + //------------------------------------------------------------------ + //-- initialize input buffers before work + //------------------------------------------------------------------ + size_t num_input_items = REALLY_BIG; //so big that it must std::min + for (size_t i = 0; i < num_inputs; i++) + { + _work_ninput_items[i] = input_items[i].size(); + _work_input_items[i] = input_items[i].get(); + _work_io_ptr_mask |= ptrdiff_t(_work_input_items[i]); + size_t items = input_items[i].size(); + if (_enable_fixed_rate) + { + if (items <= _input_history_items) + { + return this->mark_input_fail(i); + } + items -= _input_history_items; + } + + num_input_items = std::min(num_input_items, items); + } + + //------------------------------------------------------------------ + //-- initialize output buffers before work + //------------------------------------------------------------------ + size_t num_output_items = REALLY_BIG; //so big that it must std::min + for (size_t i = 0; i < num_outputs; i++) + { + _work_output_items[i] = output_items[i].get(); + _work_io_ptr_mask |= ptrdiff_t(_work_output_items[i]); + size_t items = output_items[i].size(); + items /= _output_multiple_items; + items *= _output_multiple_items; + num_output_items = std::min(num_output_items, items); + } + + //------------------------------------------------------------------ + //-- calculate the work_noutput_items given: + //-- min of num_input_items + //-- min of num_output_items + //-- relative rate and output multiple items + //------------------------------------------------------------------ + size_t work_noutput_items = num_output_items; + if (num_inputs and (_enable_fixed_rate or not num_outputs)) + { + size_t calc_output_items = size_t(num_input_items*_relative_rate); + calc_output_items += _output_multiple_items-1; + calc_output_items /= _output_multiple_items; + calc_output_items *= _output_multiple_items; + if (calc_output_items and calc_output_items < work_noutput_items) + work_noutput_items = calc_output_items; + } + + //------------------------------------------------------------------ + //-- forecast + //------------------------------------------------------------------ + if (num_inputs or num_outputs) + { + forecast_again_you_jerk: + _fcast_ninput_items = _work_ninput_items; //init for NOP case + this->forecast(work_noutput_items, _fcast_ninput_items); + for (size_t i = 0; i < input_items.size(); i++) + { + if (_fcast_ninput_items[i] <= _work_ninput_items[i]) continue; + + //handle the case of forecast failing + if (work_noutput_items <= _output_multiple_items) + { + return this->mark_input_fail(i); + } + + work_noutput_items = work_noutput_items/2; //backoff regime + work_noutput_items += _output_multiple_items-1; + work_noutput_items /= _output_multiple_items; + work_noutput_items *= _output_multiple_items; + goto forecast_again_you_jerk; + } + } + + const int work_ret = this->general_work( + work_noutput_items, + _work_ninput_items, + _work_input_items, + _work_output_items + ); + + if (work_ret > 0) for (size_t i = 0; i < num_outputs; i++) + { + this->produce(i, work_ret); + } + + if (work_ret == -1) this->mark_done(); } -void -gr_block::set_output_multiple (int multiple) +static inline unsigned long long myullround(const double x) { - if (multiple < 1) - throw std::invalid_argument ("gr_block::set_output_multiple"); + return (unsigned long long)(x + 0.5); +} - d_output_multiple_set = true; - d_output_multiple = multiple; +void gr_block::propagate_tags(const size_t which_input, const gras::TagIter &iter) +{ + const size_t num_outputs = _work_output_items.size(); + + switch (_tag_prop_policy) + { + case TPP_DONT: break; //well that was ez + case TPP_ALL_TO_ALL: + for (size_t out_i = 0; out_i < num_outputs; out_i++) + { + BOOST_FOREACH(gras::Tag t, iter) + { + t.offset = myullround(t.offset * _relative_rate); + this->post_output_tag(out_i, t); + } + } + break; + case TPP_ONE_TO_ONE: + if (which_input < num_outputs) + { + BOOST_FOREACH(gras::Tag t, iter) + { + t.offset = myullround(t.offset * _relative_rate); + this->post_output_tag(which_input, t); + } + } + break; + }; } -void -gr_block::set_alignment (int multiple) +void gr_block::forecast(int noutput_items, std::vector<int> &ninputs_req) { - if (multiple < 1) - throw std::invalid_argument ("gr_block::set_alignment_multiple"); + for (size_t i = 0; i < ninputs_req.size(); i++) + { + ninputs_req[i] = fixed_rate_noutput_to_ninput(noutput_items); + } +} - d_output_multiple = multiple; +int gr_block::general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items +){ + throw std::runtime_error("gr_block subclasses must overload general_work!"); } -void -gr_block::set_unaligned (int na) +void gr_block::consume_each(const int how_many_items) { - // unaligned value must be less than 0 and it doesn't make sense - // that it's larger than the alignment value. - if ((na < 0) || (na > d_output_multiple)) - throw std::invalid_argument ("gr_block::set_unaligned"); + if (how_many_items < 0) return; + gras::Block::consume(size_t(how_many_items)); +} - d_unaligned = na; +void gr_block::consume(const size_t i, const int how_many_items) +{ + if (how_many_items < 0) return; + gras::Block::consume(i, size_t(how_many_items)); } -void -gr_block::set_is_unaligned (bool u) +void gr_block::produce(const size_t o, const int how_many_items) { - d_is_unaligned = u; + if (how_many_items < 0) return; + gras::Block::produce(o, size_t(how_many_items)); } -void -gr_block::set_relative_rate (double relative_rate) +uint64_t gr_block::nitems_read(const size_t which_input) { - if (relative_rate < 0.0) - throw std::invalid_argument ("gr_block::set_relative_rate"); + return Block::get_consumed(which_input); +} - d_relative_rate = relative_rate; +uint64_t gr_block::nitems_written(const size_t which_output) +{ + return Block::get_produced(which_output); } +void gr_block::set_alignment(const size_t) +{ + //TODO + //probably dont need this since buffers always start aligned + //and therefore alignment is always re-acheived +} -void -gr_block::consume (int which_input, int how_many_items) +bool gr_block::is_unaligned(void) { - d_detail->consume (which_input, how_many_items); + //TODO + //probably dont need this since volk dispatcher checks alignment + //32 byte aligned is good enough for you + return (_work_io_ptr_mask & ptrdiff_t(GRAS_MAX_ALIGNMENT-1)) != 0; } -void -gr_block::consume_each (int how_many_items) +size_t gr_block::fixed_rate_noutput_to_ninput(const size_t noutput_items) { - d_detail->consume_each (how_many_items); + return ((decimation()*noutput_items)/interpolation()) + _input_history_items; } -void -gr_block::produce (int which_output, int how_many_items) +size_t gr_block::interpolation(void) const { - d_detail->produce (which_output, how_many_items); + return _interp; } -int -gr_block::fixed_rate_ninput_to_noutput(int ninput) +void gr_block::set_interpolation(const size_t interp) { - throw std::runtime_error("Unimplemented"); + _interp = interp; + this->set_relative_rate(1.0*interp); + this->set_output_multiple(interp); } -int -gr_block::fixed_rate_noutput_to_ninput(int noutput) +size_t gr_block::decimation(void) const { - throw std::runtime_error("Unimplemented"); + return _decim; } -uint64_t -gr_block::nitems_read(unsigned int which_input) +void gr_block::set_decimation(const size_t decim) { - if(d_detail) { - return d_detail->nitems_read(which_input); - } - else { - //throw std::runtime_error("No block_detail associated with block yet"); - return 0; - } + _decim = decim; + this->set_relative_rate(1.0/decim); } -uint64_t -gr_block::nitems_written(unsigned int which_output) +unsigned gr_block::history(void) const { - if(d_detail) { - return d_detail->nitems_written(which_output); - } - else { - //throw std::runtime_error("No block_detail associated with block yet"); - return 0; - } + //implement off-by-one history compat + return _input_history_items+1; } -void -gr_block::add_item_tag(unsigned int which_output, - const gr_tag_t &tag) +void gr_block::set_history(unsigned history) { - d_detail->add_item_tag(which_output, tag); + gras::InputPortConfig config = this->get_input_config(0); + //implement off-by-one history compat + if (history == 0) history++; + _input_history_items = history-1; + config.preload_items = _input_history_items; + this->set_input_config(0, config); } -void -gr_block::get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_output, - uint64_t start, uint64_t end) +void gr_block::set_fixed_rate(const bool fixed_rate) { - d_detail->get_tags_in_range(v, which_output, start, end); + _enable_fixed_rate = fixed_rate; } -void -gr_block::get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_output, - uint64_t start, uint64_t end, - const pmt::pmt_t &key) +bool gr_block::fixed_rate(void) const { - d_detail->get_tags_in_range(v, which_output, start, end, key); + return _enable_fixed_rate; } -gr_block::tag_propagation_policy_t -gr_block::tag_propagation_policy() +void gr_block::_update_input_reserve(void) { - return d_tag_propagation_policy; + /*! + * Set an input reserve for fixed rate blocks. + * + * FIXME: Also do this when output multiple is large, + * This makes gr-trellis pass under conditions where not fixed rate set, + * but the output multiple is so large that default input isnt sufficient. + */ + if (_enable_fixed_rate or _output_multiple_items > 1024) + { + gras::InputPortConfig config = this->get_input_config(0); + config.reserve_items = size_t(0.5 + _output_multiple_items/_relative_rate); + if (config.reserve_items) this->set_input_config(0, config); + } } -void -gr_block::set_tag_propagation_policy(tag_propagation_policy_t p) +void gr_block::set_output_multiple(const size_t multiple) { - d_tag_propagation_policy = p; + _output_multiple_items = multiple; + gras::OutputPortConfig config = this->get_output_config(0); + config.reserve_items = multiple; + this->set_output_config(0, config); + this->_update_input_reserve(); } +size_t gr_block::output_multiple(void) const +{ + return _output_multiple_items; +} -int -gr_block::max_noutput_items() +void gr_block::set_relative_rate(double relative_rate) { - return d_max_noutput_items; + _relative_rate = relative_rate; + this->_update_input_reserve(); } -void -gr_block::set_max_noutput_items(int m) +double gr_block::relative_rate(void) const { - if(m <= 0) - throw std::runtime_error("gr_block::set_max_noutput_items: value for max_noutput_items must be greater than 0.\n"); + return _relative_rate; +} + +int gr_block::max_noutput_items(void) const +{ + return this->get_output_config(0).maximum_items; +} + +void gr_block::set_max_noutput_items(int max_items) +{ + gras::OutputPortConfig config = this->get_output_config(0); + config.maximum_items = max_items; + this->set_output_config(0, config); +} + +void gr_block::unset_max_noutput_items(void) +{ + this->set_max_noutput_items(0); +} + +bool gr_block::is_set_max_noutput_items(void) const +{ + return this->max_noutput_items() != 0; +} + +static gr_tag_t Tag2gr_tag(const gras::Tag &tag) +{ + gr_tag_t t; + t.offset = tag.offset; + const gras::StreamTag &st = tag.object.as<gras::StreamTag>(); + t.key = pmt::pmc_to_pmt(st.key); + t.value = pmt::pmc_to_pmt(st.val); + t.srcid = pmt::pmc_to_pmt(st.src); + return t; +} + +static gras::Tag gr_tag2Tag(const gr_tag_t &tag) +{ + return gras::Tag + ( + tag.offset, + PMC_M(gras::StreamTag( + pmt::pmt_to_pmc(tag.key), + pmt::pmt_to_pmc(tag.value), + pmt::pmt_to_pmc(tag.srcid) + )) + ); +} + +void gr_block::add_item_tag( + const size_t which_output, const gr_tag_t &tag +){ + this->post_output_tag(which_output, gr_tag2Tag(tag)); +} + +void gr_block::add_item_tag( + const size_t which_output, + uint64_t abs_offset, + const pmt::pmt_t &key, + const pmt::pmt_t &value, + const pmt::pmt_t &srcid +){ + gr_tag_t t; + t.offset = abs_offset; + t.key = key; + t.value = value; + t.srcid = srcid; + this->add_item_tag(which_output, t); +} - d_max_noutput_items = m; - d_max_noutput_items_set = true; +void gr_block::get_tags_in_range( + std::vector<gr_tag_t> &tags, + const size_t which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key +){ + tags.clear(); + BOOST_FOREACH(const gras::Tag &tag, this->get_input_tags(which_input)) + { + if (tag.offset >= abs_start and tag.offset <= abs_end) + { + gr_tag_t t = Tag2gr_tag(tag); + if (not key or pmt::pmt_equal(t.key, key)) tags.push_back(t); + } + } } -void -gr_block::unset_max_noutput_items() +gr_block::tag_propagation_policy_t gr_block::tag_propagation_policy(void) { - d_max_noutput_items_set = false; + return _tag_prop_policy; } -bool -gr_block::is_set_max_noutput_items() +void gr_block::set_tag_propagation_policy(gr_block::tag_propagation_policy_t p) { - return d_max_noutput_items_set; + _tag_prop_policy = p; } -std::ostream& -operator << (std::ostream& os, const gr_block *m) +gras::BufferQueueSptr gr_block::input_buffer_allocator(const size_t, const gras::SBufferConfig &config) { - os << "<gr_block " << m->name() << " (" << m->unique_id() << ")>"; - return os; + if (_input_history_items) + { + return gras::BufferQueue::make_circ(config, 32/*many*/); + } + return gras::BufferQueueSptr(); } -int -gr_block::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +gras::BufferQueueSptr gr_block::output_buffer_allocator(const size_t which, const gras::SBufferConfig &config) { - throw std::runtime_error("gr_block::general_work() not implemented"); - return 0; + return gras::Block::output_buffer_allocator(which, config); } diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h index 57e3fda90..0004f887b 100644 --- a/gnuradio-core/src/lib/runtime/gr_block.h +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -1,481 +1,334 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2007,2009,2010 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 3, 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_BLOCK_H -#define INCLUDED_GR_BLOCK_H +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#ifndef INCLUDED_GNURADIO_GR_BLOCK_H +#define INCLUDED_GNURADIO_GR_BLOCK_H #include <gr_core_api.h> -#include <gr_basic_block.h> +#include <gras/block.hpp> +#include <gr_io_signature.h> +#include <gr_types.h> #include <gr_tags.h> +#include <string> +#include <deque> +#include <map> +#include <boost/foreach.hpp> -/*! - * \brief The abstract base class for all 'terminal' processing blocks. - * \ingroup base_blk - * - * 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 - * items in each stream. - * - * Although blocks may consume data on each input stream at a - * different rate, all outputs streams must produce data at the same - * rate. That rate may be different from any of the input rates. - * - * User derived blocks override two methods, forecast and general_work, - * to implement their signal processing behavior. forecast is called - * by the system scheduler to determine how many items are required on - * each input stream in order to produce a given number of output - * items. - * - * general_work is called to perform the signal processing in the block. - * It reads the input items and writes the output items. - */ - -class GR_CORE_API gr_block : public gr_basic_block { - - public: - - //! Magic return values from general_work - enum { - WORK_CALLED_PRODUCE = -2, - WORK_DONE = -1 - }; - - enum tag_propagation_policy_t { - TPP_DONT = 0, - TPP_ALL_TO_ALL = 1, - TPP_ONE_TO_ONE = 2 - }; - - virtual ~gr_block (); - - /*! - * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...) - * History is the number of x_i's that are examined to produce one y_i. - * This comes in handy for FIR filters, where we use history to - * ensure that our input contains the appropriate "history" for the - * filter. History should be equal to the number of filter taps. - */ - unsigned history () const { return d_history; } - void set_history (unsigned history) { d_history = history; } - - /*! - * \brief Return true if this block has a fixed input to output rate. - * - * If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called. - */ - bool fixed_rate() const { return d_fixed_rate; } - - // ---------------------------------------------------------------- - // override these to define your behavior - // ---------------------------------------------------------------- - - /*! - * \brief Estimate input requirements given output request - * - * \param noutput_items number of output items to produce - * \param ninput_items_required number of input items required on each input stream - * - * Given a request to product \p noutput_items, estimate the number of - * data items required on each input stream. The estimate doesn't have - * to be exact, but should be close. - */ - virtual void forecast (int noutput_items, - gr_vector_int &ninput_items_required); - - /*! - * \brief compute output items from input items - * - * \param noutput_items number of output items to write on each output stream - * \param ninput_items number of input items available on each input stream - * \param input_items vector of pointers to the input items, one entry per input stream - * \param output_items vector of pointers to the output items, one entry per output stream - * - * \returns number of items actually written to each output stream, or -1 on EOF. - * It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items - * - * general_work must call consume or consume_each to indicate how many items - * were consumed on each input stream. - */ - virtual int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - /*! - * \brief Called to enable drivers, etc for i/o devices. - * - * This allows a block to enable an associated driver to begin - * transfering data just before we start to execute the scheduler. - * The end result is that this reduces latency in the pipeline when - * dealing with audio devices, usrps, etc. - */ - virtual bool start(); - - /*! - * \brief Called to disable drivers, etc for i/o devices. - */ - virtual bool stop(); - - // ---------------------------------------------------------------- - - /*! - * \brief Constrain the noutput_items argument passed to forecast and general_work - * - * set_output_multiple causes the scheduler to ensure that the noutput_items - * argument passed to forecast and general_work will be an integer multiple - * of \param multiple The default value of output multiple is 1. - */ - void set_output_multiple (int multiple); - int output_multiple () const { return d_output_multiple; } - bool output_multiple_set () const { return d_output_multiple_set; } - - /*! - * \brief Constrains buffers to work on a set item alignment (for SIMD) - * - * set_alignment_multiple causes the scheduler to ensure that the noutput_items - * argument passed to forecast and general_work will be an integer multiple - * of \param multiple The default value is 1. - * - * This control is similar to the output_multiple setting, except - * that if the number of items passed to the block is less than the - * output_multiple, this value is ignored and the block can produce - * like normal. The d_unaligned value is set to the number of items - * the block is off by. In the next call to general_work, the - * noutput_items is set to d_unaligned or less until - * d_unaligned==0. The buffers are now aligned again and the aligned - * calls can be performed again. - */ - void set_alignment (int multiple); - int alignment () const { return d_output_multiple; } - - void set_unaligned (int na); - int unaligned () const { return d_unaligned; } - void set_is_unaligned (bool u); - bool is_unaligned () const { return d_is_unaligned; } - - /*! - * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed. - */ - void consume (int which_input, int how_many_items); - - /*! - * \brief Tell the scheduler \p how_many_items were consumed on each input stream. - */ - void consume_each (int how_many_items); - - /*! - * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output. - * - * If the block's general_work method calls produce, \p general_work must return WORK_CALLED_PRODUCE. - */ - void produce (int which_output, int how_many_items); - - /*! - * \brief Set the approximate output rate / input rate - * - * Provide a hint to the buffer allocator and scheduler. - * The default relative_rate is 1.0 - * - * decimators have relative_rates < 1.0 - * interpolators have relative_rates > 1.0 - */ - void set_relative_rate (double relative_rate); - - /*! - * \brief return the approximate output rate / input rate - */ - double relative_rate () const { return d_relative_rate; } - - /* - * The following two methods provide special case info to the - * scheduler in the event that a block has a fixed input to output - * ratio. gr_sync_block, gr_sync_decimator and gr_sync_interpolator - * override these. If you're fixed rate, subclass one of those. - */ - /*! - * \brief Given ninput samples, return number of output samples that will be produced. - * N.B. this is only defined if fixed_rate returns true. - * Generally speaking, you don't need to override this. - */ - virtual int fixed_rate_ninput_to_noutput(int ninput); - - /*! - * \brief Given noutput samples, return number of input samples required to produce noutput. - * N.B. this is only defined if fixed_rate returns true. - * Generally speaking, you don't need to override this. - */ - virtual int fixed_rate_noutput_to_ninput(int noutput); - - /*! - * \brief Return the number of items read on input stream which_input - */ - uint64_t nitems_read(unsigned int which_input); - - /*! - * \brief Return the number of items written on output stream which_output - */ - uint64_t nitems_written(unsigned int which_output); - - /*! - * \brief Asks for the policy used by the scheduler to moved tags downstream. - */ - tag_propagation_policy_t tag_propagation_policy(); - - /*! - * \brief Set the policy by the scheduler to determine how tags are moved downstream. - */ - void set_tag_propagation_policy(tag_propagation_policy_t p); - - /*! - * \brief Return the maximum number of output items this block will - * handle during a call to work. - */ - int max_noutput_items(); - - /*! - * \brief Set the maximum number of ouput items htis block will - * handle during a call to work. - * - * \param m the maximum noutput_items this block will handle. - */ - void set_max_noutput_items(int m); - - /*! - * \brief Clear the switch for using the max_noutput_items value of this block. - * - * When is_set_max_noutput_items() returns 'true', the scheduler - * will use the value returned by max_noutput_items() to limit the - * size of the number of items possible for this block's work - * function. If is_set_max_notput_items() returns 'false', then the - * scheduler ignores the internal value and uses the value set - * globally in the top_block. - * - * Use this value to clear the 'is_set' flag so the scheduler will - * ignore this. Use the set_max_noutput_items(m) call to both set a - * new value for max_noutput_items and to reenable its use in the - * scheduler. - */ - void unset_max_noutput_items(); - - /*! - * \brief Ask the block if the flag is or is not set to use the - * internal value of max_noutput_items during a call to work. - */ - bool is_set_max_noutput_items(); - - /* - * Used to expand the vectors that hold the min/max buffer sizes. - * - * Specifically, when -1 is used, the vectors are just initialized - * with 1 value; this is used by the flat_flowgraph to expand when - * required to add a new value for new ports on these blocks. - */ - void expand_minmax_buffer(int port) { - if((size_t)port >= d_max_output_buffer.size()) - set_max_output_buffer(port, -1); - if((size_t)port >= d_min_output_buffer.size()) - set_min_output_buffer(port, -1); - } - - /*! - * \brief Returns max buffer size on output port \p i. - */ - long max_output_buffer(size_t i) { - if(i >= d_max_output_buffer.size()) - throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range."); - return d_max_output_buffer[i]; - } - - /*! - * \brief Sets max buffer size on all output ports. - */ - void set_max_output_buffer(long max_output_buffer) { - for(int i = 0; i < output_signature()->max_streams(); i++) { - set_max_output_buffer(i, max_output_buffer); +typedef std::vector<int> gr_vector_int; +typedef std::vector<void *> gr_vector_void_star; +typedef std::vector<const void *> gr_vector_const_void_star; + +namespace gnuradio +{ +//! dummy entry, just here for legacy purposes +template <typename T> +boost::shared_ptr<T> get_initial_sptr(T *p) +{ + return boost::shared_ptr<T>(p); +} +} + +struct GR_CORE_API gr_block : gras::Block +{ + + gr_block(void); + + gr_block( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature + ); + + virtual ~gr_block(void); + + virtual bool check_topology(int ninputs, int noutputs); + + //! Overload me! I am the forecast + virtual void forecast(int, std::vector<int> &); + + //! Return options for the work call + enum + { + WORK_CALLED_PRODUCE = -2, + WORK_DONE = -1 + }; + + /*! + * \brief compute output items from input items + * + * \param noutput_items number of output items to write on each output stream + * \param ninput_items number of input items available on each input stream + * \param input_items vector of pointers to the input items, one entry per input stream + * \param output_items vector of pointers to the output items, one entry per output stream + * + * \returns number of items actually written to each output stream, or -1 on EOF. + * It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items + * + * general_work must call consume or consume_each to indicate how many items + * were consumed on each input stream. + */ + virtual int general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ); + + virtual bool start(void); + virtual bool stop(void); + + //! Call during work to consume items + void consume_each(const int how_many_items); + + void consume(const size_t i, const int how_many_items); + + void produce(const size_t o, const int how_many_items); + + //! Get absolute count of all items consumed on the given input port + uint64_t nitems_read(const size_t which_input = 0); + + //! Get absolute count of all items produced on the given output port + uint64_t nitems_written(const size_t which_output = 0); + + void add_item_tag( + const size_t which_output, const gr_tag_t &tag + ); + + void add_item_tag( + const size_t which_output, + uint64_t abs_offset, + const pmt::pmt_t &key, + const pmt::pmt_t &value, + const pmt::pmt_t &srcid=pmt::PMT_F + ); + + void get_tags_in_range( + std::vector<gr_tag_t> &tags, + const size_t which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key = pmt::pmt_t() + ); + + void set_alignment(const size_t alignment); + + bool is_unaligned(void); + + size_t fixed_rate_noutput_to_ninput(const size_t noutput_items); + + size_t interpolation(void) const; + + void set_interpolation(const size_t); + + size_t decimation(void) const; + + void set_decimation(const size_t); + + int max_noutput_items(void) const; + + void set_max_noutput_items(int); + + void unset_max_noutput_items(void); + + bool is_set_max_noutput_items(void) const; + + /******************************************************************* + * Deal with input and output port configuration + ******************************************************************/ + + unsigned history(void) const; + + void set_history(unsigned history); + + /*! + * Enable fixed rate logic. + * When enabled, relative rate is assumed to be set, + * and forecast is automatically called. + * Also, consume will be called automatically. + */ + void set_fixed_rate(const bool fixed_rate); + + //! Get the fixed rate setting + bool fixed_rate(void) const; + + /*! + * The relative rate can be thought of as interpolation/decimation. + * In other words, relative rate is the ratio of output items to input items. + */ + void set_relative_rate(const double relative_rate); + + //! Get the relative rate setting + double relative_rate(void) const; + + /*! + * The output multiple setting controls work output buffer sizes. + * Buffers will be number of items modulo rounted to the multiple. + */ + void set_output_multiple(const size_t multiple); + + //! Get the output multiple setting + size_t output_multiple(void) const; + + /******************************************************************* + * Deal with tag handling and tag configuration + ******************************************************************/ + + enum tag_propagation_policy_t + { + TPP_DONT = 0, + TPP_ALL_TO_ALL = 1, + TPP_ONE_TO_ONE = 2 + }; + + tag_propagation_policy_t tag_propagation_policy(void); + + void set_tag_propagation_policy(tag_propagation_policy_t p); + + ///////////// TODO ////////////////////// + void set_max_output_buffer(long){} + void set_max_output_buffer(int, long){} + long max_output_buffer(size_t){return 0;} + void set_min_output_buffer(long){} + void set_min_output_buffer(int, long){} + long min_output_buffer(size_t){return 0;} + + ///////////// ALIAS stuff - is it used? ////////////////////// + std::string d_symbol_alias; + std::string d_symbol_name; + std::string symbol_name() const { return d_symbol_name; } + bool alias_set() { return !d_symbol_alias.empty(); } + std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); } + pmt::pmt_t alias_pmt(){ return pmt::pmt_intern(alias()); } + void set_block_alias(std::string name){d_symbol_alias = name;} + + ///////////// MSG stuff not implemented ////////////////////// + typedef std::deque<pmt::pmt_t> msg_queue_t; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator> msg_queue_map_t; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator>::iterator msg_queue_map_itr; + msg_queue_map_t msg_queue; + pmt::pmt_t message_subscribers; + + template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler){} + + void message_port_register_in(pmt::pmt_t /*port_id*/){} + void message_port_register_out(pmt::pmt_t /*port_id*/){} + void message_port_pub(pmt::pmt_t /*port_id*/, pmt::pmt_t /*msg*/){} + void message_port_sub(pmt::pmt_t /*port_id*/, pmt::pmt_t /*target*/){} + void message_port_unsub(pmt::pmt_t /*port_id*/, pmt::pmt_t /*target*/){} + + virtual bool message_port_is_hier(pmt::pmt_t port_id) { (void) port_id; /*std::cout << "is_hier\n";*/ return false; } + virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { (void) port_id; /*std::cout << "is_hier_in\n";*/ return false; } + virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { (void) port_id; /*std::cout << "is_hier_out\n";*/ return false; } + + /*! + * \brief Get input message port names. + * + * Returns the available input message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_in(){return pmt::PMT_NIL;} + + /*! + * \brief Get output message port names. + * + * Returns the available output message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_out(){return pmt::PMT_NIL;} + + //! is the queue empty? + bool empty_p(pmt::pmt_t which_port) { + if(msg_queue.find(which_port) == msg_queue.end()) + throw std::runtime_error("port does not exist!"); + return msg_queue[which_port].empty(); } - } - - /*! - * \brief Sets max buffer size on output port \p port. - */ - void set_max_output_buffer(int port, long max_output_buffer) { - if((size_t)port >= d_max_output_buffer.size()) - d_max_output_buffer.push_back(max_output_buffer); - else - d_max_output_buffer[port] = max_output_buffer; - } - - /*! - * \brief Returns min buffer size on output port \p i. - */ - long min_output_buffer(size_t i) { - if(i >= d_min_output_buffer.size()) - throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range."); - return d_min_output_buffer[i]; - } - - /*! - * \brief Sets min buffer size on all output ports. - */ - void set_min_output_buffer(long min_output_buffer) { - for(int i=0; i<output_signature()->max_streams(); i++) { - set_min_output_buffer(i, min_output_buffer); + bool empty_p() { + bool rv = true; + BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue){ rv &= msg_queue[i.first].empty(); } + return rv; } - } - - /*! - * \brief Sets min buffer size on output port \p port. - */ - void set_min_output_buffer(int port, long min_output_buffer) { - if((size_t)port >= d_min_output_buffer.size()) - d_min_output_buffer.push_back(min_output_buffer); - else - d_min_output_buffer[port] = min_output_buffer; - } - - // ---------------------------------------------------------------------------- - - private: - - int d_output_multiple; - bool d_output_multiple_set; - int d_unaligned; - bool d_is_unaligned; - double d_relative_rate; // approx output_rate / input_rate - gr_block_detail_sptr d_detail; // implementation details - unsigned d_history; - bool d_fixed_rate; - bool d_max_noutput_items_set; // if d_max_noutput_items is valid - int d_max_noutput_items; // value of max_noutput_items for this block - tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream - - protected: - gr_block (void){} //allows pure virtual interface sub-classes - gr_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - - void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; } - - - /*! - * \brief Adds a new tag onto the given output buffer. - * - * \param which_output an integer of which output stream to attach the tag - * \param abs_offset a uint64 number of the absolute item number - * assicated with the tag. Can get from nitems_written. - * \param key the tag key as a PMT symbol - * \param value any PMT holding any value for the given key - * \param srcid optional source ID specifier; defaults to PMT_F - */ - inline void add_item_tag(unsigned int which_output, - uint64_t abs_offset, - const pmt::pmt_t &key, - const pmt::pmt_t &value, - const pmt::pmt_t &srcid=pmt::PMT_F) - { - gr_tag_t tag; - tag.offset = abs_offset; - tag.key = key; - tag.value = value; - tag.srcid = srcid; - this->add_item_tag(which_output, tag); + + //| Acquires and release the mutex + void insert_tail( pmt::pmt_t /*which_port*/, pmt::pmt_t /*msg*/){} + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_nowait( pmt::pmt_t /*which_port*/){return pmt::PMT_NIL;} + + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_blocking( pmt::pmt_t /*which_port*/){return pmt::PMT_NIL;} + + msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){ + return msg_queue[which_port].begin(); } - /*! - * \brief Adds a new tag onto the given output buffer. - * - * \param which_output an integer of which output stream to attach the tag - * \param tag the tag object to add - */ - void add_item_tag(unsigned int which_output, const gr_tag_t &tag); - - /*! - * \brief Given a [start,end), returns a vector of all tags in the range. - * - * Range of counts is from start to end-1. - * - * Tags are tuples of: - * (item count, source id, key, value) - * - * \param v a vector reference to return tags into - * \param which_input an integer of which input stream to pull from - * \param abs_start a uint64 count of the start of the range of interest - * \param abs_end a uint64 count of the end of the range of interest - */ - void get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end); - - /*! - * \brief Given a [start,end), returns a vector of all tags in the range - * with a given key. - * - * Range of counts is from start to end-1. - * - * Tags are tuples of: - * (item count, source id, key, value) - * - * \param v a vector reference to return tags into - * \param which_input an integer of which input stream to pull from - * \param abs_start a uint64 count of the start of the range of interest - * \param abs_end a uint64 count of the end of the range of interest - * \param key a PMT symbol key to filter only tags of this key - */ - void get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end, - const pmt::pmt_t &key); - - std::vector<long> d_max_output_buffer; - std::vector<long> d_min_output_buffer; - - - // These are really only for internal use, but leaving them public avoids - // having to work up an ever-varying list of friend GR_CORE_APIs - - public: - gr_block_detail_sptr detail () const { return d_detail; } - void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } -}; + void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){ + msg_queue[which_port].erase(it); + } + + virtual bool has_msg_port(pmt::pmt_t which_port){ + if(msg_queue.find(which_port) != msg_queue.end()){ + return true; + } + if(pmt::pmt_dict_has_key(message_subscribers, which_port)){ + return true; + } + return false; + } -typedef std::vector<gr_block_sptr> gr_block_vector_t; -typedef std::vector<gr_block_sptr>::iterator gr_block_viter_t; + ///////////////// private vars ////////////////////// -inline gr_block_sptr cast_to_block_sptr(gr_basic_block_sptr p) -{ - return boost::dynamic_pointer_cast<gr_block, gr_basic_block>(p); -} + gr_vector_int _work_ninput_items; + gr_vector_int _fcast_ninput_items; + gr_vector_const_void_star _work_input_items; + gr_vector_void_star _work_output_items; + ptrdiff_t _work_io_ptr_mask; + size_t _output_multiple_items; + double _relative_rate; + bool _enable_fixed_rate; + size_t _input_history_items; + tag_propagation_policy_t _tag_prop_policy; + size_t _interp, _decim; + + ///////////////// the Block overloads ////////////////////// + //! implements work -> calls general work + void work(const InputItems &, const OutputItems &); + + //! notifications of new topological commits + void notify_topology(const size_t, const size_t); + + //! start notification + void notify_active(void); + + //! stop notification + void notify_inactive(void); + + //! implements tag_propagation_policy() + virtual void propagate_tags(const size_t, const gras::TagIter &); + + void _update_input_reserve(void); + + gras::BufferQueueSptr input_buffer_allocator(const size_t, const gras::SBufferConfig &); + gras::BufferQueueSptr output_buffer_allocator(const size_t, const gras::SBufferConfig &); + +}; -std::ostream& -operator << (std::ostream& os, const gr_block *m); +typedef boost::shared_ptr<gr_block> gr_block_sptr; -#endif /* INCLUDED_GR_BLOCK_H */ +#endif /*INCLUDED_GNURADIO_GR_BLOCK_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc index 8c2794c63..c43f903a3 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc @@ -25,129 +25,28 @@ #endif #include <gr_hier_block2.h> -#include <gr_io_signature.h> -#include <gr_hier_block2_detail.h> -#include <iostream> -#define GR_HIER_BLOCK2_DEBUG 0 - -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 gnuradio::get_initial_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)), - hier_message_ports_in(pmt::PMT_NIL), - hier_message_ports_out(pmt::PMT_NIL) -{ - // This bit of magic ensures that self() works in the constructors of derived classes. - gnuradio::detail::sptr_magic::create_and_stash_initial_sptr(this); -} - -gr_hier_block2::~gr_hier_block2() -{ - delete d_detail; -} - -gr_hier_block2::opaque_self -gr_hier_block2::self() +gr_hier_block2::gr_hier_block2(void) { - return shared_from_this(); + //NOP } -gr_hier_block2_sptr -gr_hier_block2::to_hier_block2() +gr_hier_block2::gr_hier_block2( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature +): + gras::HierBlock(name) { - return cast_to_hier_block2_sptr(shared_from_this()); + this->set_input_signature(input_signature); + this->set_output_signature(output_signature); } -void -gr_hier_block2::connect(gr_basic_block_sptr block) -{ - d_detail->connect(block); -} - -void -gr_hier_block2::connect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port) -{ - d_detail->connect(src, src_port, dst, dst_port); -} - -void -gr_hier_block2::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport) -{ - if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); } - d_detail->msg_connect(src, srcport, dst, dstport); -} - -void -gr_hier_block2::msg_connect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport) -{ - d_detail->msg_connect(src, pmt::mp(srcport), dst, pmt::mp(dstport)); -} - -void -gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport) -{ - if(!pmt::pmt_is_symbol(srcport)){throw std::runtime_error("bad port id"); } - d_detail->msg_disconnect(src, srcport, dst, dstport); -} - -void -gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport) -{ - d_detail->msg_disconnect(src, pmt::mp(srcport), dst, pmt::mp(dstport)); -} - -void -gr_hier_block2::disconnect(gr_basic_block_sptr block) -{ - d_detail->disconnect(block); -} - -void -gr_hier_block2::disconnect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port) -{ - d_detail->disconnect(src, src_port, dst, dst_port); -} - -void -gr_hier_block2::disconnect_all() -{ - d_detail->disconnect_all(); -} - -void -gr_hier_block2::lock() -{ - d_detail->lock(); -} - -void -gr_hier_block2::unlock() -{ - d_detail->unlock(); -} - - -gr_flat_flowgraph_sptr -gr_hier_block2::flatten() const -{ - gr_flat_flowgraph_sptr new_ffg = gr_make_flat_flowgraph(); - d_detail->flatten_aux(new_ffg); - return new_ffg; +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)); } diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h index f80dd73e4..2ab04ac6f 100644 --- a/gnuradio-core/src/lib/runtime/gr_hier_block2.h +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h @@ -1,208 +1,49 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2007,2008,2009 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 3, 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 +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#ifndef INCLUDED_GNURADIO_GR_HIER_BLOCK2_H +#define INCLUDED_GNURADIO_GR_HIER_BLOCK2_H #include <gr_core_api.h> -#include <gr_basic_block.h> +#include <gras/hier_block.hpp> +#include <gr_io_signature.h> -/*! - * \brief public constructor for gr_hier_block2 - - */ -GR_CORE_API 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 Hierarchical container class for gr_block's and gr_hier_block2's - * \ingroup container_blk - * \ingroup base_blk - * - */ -class GR_CORE_API gr_hier_block2 : public gr_basic_block +struct GR_CORE_API gr_hier_block2 : gras::HierBlock { -private: - friend class gr_hier_block2_detail; - friend GR_CORE_API 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 (void){} //allows pure virtual interface sub-classes - gr_hier_block2(const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - -public: - virtual ~gr_hier_block2(); - - /*! - * \brief typedef for object returned from self(). - * - * This type is only guaranteed to be passable to connect and disconnect. - * No other assumptions should be made about it. - */ - typedef gr_basic_block_sptr opaque_self; - - /*! - * \brief Return an object, representing the current block, which can be passed to connect. - * - * The returned object may only be used as an argument to connect or disconnect. - * Any other use of self() results in unspecified (erroneous) behavior. - */ - opaque_self self(); - - /*! - * \brief Add a stand-alone (possibly hierarchical) block to internal graph - * - * This adds a gr-block or hierarchical block to the internal graph - * without wiring it to anything else. - */ - void connect(gr_basic_block_sptr block); - - /*! - * \brief Add gr-blocks or hierarchical blocks to internal graph and wire together - * - * This adds (if not done earlier by another connect) a pair of gr-blocks or - * hierarchical blocks to the internal flowgraph, and wires the specified output - * port to the specified input port. - */ - void connect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port); - - /*! - * \brief Add gr-blocks or hierarchical blocks to internal graph and wire together - * - * This adds (if not done earlier by another connect) a pair of gr-blocks or - * hierarchical blocks to the internal message port subscription - */ - void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport); - void msg_connect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport); - void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport); - void msg_disconnect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport); - - /*! - * \brief Remove a gr-block or hierarchical block from the internal flowgraph. - * - * This removes a gr-block or hierarchical block from the internal flowgraph, - * disconnecting it from other blocks as needed. - * - */ - void disconnect(gr_basic_block_sptr block); - /*! - * \brief Disconnect a pair of gr-blocks or hierarchical blocks in internal - * flowgraph. - * - * This disconnects the specified input port from the specified output port - * of a pair of gr-blocks or hierarchical blocks. - */ - void disconnect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port); + gr_hier_block2(void); - /*! - * \brief Disconnect all connections in the internal flowgraph. - * - * This call removes all output port to input port connections in the internal - * flowgraph. - */ - void disconnect_all(); + gr_hier_block2( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature + ); - /*! - * Lock a flowgraph in preparation for reconfiguration. When an equal - * number of calls to lock() and unlock() have occurred, the flowgraph - * will be reconfigured. - * - * N.B. lock() and unlock() may not be called from a flowgraph thread - * (E.g., gr_block::work method) or deadlock will occur when - * reconfiguration happens. - */ - virtual void lock(); - - /*! - * Unlock a flowgraph in preparation for reconfiguration. When an equal - * number of calls to lock() and unlock() have occurred, the flowgraph - * will be reconfigured. - * - * N.B. lock() and unlock() may not be called from a flowgraph thread - * (E.g., gr_block::work method) or deadlock will occur when - * reconfiguration happens. - */ - virtual void unlock(); - - // This is a public method for ease of code organization, but should be - // ignored by the user. - gr_flat_flowgraph_sptr flatten() const; - - gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion - - bool has_msg_port(pmt::pmt_t which_port){ - return message_port_is_hier(which_port) || gr_basic_block::has_msg_port(which_port); - } - - bool message_port_is_hier(pmt::pmt_t port_id){ - return message_port_is_hier_in(port_id) || message_port_is_hier_out(port_id); - } - bool message_port_is_hier_in(pmt::pmt_t port_id){ - return pmt::pmt_list_has(hier_message_ports_in, port_id); - } - bool message_port_is_hier_out(pmt::pmt_t port_id){ - return pmt::pmt_list_has(hier_message_ports_out, port_id); + const gr_hier_block2 &self(void) const + { + return *this; } - - pmt::pmt_t hier_message_ports_in; - pmt::pmt_t hier_message_ports_out; - - void message_port_register_hier_in(pmt::pmt_t port_id){ - if(pmt::pmt_list_has(hier_message_ports_in, port_id)) - throw std::invalid_argument("hier msg in port by this name already registered"); - if(msg_queue.find(port_id) != msg_queue.end()) - throw std::invalid_argument("block already has a primitive input port by this name"); - hier_message_ports_in = pmt::pmt_list_add(hier_message_ports_in, port_id); - } - void message_port_register_hier_out(pmt::pmt_t port_id){ - if(pmt::pmt_list_has(hier_message_ports_out, port_id)) - throw std::invalid_argument("hier msg out port by this name already registered"); - if(pmt::pmt_dict_has_key(message_subscribers, port_id)) - throw std::invalid_argument("block already has a primitive output port by this name"); - hier_message_ports_out = pmt::pmt_list_add(hier_message_ports_out, port_id); - } - }; -inline gr_hier_block2_sptr cast_to_hier_block2_sptr(gr_basic_block_sptr block) { - return boost::dynamic_pointer_cast<gr_hier_block2, gr_basic_block>(block); -} +typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; + +GR_CORE_API gr_hier_block2_sptr gr_make_hier_block2( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature +); -#endif /* INCLUDED_GR_HIER_BLOCK2_H */ +#endif /*INCLUDED_GNURADIO_GR_HIER_BLOCK2_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_io_signature.h b/gnuradio-core/src/lib/runtime/gr_io_signature.h index fd1825797..4c1eec4e8 100644 --- a/gnuradio-core/src/lib/runtime/gr_io_signature.h +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.h @@ -1,117 +1,84 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2007 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 3, 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_IO_SIGNATURE_H -#define INCLUDED_IO_SIGNATURE_H - -#include <gr_core_api.h> -#include <gr_runtime_types.h> - -/*! - * \brief Create an i/o signature - * - * \ingroup internal - * \param min_streams specify minimum number of streams (>= 0) - * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) - * \param sizeof_stream_item specify the size of the items in each stream - */ -GR_CORE_API gr_io_signature_sptr -gr_make_io_signature(int min_streams, int max_streams, - int sizeof_stream_item); - -/*! - * \brief Create an i/o signature - * - * \param min_streams specify minimum number of streams (>= 0) - * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) - * \param sizeof_stream_item1 specify the size of the items in the first stream - * \param sizeof_stream_item2 specify the size of the items in the second and subsequent streams - */ -GR_CORE_API gr_io_signature_sptr -gr_make_io_signature2(int min_streams, int max_streams, - int sizeof_stream_item1, - int sizeof_stream_item2 - ); - -/*! - * \brief Create an i/o signature - * - * \param min_streams specify minimum number of streams (>= 0) - * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) - * \param sizeof_stream_item1 specify the size of the items in the first stream - * \param sizeof_stream_item2 specify the size of the items in the second stream - * \param sizeof_stream_item3 specify the size of the items in the third and subsequent streams - */ -GR_CORE_API gr_io_signature_sptr -gr_make_io_signature3(int min_streams, int max_streams, - int sizeof_stream_item1, - int sizeof_stream_item2, - int sizeof_stream_item3 - ); - -/*! - * \brief Create an i/o signature - * - * \param min_streams specify minimum number of streams (>= 0) - * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) - * \param sizeof_stream_items specify the size of the items in the streams - * - * If there are more streams than there are entries in sizeof_stream_items, the - * value of the last entry in sizeof_stream_items is used for the missing values. - * sizeof_stream_items must contain at least 1 entry. - */ -GR_CORE_API gr_io_signature_sptr -gr_make_io_signaturev(int min_streams, int max_streams, - const std::vector<int> &sizeof_stream_items); - - -/*! - * \brief i/o signature for input and output ports. - * \brief misc - */ -class GR_CORE_API gr_io_signature { - int d_min_streams; - int d_max_streams; - std::vector<int> d_sizeof_stream_item; - - gr_io_signature(int min_streams, int max_streams, - const std::vector<int> &sizeof_stream_items); - - friend GR_CORE_API gr_io_signature_sptr - gr_make_io_signaturev(int min_streams, - int max_streams, - const std::vector<int> &sizeof_stream_items); - - public: - - static const int IO_INFINITE = -1; - - ~gr_io_signature (); - - int min_streams () const { return d_min_streams; } - int max_streams () const { return d_max_streams; } - int sizeof_stream_item (int index) const; - std::vector<int> sizeof_stream_items() const; -}; - - -#endif /* INCLUDED_IO_SIGNATURE_H */ +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#ifndef INCLUDED_GNURADIO_GR_IO_SIGNATURE_H +#define INCLUDED_GNURADIO_GR_IO_SIGNATURE_H + +#include <gras/io_signature.hpp> +#include <vector> + +typedef gras::IOSignature gr_io_signature; +typedef gr_io_signature gr_io_signature_sptr; + +inline gr_io_signature_sptr gr_make_io_signature( + int min_streams, + int max_streams, + int sizeof_stream_item +){ + gr_io_signature io_sig(min_streams, max_streams); + + if (io_sig.max_streams() != gr_io_signature::IO_INFINITE) + { + io_sig.resize(io_sig.max_streams(), sizeof_stream_item); + } + else + { + io_sig.resize(1, sizeof_stream_item); + } + + return io_sig; +} + +inline gr_io_signature_sptr gr_make_io_signature2( + int min_streams, + int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2 +){ + gr_io_signature io_sig(min_streams, max_streams); + io_sig.push_back(sizeof_stream_item1); + io_sig.push_back(sizeof_stream_item2); + return io_sig; +} + +inline gr_io_signature_sptr gr_make_io_signature3( + int min_streams, + int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2, + int sizeof_stream_item3 +){ + gr_io_signature io_sig(min_streams, max_streams); + io_sig.push_back(sizeof_stream_item1); + io_sig.push_back(sizeof_stream_item2); + io_sig.push_back(sizeof_stream_item3); + return io_sig; +} + +inline gr_io_signature_sptr gr_make_io_signaturev( + int min_streams, + int max_streams, + const std::vector<int> &sizeof_stream_items +){ + gr_io_signature io_sig(min_streams, max_streams); + for (unsigned i = 0; i < sizeof_stream_items.size(); i++) + { + io_sig.push_back(sizeof_stream_items[i]); + } + return io_sig; +} + +#endif /*INCLUDED_GNURADIO_GR_IO_SIGNATURE_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_sync_block.cc b/gnuradio-core/src/lib/runtime/gr_sync_block.cc index 94efcdc8e..96b5e6253 100644 --- a/gnuradio-core/src/lib/runtime/gr_sync_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_sync_block.cc @@ -26,43 +26,44 @@ #include <gr_sync_block.h> -gr_sync_block::gr_sync_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature) - : gr_block(name, input_signature, output_signature) +gr_sync_block::gr_sync_block(void) { - set_fixed_rate(true); + //NOP } - -void -gr_sync_block::forecast (int noutput_items, gr_vector_int &ninput_items_required) +gr_sync_block::gr_sync_block( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature +): + gr_block(name, input_signature, output_signature) { - unsigned ninputs = ninput_items_required.size(); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = fixed_rate_noutput_to_ninput (noutput_items); + this->set_fixed_rate(true); } -int -gr_sync_block::fixed_rate_noutput_to_ninput(int noutput_items) +gr_sync_block::~gr_sync_block(void) { - return noutput_items + history() - 1; + //NOP } -int -gr_sync_block::fixed_rate_ninput_to_noutput(int ninput_items) -{ - return std::max(0, ninput_items - (int)history() + 1); +int gr_sync_block::work( + int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items +){ + throw std::runtime_error("gr_block subclasses must overload general_work!"); } -int -gr_sync_block::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int r = work (noutput_items, input_items, output_items); - if (r > 0) - consume_each (r); - return r; +int gr_sync_block::general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items +){ + const int work_ret = this->work(noutput_items, input_items, output_items); + if (work_ret > 0) + { + this->consume_each((decimation()*size_t(work_ret))/interpolation()); + } + return work_ret; } diff --git a/gnuradio-core/src/lib/runtime/gr_sync_block.h b/gnuradio-core/src/lib/runtime/gr_sync_block.h index 1e4109b03..90370dd2b 100644 --- a/gnuradio-core/src/lib/runtime/gr_sync_block.h +++ b/gnuradio-core/src/lib/runtime/gr_sync_block.h @@ -1,66 +1,55 @@ -/* -*- 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 3, 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. - */ +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#ifndef INCLUDED_GNURADIO_GR_SYNC_BLOCK_H +#define INCLUDED_GNURADIO_GR_SYNC_BLOCK_H -#ifndef INCLUDED_GR_SYNC_BLOCK_H -#define INCLUDED_GR_SYNC_BLOCK_H - -#include <gr_core_api.h> #include <gr_block.h> -/*! - * \brief synchronous 1:1 input to output with history - * \ingroup base_blk - * - * Override work to provide the signal processing implementation. - */ -class GR_CORE_API gr_sync_block : public gr_block +struct GR_CORE_API gr_sync_block : public gr_block { - protected: - gr_sync_block (void){} //allows pure virtual interface sub-classes - gr_sync_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - - public: - - /*! - * \brief just like gr_block::general_work, only this arranges to call consume_each for you - * - * The user must override work to define the signal processing code - */ - virtual int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; - - - // gr_sync_block overrides these to assist work - void forecast (int noutput_items, gr_vector_int &ninput_items_required); - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_sync_block(void); + + gr_sync_block( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature + ); + + virtual ~gr_sync_block(void); + + //! implements work -> calls work + int general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ); + + /*! + * \brief just like gr_block::general_work, only this arranges to call consume_each for you + * + * The user must override work to define the signal processing code + */ + virtual int work( + int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ); - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); }; -#endif /* INCLUDED_GR_SYNC_BLOCK_H */ +#endif /*INCLUDED_GNURADIO_GR_SYNC_BLOCK_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_sync_decimator.cc b/gnuradio-core/src/lib/runtime/gr_sync_decimator.cc index a0f907db5..a39c53b09 100644 --- a/gnuradio-core/src/lib/runtime/gr_sync_decimator.cc +++ b/gnuradio-core/src/lib/runtime/gr_sync_decimator.cc @@ -26,44 +26,23 @@ #include <gr_sync_decimator.h> -gr_sync_decimator::gr_sync_decimator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned decimation) - : gr_sync_block (name, input_signature, output_signature) +gr_sync_decimator::gr_sync_decimator(void) { - set_decimation (decimation); + //NOP } -void -gr_sync_decimator::forecast (int noutput_items, gr_vector_int &ninput_items_required) +gr_sync_decimator::gr_sync_decimator( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + const size_t decim_rate +): + gr_sync_block(name, input_signature, output_signature) { - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); + this->set_decimation(decim_rate); } -int -gr_sync_decimator::fixed_rate_noutput_to_ninput(int noutput_items) +gr_sync_decimator::~gr_sync_decimator(void) { - return noutput_items * decimation() + history() - 1; + //NOP } - -int -gr_sync_decimator::fixed_rate_ninput_to_noutput(int ninput_items) -{ - return std::max(0, ninput_items - (int)history() + 1) / decimation(); -} - -int -gr_sync_decimator::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int r = work (noutput_items, input_items, output_items); - if (r > 0) - consume_each (r * decimation ()); - return r; -} - diff --git a/gnuradio-core/src/lib/runtime/gr_sync_decimator.h b/gnuradio-core/src/lib/runtime/gr_sync_decimator.h index 657aba985..dd7de7d1f 100644 --- a/gnuradio-core/src/lib/runtime/gr_sync_decimator.h +++ b/gnuradio-core/src/lib/runtime/gr_sync_decimator.h @@ -1,69 +1,38 @@ -/* -*- 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 3, 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. - */ +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#ifndef INCLUDED_GNURADIO_GR_SYNC_DECIMATOR_H +#define INCLUDED_GNURADIO_GR_SYNC_DECIMATOR_H -#ifndef INCLUDED_GR_SYNC_DECIMATOR_H -#define INCLUDED_GR_SYNC_DECIMATOR_H - -#include <gr_core_api.h> #include <gr_sync_block.h> -/*! - * \brief synchronous N:1 input to output with history - * \ingroup base_blk - * - * Override work to provide the signal processing implementation. - */ -class GR_CORE_API gr_sync_decimator : public gr_sync_block +struct GR_CORE_API gr_sync_decimator : gr_sync_block { - private: - unsigned d_decimation; - - protected: - gr_sync_decimator (void){} //allows pure virtual interface sub-classes - gr_sync_decimator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned decimation); - public: - unsigned decimation () const { return d_decimation; } - void set_decimation (unsigned decimation) - { - d_decimation = decimation; - set_relative_rate (1.0 / decimation); - } + gr_sync_decimator(void); - // gr_sync_decimator overrides these to assist work - void forecast (int noutput_items, gr_vector_int &ninput_items_required); - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_sync_decimator( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + const size_t decim_rate + ); - // derived classes should override work + virtual ~gr_sync_decimator(void); - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); }; - -#endif /* INCLUDED_GR_SYNC_DECIMATOR_H */ +#endif /*INCLUDED_GNURADIO_GR_SYNC_DECIMATOR_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_sync_interpolator.cc b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.cc index ece873c14..17f60e613 100644 --- a/gnuradio-core/src/lib/runtime/gr_sync_interpolator.cc +++ b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.cc @@ -26,45 +26,23 @@ #include <gr_sync_interpolator.h> -gr_sync_interpolator::gr_sync_interpolator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned interpolation) - : gr_sync_block (name, input_signature, output_signature) +gr_sync_interpolator::gr_sync_interpolator(void) { - set_interpolation (interpolation); + //NOP } -void -gr_sync_interpolator::forecast (int noutput_items, gr_vector_int &ninput_items_required) +gr_sync_interpolator::gr_sync_interpolator( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + const size_t interp_rate +): + gr_sync_block(name, input_signature, output_signature) { - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); + this->set_interpolation(interp_rate); } -int -gr_sync_interpolator::fixed_rate_noutput_to_ninput(int noutput_items) +gr_sync_interpolator::~gr_sync_interpolator(void) { - return noutput_items / interpolation() + history() - 1; + //NOP } - -int -gr_sync_interpolator::fixed_rate_ninput_to_noutput(int ninput_items) -{ - return std::max(0, ninput_items - (int)history() + 1) * interpolation(); -} - -int -gr_sync_interpolator::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int r = work (noutput_items, input_items, output_items); - if (r > 0) - consume_each (r / interpolation ()); - return r; -} - - diff --git a/gnuradio-core/src/lib/runtime/gr_sync_interpolator.h b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.h index 86d2fde43..0ed8c6f56 100644 --- a/gnuradio-core/src/lib/runtime/gr_sync_interpolator.h +++ b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.h @@ -1,70 +1,38 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2008 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 3, 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. - */ +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#ifndef INCLUDED_GNURADIO_GR_SYNC_INTERPOLATOR_H +#define INCLUDED_GNURADIO_GR_SYNC_INTERPOLATOR_H -#ifndef INCLUDED_GR_SYNC_INTERPOLATOR_H -#define INCLUDED_GR_SYNC_INTERPOLATOR_H - -#include <gr_core_api.h> #include <gr_sync_block.h> -/*! - * \brief synchronous 1:N input to output with history - * \ingroup base_blk - * - * Override work to provide the signal processing implementation. - */ -class GR_CORE_API gr_sync_interpolator : public gr_sync_block +struct GR_CORE_API gr_sync_interpolator : gr_sync_block { - private: - unsigned d_interpolation; - - protected: - gr_sync_interpolator (void){} //allows pure virtual interface sub-classes - gr_sync_interpolator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned interpolation); - public: - unsigned interpolation () const { return d_interpolation; } - void set_interpolation (unsigned interpolation) - { - d_interpolation = interpolation; - set_relative_rate (1.0 * interpolation); - set_output_multiple (interpolation); - } + gr_sync_interpolator(void); - // gr_sync_interpolator overrides these to assist work - void forecast (int noutput_items, gr_vector_int &ninput_items_required); - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_sync_interpolator( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + const size_t interp_rate + ); - // derived classes should override work + virtual ~gr_sync_interpolator(void); - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); }; - -#endif /* INCLUDED_GR_SYNC_INTERPOLATOR_H */ +#endif /*INCLUDED_GNURADIO_GR_SYNC_INTERPOLATOR_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.cc b/gnuradio-core/src/lib/runtime/gr_top_block.cc index e47473edd..da221c7d5 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block.cc +++ b/gnuradio-core/src/lib/runtime/gr_top_block.cc @@ -26,90 +26,65 @@ #include <unistd.h> #include <gr_top_block.h> -#include <gr_top_block_impl.h> -#include <gr_io_signature.h> -#include <iostream> -gr_top_block_sptr -gr_make_top_block(const std::string &name) +gr_top_block::gr_top_block(void): + //cannot make a null top block, use name constructor + gras::TopBlock("top") { - return gnuradio::get_initial_sptr(new gr_top_block(name)); + //NOP } -gr_top_block::gr_top_block(const std::string &name) - : gr_hier_block2(name, - gr_make_io_signature(0,0,0), - gr_make_io_signature(0,0,0)) - -{ - d_impl = new gr_top_block_impl(this); -} - -gr_top_block::~gr_top_block() -{ - stop(); - wait(); - - delete d_impl; -} - -void -gr_top_block::start(int max_noutput_items) +gr_top_block::gr_top_block(const std::string &name): + gras::TopBlock(name) { - d_impl->start(max_noutput_items); + //NOP } -void -gr_top_block::stop() +gr_top_block_sptr gr_make_top_block(const std::string &name) { - d_impl->stop(); + return gr_top_block_sptr(new gr_top_block(name)); } -void -gr_top_block::wait() +void gr_top_block::start(const size_t max_items) { - d_impl->wait(); + this->set_max_noutput_items(max_items); + this->start(); } -void -gr_top_block::run(int max_noutput_items) +void gr_top_block::run(const size_t max_items) { - start(max_noutput_items); - wait(); + this->set_max_noutput_items(max_items); + this->run(); } -void -gr_top_block::lock() +int gr_top_block::max_noutput_items(void) const { - d_impl->lock(); + return this->get_global_config().maximum_output_items; } -void -gr_top_block::unlock() +void gr_top_block::set_max_noutput_items(int max_items) { - d_impl->unlock(); + gras::GlobalBlockConfig config = this->get_global_config(); + config.maximum_output_items = max_items; + this->set_global_config(config); } -void -gr_top_block::dump() +void gr_top_block::run(void) { - d_impl->dump(); + gras::TopBlock::run(); } -int -gr_top_block::max_noutput_items() +void gr_top_block::start(void) { - return d_impl->max_noutput_items(); + gras::TopBlock::start(); } -void -gr_top_block::set_max_noutput_items(int nmax) +void gr_top_block::stop(void) { - d_impl->set_max_noutput_items(nmax); + gras::TopBlock::stop(); } -gr_top_block_sptr -gr_top_block::to_top_block() +void gr_top_block::wait(void) { - return cast_to_top_block_sptr(shared_from_this()); + gras::TopBlock::wait(); } diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.h b/gnuradio-core/src/lib/runtime/gr_top_block.h index 04d1e95e5..0126e9215 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block.h +++ b/gnuradio-core/src/lib/runtime/gr_top_block.h @@ -1,133 +1,53 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008,2009 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 3, 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_TOP_BLOCK_H -#define INCLUDED_GR_TOP_BLOCK_H +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#ifndef INCLUDED_GNURADIO_GR_TOP_BLOCK_H +#define INCLUDED_GNURADIO_GR_TOP_BLOCK_H #include <gr_core_api.h> +#include <gras/top_block.hpp> #include <gr_hier_block2.h> -class gr_top_block_impl; +struct GR_CORE_API gr_top_block : gras::TopBlock +{ -GR_CORE_API gr_top_block_sptr gr_make_top_block(const std::string &name); + gr_top_block(void); + + gr_top_block(const std::string &name); + + void start(const size_t max_items); + + void run(const size_t max_items); + + int max_noutput_items(void) const; + + void set_max_noutput_items(int max_items); + + void run(void); + + virtual void start(void); + + virtual void stop(void); + + virtual void wait(void); -/*! - *\brief Top-level hierarchical block representing a flowgraph - * \ingroup container_blk - * - */ -class GR_CORE_API gr_top_block : public gr_hier_block2 -{ -private: - friend GR_CORE_API gr_top_block_sptr gr_make_top_block(const std::string &name); - - gr_top_block_impl *d_impl; - -protected: - gr_top_block(const std::string &name); - -public: - ~gr_top_block(); - - /*! - * \brief The simple interface to running a flowgraph. - * - * Calls start() then wait(). Used to run a flowgraph that will stop - * on its own, or when another thread will call stop(). - * - * \param max_noutput_items the maximum number of output items - * allowed for any block in the flowgraph. This passes through to - * the start function; see that function for more details. - */ - void run(int max_noutput_items=100000); - - /*! - * Start the contained flowgraph. Creates one or more threads to - * execute the flow graph. Returns to the caller once the threads - * are created. Calling start() on a top_block that is already - * started IS an error. - * - * \param max_noutput_items the maximum number of output items - * allowed for any block in the flowgraph; the noutput_items can - * always be less than this, but this will cap it as a maximum. Use - * this to adjust the maximum latency a flowgraph can exhibit. - */ - void start(int max_noutput_items=100000); - - /*! - * Stop the running flowgraph. Notifies each thread created by the - * scheduler to shutdown, then returns to caller. Calling stop() on - * a top_block that is already stopped IS NOT an error. - */ - void stop(); - - /*! - * Wait for a flowgraph to complete. Flowgraphs complete when - * either (1) all blocks indicate that they are done (typically only - * when using gr.file_source, or gr.head, or (2) after stop() has been - * called to request shutdown. Calling wait on a top_block that is - * not running IS NOT an error (wait returns w/o blocking). - */ - void wait(); - - /*! - * Lock a flowgraph in preparation for reconfiguration. When an equal - * number of calls to lock() and unlock() have occurred, the flowgraph - * will be reconfigured. - * - * N.B. lock() and unlock() may not be called from a flowgraph thread - * (E.g., gr_block::work method) or deadlock will occur when - * reconfiguration happens. - */ - virtual void lock(); - - /*! - * Unlock a flowgraph in preparation for reconfiguration. When an equal - * number of calls to lock() and unlock() have occurred, the flowgraph - * will be reconfigured. - * - * N.B. lock() and unlock() may not be called from a flowgraph thread - * (E.g., gr_block::work method) or deadlock will occur when - * reconfiguration happens. - */ - virtual void unlock(); - - /*! - * Displays flattened flowgraph edges and block connectivity - */ - void dump(); - - //! Get the number of max noutput_items in the flowgraph - int max_noutput_items(); - - //! Set the maximum number of noutput_items in the flowgraph - void set_max_noutput_items(int nmax); - - gr_top_block_sptr to_top_block(); // Needed for Python type coercion }; -inline gr_top_block_sptr cast_to_top_block_sptr(gr_basic_block_sptr block) { - return boost::dynamic_pointer_cast<gr_top_block, gr_basic_block>(block); -} +typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr; +GR_CORE_API gr_top_block_sptr gr_make_top_block(const std::string &name); -#endif /* INCLUDED_GR_TOP_BLOCK_H */ +#endif /*INCLUDED_GNURADIO_GR_TOP_BLOCK_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_types.h b/gnuradio-core/src/lib/runtime/gr_types.h index ad6cee768..7b25a6811 100644 --- a/gnuradio-core/src/lib/runtime/gr_types.h +++ b/gnuradio-core/src/lib/runtime/gr_types.h @@ -1,64 +1,45 @@ -/* -*- 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 3, 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. - */ +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. -#ifndef INCLUDED_GR_TYPES_H -#define INCLUDED_GR_TYPES_H +#ifndef INCLUDED_GRNURADIO_TYPES_H +#define INCLUDED_GRNURADIO_TYPES_H -#include <gr_core_api.h> -#include <boost/shared_ptr.hpp> -#include <vector> -#include <stddef.h> // size_t +// this section is to satisfy swig includes for gras.i +// since gras.i includes gr_types.h, we only have to edit this file +#include <gras/io_signature.hpp> +#include <gras/element.hpp> +#include <gras/block.hpp> +#include <gras/top_block.hpp> +#include <gras/hier_block.hpp> -#include <gr_complex.h> +// and gnuradio apparently needs its own typedefs for stdint... +#ifdef __cplusplus -typedef std::vector<int> gr_vector_int; -typedef std::vector<float> gr_vector_float; -typedef std::vector<double> gr_vector_double; -typedef std::vector<void *> gr_vector_void_star; -typedef std::vector<const void *> gr_vector_const_void_star; +#include <boost/cstdint.hpp> +typedef boost::int16_t gr_int16; +typedef boost::int32_t gr_int32; +typedef boost::int64_t gr_int64; +typedef boost::uint16_t gr_uint16; +typedef boost::uint32_t gr_uint32; +typedef boost::uint64_t gr_uint64; -/* - * #include <config.h> must be placed beforehand - * in the source file including gr_types.h for - * the following to work correctly - */ -#ifdef HAVE_STDINT_H -#include <stdint.h> -typedef int16_t gr_int16; -typedef int32_t gr_int32; -typedef int64_t gr_int64; -typedef uint16_t gr_uint16; -typedef uint32_t gr_uint32; -typedef uint64_t gr_uint64; -#else -/* - * Note: these defaults may be wrong on 64-bit systems - */ -typedef short gr_int16; -typedef int gr_int32; -typedef long long gr_int64; -typedef unsigned short gr_uint16; -typedef unsigned int gr_uint32; -typedef unsigned long long gr_uint64; -#endif /* HAVE_STDINT_H */ +#include <complex> +typedef std::complex<float> gr_complex; +typedef std::complex<double> gr_complexd; -#endif /* INCLUDED_GR_TYPES_H */ +#endif + +#endif /* INCLUDED_GRNURADIO_TYPES_H */ diff --git a/gnuradio-core/src/lib/runtime/pmx_helper.hpp b/gnuradio-core/src/lib/runtime/pmx_helper.hpp new file mode 100644 index 000000000..4178daa06 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/pmx_helper.hpp @@ -0,0 +1,263 @@ +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#ifndef INCLUDED_LIBGRAS_PMX_HELPER_HPP +#define INCLUDED_LIBGRAS_PMX_HELPER_HPP + +#include <PMC/PMC.hpp> +#include <PMC/Containers.hpp> +#include <gruel/pmt.h> +#include <boost/foreach.hpp> + +namespace pmt +{ + +inline pmt_t pmc_to_pmt(const PMCC &p) +{ + //the container is null + if (not p) return pmt::pmt_t(); + + #define decl_pmc_to_pmt(type, conv) if (p.is<type >()) return conv(p.as<type >()) + + //bool + decl_pmc_to_pmt(bool, pmt_from_bool); + + //string + decl_pmc_to_pmt(std::string, pmt_string_to_symbol); + + //numeric types + decl_pmc_to_pmt(int8_t, pmt_from_long); + decl_pmc_to_pmt(int16_t, pmt_from_long); + decl_pmc_to_pmt(int32_t, pmt_from_long); + decl_pmc_to_pmt(uint8_t, pmt_from_long); + decl_pmc_to_pmt(uint16_t, pmt_from_long); + decl_pmc_to_pmt(uint32_t, pmt_from_long); + decl_pmc_to_pmt(int64_t, pmt_from_uint64); + decl_pmc_to_pmt(uint64_t, pmt_from_uint64); + decl_pmc_to_pmt(float, pmt_from_double); + decl_pmc_to_pmt(double, pmt_from_double); + #define pmt_from_complex(x) pmt_make_rectangular((x).real(), (x).imag()) + decl_pmc_to_pmt(std::complex<float>, pmt_from_complex); + decl_pmc_to_pmt(std::complex<double>, pmt_from_complex); + + //pair container + if (p.is<PMCPair>()) + { + const PMCPair &pr = p.as<PMCPair>(); + return pmt_cons(pmc_to_pmt(pr.first), pmc_to_pmt(pr.second)); + } + + //fucking tuples +/* +for i in range(11): + args = list() + for j in range(i): + args.append('pmc_to_pmt(p.as<PMCTuple<%d> >()[%d])'%(i, j)) + print ' if (p.is<PMCTuple<%d> >())'%i + print ' return pmt_make_tuple(%s);'%(', '.join(args),) +*/ + if (p.is<PMCTuple<0> >()) + return pmt_make_tuple(); + if (p.is<PMCTuple<1> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<1> >()[0])); + if (p.is<PMCTuple<2> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<2> >()[0]), pmc_to_pmt(p.as<PMCTuple<2> >()[1])); + if (p.is<PMCTuple<3> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<3> >()[0]), pmc_to_pmt(p.as<PMCTuple<3> >()[1]), pmc_to_pmt(p.as<PMCTuple<3> >()[2])); + if (p.is<PMCTuple<4> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<4> >()[0]), pmc_to_pmt(p.as<PMCTuple<4> >()[1]), pmc_to_pmt(p.as<PMCTuple<4> >()[2]), pmc_to_pmt(p.as<PMCTuple<4> >()[3])); + if (p.is<PMCTuple<5> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<5> >()[0]), pmc_to_pmt(p.as<PMCTuple<5> >()[1]), pmc_to_pmt(p.as<PMCTuple<5> >()[2]), pmc_to_pmt(p.as<PMCTuple<5> >()[3]), pmc_to_pmt(p.as<PMCTuple<5> >()[4])); + if (p.is<PMCTuple<6> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<6> >()[0]), pmc_to_pmt(p.as<PMCTuple<6> >()[1]), pmc_to_pmt(p.as<PMCTuple<6> >()[2]), pmc_to_pmt(p.as<PMCTuple<6> >()[3]), pmc_to_pmt(p.as<PMCTuple<6> >()[4]), pmc_to_pmt(p.as<PMCTuple<6> >()[5])); + if (p.is<PMCTuple<7> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<7> >()[0]), pmc_to_pmt(p.as<PMCTuple<7> >()[1]), pmc_to_pmt(p.as<PMCTuple<7> >()[2]), pmc_to_pmt(p.as<PMCTuple<7> >()[3]), pmc_to_pmt(p.as<PMCTuple<7> >()[4]), pmc_to_pmt(p.as<PMCTuple<7> >()[5]), pmc_to_pmt(p.as<PMCTuple<7> >()[6])); + if (p.is<PMCTuple<8> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<8> >()[0]), pmc_to_pmt(p.as<PMCTuple<8> >()[1]), pmc_to_pmt(p.as<PMCTuple<8> >()[2]), pmc_to_pmt(p.as<PMCTuple<8> >()[3]), pmc_to_pmt(p.as<PMCTuple<8> >()[4]), pmc_to_pmt(p.as<PMCTuple<8> >()[5]), pmc_to_pmt(p.as<PMCTuple<8> >()[6]), pmc_to_pmt(p.as<PMCTuple<8> >()[7])); + if (p.is<PMCTuple<9> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<9> >()[0]), pmc_to_pmt(p.as<PMCTuple<9> >()[1]), pmc_to_pmt(p.as<PMCTuple<9> >()[2]), pmc_to_pmt(p.as<PMCTuple<9> >()[3]), pmc_to_pmt(p.as<PMCTuple<9> >()[4]), pmc_to_pmt(p.as<PMCTuple<9> >()[5]), pmc_to_pmt(p.as<PMCTuple<9> >()[6]), pmc_to_pmt(p.as<PMCTuple<9> >()[7]), pmc_to_pmt(p.as<PMCTuple<9> >()[8])); + if (p.is<PMCTuple<10> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<10> >()[0]), pmc_to_pmt(p.as<PMCTuple<10> >()[1]), pmc_to_pmt(p.as<PMCTuple<10> >()[2]), pmc_to_pmt(p.as<PMCTuple<10> >()[3]), pmc_to_pmt(p.as<PMCTuple<10> >()[4]), pmc_to_pmt(p.as<PMCTuple<10> >()[5]), pmc_to_pmt(p.as<PMCTuple<10> >()[6]), pmc_to_pmt(p.as<PMCTuple<10> >()[7]), pmc_to_pmt(p.as<PMCTuple<10> >()[8]), pmc_to_pmt(p.as<PMCTuple<10> >()[9])); + + //vector container + if (p.is<PMCList>()) + { + const PMCList &l = p.as<PMCList>(); + pmt_t v = pmt_make_vector(l.size(), pmt_t()); + for (size_t i = 0; i < l.size(); i++) + { + pmt_vector_set(v, i, pmc_to_pmt(l[i])); + } + return v; + } + + //numeric arrays + #define decl_pmc_to_pmt_numeric_array(type, suffix) \ + if (p.is<std::vector<type> >()) return pmt_init_ ## suffix ## vector(p.as<std::vector<type> >().size(), &p.as<std::vector<type> >()[0]) + decl_pmc_to_pmt_numeric_array(uint8_t, u8); + decl_pmc_to_pmt_numeric_array(uint16_t, u16); + decl_pmc_to_pmt_numeric_array(uint32_t, u32); + decl_pmc_to_pmt_numeric_array(uint64_t, u64); + decl_pmc_to_pmt_numeric_array(int8_t, s8); + decl_pmc_to_pmt_numeric_array(int16_t, s16); + decl_pmc_to_pmt_numeric_array(int32_t, s32); + decl_pmc_to_pmt_numeric_array(int64_t, s64); + decl_pmc_to_pmt_numeric_array(float, f32); + decl_pmc_to_pmt_numeric_array(double, f64); + decl_pmc_to_pmt_numeric_array(std::complex<float>, c32); + decl_pmc_to_pmt_numeric_array(std::complex<double>, c64); + + //dictionary container + if (p.is<PMCDict>()) + { + const PMCDict &m = p.as<PMCDict>(); + pmt_t d = pmt_make_dict(); + BOOST_FOREACH(const PMCPair &pr, m) + { + d = pmt_dict_add(d, pmc_to_pmt(pr.first), pmc_to_pmt(pr.second)); + } + return d; + } + + //set container + if (p.is<PMCSet>()) + { + const PMCSet &s = p.as<PMCSet>(); + pmt_t l = PMT_NIL; + BOOST_FOREACH(const PMCC &elem, s) + { + l = pmt_list_add(l, pmc_to_pmt(elem)); + } + return l; + } + + //is it already a pmt? + if (p.is<pmt_t>()) return p.as<pmt_t>(); + + //backup plan... boost::any + return pmt_make_any(p); + +} + +inline PMCC pmt_to_pmc(const pmt_t &p) +{ + //if the container null? + if (not p) return PMC(); + + #define decl_pmt_to_pmc(check, conv) if (check(p)) return PMC_M(conv(p)) + + //bool + decl_pmt_to_pmc(pmt_is_bool, pmt_to_bool); + + //string (do object interning for strings) + decl_pmt_to_pmc(pmt_is_symbol, pmt_symbol_to_string).intern(); + + //numeric types + decl_pmt_to_pmc(pmt_is_integer, pmt_to_long); + decl_pmt_to_pmc(pmt_is_uint64, pmt_to_uint64); + decl_pmt_to_pmc(pmt_is_real, pmt_to_double); + decl_pmt_to_pmc(pmt_is_complex, pmt_to_complex); + + //is it a boost any holding a PMCC? + if (pmt_is_any(p)) + { + const boost::any a = pmt_any_ref(p); + if (a.type() == typeid(PMCC)) return boost::any_cast<PMCC>(a); + } + + //pair container + if (pmt_is_pair(p)) + { + PMCPair pr(pmt_to_pmc(pmt_car(p)), pmt_to_pmc(pmt_cdr(p))); + return PMC_M(pr); + } + + //fucking tuples + #define decl_pmt_to_pmc_tuple(n) \ + if (pmt_is_tuple(p) and pmt_length(p) == n) \ + { \ + PMCTuple<n> t; \ + for (size_t i = 0; i < n; i++) t[i] = pmt_to_pmc(pmt_tuple_ref(p, i)); \ + return PMC_M(t); \ + } + decl_pmt_to_pmc_tuple(0); + decl_pmt_to_pmc_tuple(1); + decl_pmt_to_pmc_tuple(2); + decl_pmt_to_pmc_tuple(3); + decl_pmt_to_pmc_tuple(4); + decl_pmt_to_pmc_tuple(5); + decl_pmt_to_pmc_tuple(6); + decl_pmt_to_pmc_tuple(7); + decl_pmt_to_pmc_tuple(8); + decl_pmt_to_pmc_tuple(9); + decl_pmt_to_pmc_tuple(10); + + //vector container + if (pmt_is_vector(p)) + { + PMCList l(pmt_length(p)); + for (size_t i = 0; i < l.size(); i++) + { + l[i] = pmt_to_pmc(pmt_vector_ref(p, i)); + } + return PMC_M(l); + } + + //numeric arrays + #define decl_pmt_to_pmc_numeric_array(type, suffix) \ + if (pmt_is_ ## suffix ## vector(p)) \ + { \ + size_t n; const type* i = pmt_ ## suffix ## vector_elements(p, n); \ + return PMC_M(std::vector<type>(i, i+n)); \ + } + decl_pmt_to_pmc_numeric_array(uint8_t, u8); + decl_pmt_to_pmc_numeric_array(uint16_t, u16); + decl_pmt_to_pmc_numeric_array(uint32_t, u32); + decl_pmt_to_pmc_numeric_array(uint64_t, u64); + decl_pmt_to_pmc_numeric_array(int8_t, s8); + decl_pmt_to_pmc_numeric_array(int16_t, s16); + decl_pmt_to_pmc_numeric_array(int32_t, s32); + decl_pmt_to_pmc_numeric_array(int64_t, s64); + decl_pmt_to_pmc_numeric_array(float, f32); + decl_pmt_to_pmc_numeric_array(double, f64); + decl_pmt_to_pmc_numeric_array(std::complex<float>, c32); + decl_pmt_to_pmc_numeric_array(std::complex<double>, c64); + + //dictionary container + if (pmt_is_dict(p)) + { + PMCDict m; + pmt_t items = pmt_dict_items(p); + for (size_t i = 0; i < pmt_length(items); i++) + { + pmt_t item = pmt_nth(i, items); + PMCC key = pmt_to_pmc(pmt_car(item)); + PMCC val = pmt_to_pmc(pmt_cdr(item)); + m[key] = val; + } + return PMC_M(m); + } + + //set container + //FIXME no pmt_is_list... + + //backup plan... store the pmt + return PMC_M(p); +} + +} + +#endif /*INCLUDED_LIBGRAS_PMX_HELPER_HPP*/ diff --git a/gnuradio-core/src/lib/runtime/qa_runtime.cc b/gnuradio-core/src/lib/runtime/qa_runtime.cc index 5e62c7991..9091d5c00 100644 --- a/gnuradio-core/src/lib/runtime/qa_runtime.cc +++ b/gnuradio-core/src/lib/runtime/qa_runtime.cc @@ -49,13 +49,13 @@ 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_flowgraph::suite ()); + //s->addTest (qa_gr_flowgraph::suite ()); s->addTest (qa_gr_top_block::suite ()); s->addTest (qa_gr_hier_block2::suite ()); s->addTest (qa_gr_hier_block2_derived::suite ()); s->addTest (qa_gr_buffer::suite ()); - s->addTest (qa_block_tags::suite ()); - s->addTest (qa_set_msg_handler::suite ()); + //s->addTest (qa_block_tags::suite ()); + //s->addTest (qa_set_msg_handler::suite ()); return s; } diff --git a/gnuradio-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i index 8e35df834..4dff7fabe 100644 --- a/gnuradio-core/src/lib/runtime/runtime.i +++ b/gnuradio-core/src/lib/runtime/runtime.i @@ -1,69 +1,89 @@ -/* -*- 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 3, 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. - */ +// +// Copyright 2012 Josh Blum +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. #define GR_CORE_API +//not here to fight you swig, reference() is ambigi with shared ptr, but whatevs +%ignore gri_agc_cc::reference(); +%ignore gri_agc2_ff::reference(); +%ignore gri_agc2_cc::reference(); + %{ -#include <gr_runtime_types.h> + +#include <gras/block.hpp> +#include <gras/hier_block.hpp> +#include <gras/top_block.hpp> +#include <gras/io_signature.hpp> #include <gr_io_signature.h> -#include <gr_buffer.h> #include <gr_block.h> -#include <gr_block_detail.h> +#include <gr_top_block.h> #include <gr_hier_block2.h> -#include <gr_single_threaded_scheduler.h> #include <gr_message.h> #include <gr_msg_handler.h> #include <gr_msg_queue.h> -#include <gr_dispatcher.h> -#include <gr_error_handler.h> -#include <gr_realtime.h> #include <gr_sync_block.h> #include <gr_sync_decimator.h> #include <gr_sync_interpolator.h> -#include <gr_top_block.h> + %} -%constant int sizeof_char = sizeof(char); -%constant int sizeof_short = sizeof(short); -%constant int sizeof_int = sizeof(int); -%constant int sizeof_float = sizeof(float); -%constant int sizeof_double = sizeof(double); -%constant int sizeof_gr_complex = sizeof(gr_complex); +%rename(io_signature) gr_make_io_signature; +%rename(io_signature2) gr_make_io_signature2; +%rename(io_signature3) gr_make_io_signature3; +%rename(io_signaturev) gr_make_io_signaturev; -%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_single_threaded_scheduler.i> %include <gr_message.i> %include <gr_msg_handler.i> %include <gr_msg_queue.i> -%include <gr_dispatcher.i> -%include <gr_error_handler.i> -%include <gr_realtime.i> -%include <gr_sync_block.i> -%include <gr_sync_decimator.i> -%include <gr_sync_interpolator.i> -%include <gr_top_block.i> +%include <gr_swig_block_magic.i> +%include <gr_io_signature.h> + +#ifdef SW_RUNTIME + +//const size types used by blocks in python +%constant int sizeof_char = sizeof(char); +%constant int sizeof_short = sizeof(short); +%constant int sizeof_int = sizeof(int); +%constant int sizeof_float = sizeof(float); +%constant int sizeof_double = sizeof(double); +%constant int sizeof_gr_complex = sizeof(gr_complex); + +%import <gras/block.i> +%include <gr_io_signature.h> +%include <gr_block.h> +%include <gr_hier_block2.h> +%include <gr_top_block.h> +%include <gr_sync_block.h> +%include <gr_sync_decimator.h> +%include <gr_sync_interpolator.h> + +#else + +//the bare minimum block inheritance interface to make things work but keep swig cxx file size down +%include <gras/gras.hpp> +%include <gras/element.hpp> +namespace gras +{ + struct Block : gras::Element{}; + struct HierBlock : gras::Element{}; +} +struct gr_hier_block2 : gras::HierBlock{}; +struct gr_block : gras::Block{}; +struct gr_sync_block : gr_block{}; +struct gr_sync_interpolator : gr_sync_block{}; +struct gr_sync_decimator : gr_sync_block{}; + +#endif |