summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.cc30
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.h28
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.cc41
3 files changed, 96 insertions, 3 deletions
diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc
index 9463869f5..78f77486b 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block.cc
@@ -34,6 +34,9 @@ gr_block::gr_block (const std::string &name,
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),
@@ -75,10 +78,37 @@ gr_block::set_output_multiple (int multiple)
if (multiple < 1)
throw std::invalid_argument ("gr_block::set_output_multiple");
+ d_output_multiple_set = true;
d_output_multiple = multiple;
}
void
+gr_block::set_alignment (int multiple)
+{
+ if (multiple < 1)
+ throw std::invalid_argument ("gr_block::set_alignment_multiple");
+
+ d_output_multiple = multiple;
+}
+
+void
+gr_block::set_unaligned (int na)
+{
+ // 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");
+
+ d_unaligned = na;
+}
+
+void
+gr_block::set_is_unaligned (bool u)
+{
+ d_is_unaligned = u;
+}
+
+void
gr_block::set_relative_rate (double relative_rate)
{
if (relative_rate < 0.0)
diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h
index 86e0583e9..9171942e0 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_block.h
@@ -152,8 +152,33 @@ class GR_CORE_API gr_block : public gr_basic_block {
*/
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);
@@ -231,6 +256,9 @@ class GR_CORE_API gr_block : public gr_basic_block {
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;
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
index ef53baf78..1c52c0e13 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
@@ -36,7 +36,7 @@
#include <stdio.h>
// must be defined to either 0 or 1
-#define ENABLE_LOGGING 0
+#define ENABLE_LOGGING 1
#if (ENABLE_LOGGING)
#define LOG(x) do { x; } while(0)
@@ -183,6 +183,7 @@ gr_block_executor::run_one_iteration()
int noutput_items;
int max_items_avail;
int max_noutput_items = d_max_noutput_items;
+ int new_alignment;
gr_block *m = d_block.get();
gr_block_detail *d = m->detail().get();
@@ -284,7 +285,7 @@ gr_block_executor::run_one_iteration()
}
// determine the minimum available output space
- noutput_items = min_available_space (d, m->output_multiple ());
+ noutput_items = min_available_space (d, m->output_multiple ()) - m->output_multiple();
if (ENABLE_LOGGING){
*d_log << " regular ";
if (m->relative_rate() >= 1.0)
@@ -307,7 +308,11 @@ gr_block_executor::run_one_iteration()
// try to work it forward starting with max_items_avail.
// We want to try to consume all the input we've got.
int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail);
- reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple());
+
+ // only test this if we specifically set the output_multiple
+ if(m->output_multiple_set())
+ reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple());
+
if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items)
noutput_items = reqd_noutput_items;
@@ -316,6 +321,30 @@ gr_block_executor::run_one_iteration()
}
noutput_items = std::min(noutput_items, max_noutput_items);
+ // Check if we're still unaligned; only use up items until we're
+ // aligned again. Otherwise, make sure we set the alignment
+ // requirement.
+ if(m->is_unaligned()) {
+ if(noutput_items >= m->unaligned()) {
+ noutput_items = round_up(noutput_items, m->alignment()) \
+ - (m->alignment() - m->unaligned());
+ new_alignment = 0;
+ }
+ else {
+ new_alignment = m->unaligned() - noutput_items;
+ }
+ }
+ else if(noutput_items < m->alignment()) {
+ //m->set_unaligned(m->alignment());
+ new_alignment = m->alignment() - noutput_items;
+ m->set_unaligned(new_alignment);
+ m->set_is_unaligned(true);
+ }
+ else {
+ noutput_items = round_down(noutput_items, m->alignment());
+ m->set_is_unaligned(false);
+ }
+
// ask the block how much input they need to produce noutput_items
m->forecast (noutput_items, d_ninput_items_required);
@@ -379,6 +408,12 @@ gr_block_executor::run_one_iteration()
LOG(*d_log << " general_work: noutput_items = " << noutput_items
<< " result = " << n << std::endl);
+ // Adjust number of unaligned items left to process
+ if(m->is_unaligned()) {
+ m->set_unaligned(new_alignment);
+ m->set_is_unaligned(m->unaligned() != 0);
+ }
+
if(!propagate_tags(m->tag_propagation_policy(), d,
d_start_nitems_read, m->relative_rate(),
d_returned_tags))