summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gnuradio/block.hpp142
-rw-r--r--include/gnuradio/gr_block.h18
-rw-r--r--lib/block.cpp41
-rw-r--r--lib/block_allocator.cpp2
-rw-r--r--lib/block_handlers.cpp4
-rw-r--r--lib/block_task.cpp6
-rw-r--r--lib/gr_block.cpp2
-rw-r--r--lib/gras_impl/block_actor.hpp7
-rw-r--r--lib/topology_handler.cpp20
9 files changed, 146 insertions, 96 deletions
diff --git a/include/gnuradio/block.hpp b/include/gnuradio/block.hpp
index 87dda04..a7744fd 100644
--- a/include/gnuradio/block.hpp
+++ b/include/gnuradio/block.hpp
@@ -27,6 +27,57 @@
namespace gnuradio
{
+//! Configuration parameters for an input port
+struct GRAS_API InputPortConfig
+{
+ InputPortConfig(void);
+
+ /*!
+ * Set buffer inlining for this port config.
+ * Inlining means that the input buffer can be used as an output buffer.
+ * The goal is to make better use of cache and memory bandwidth.
+ *
+ * By default, inlining is disabled on all input ports.
+ * The user should enable inlining on an input port
+ * when it is understood that the work function will read
+ * before writting to a particular section of the buffer.
+ *
+ * The scheduler will inline a buffer when
+ * * inlining is enabled on the particular input port
+ * * block holds the only buffer reference aka unique
+ * * the input buffer has the same affinity as the block
+ * * the input port has a buffer look-ahead of 0
+ *
+ * Default = false.
+ */
+ bool inline_buffer;
+
+ /*!
+ * Set the number of input buffer look-ahead items.
+ * When num look-ahead items are not consumed,
+ * they will be available for the next work call.
+ * This is used to implement sample memory for
+ * things like sliding dot products/FIR filters.
+ *
+ * Default = 0.
+ */
+ size_t lookahead_items;
+};
+
+//! Configuration parameters for an output port
+struct GRAS_API OutputPortConfig
+{
+ OutputPortConfig(void);
+
+ /*!
+ * Set an output reserve requirement such that work is called
+ * with an output buffer at least reserve items in size.
+ *
+ * Default = 1.
+ */
+ size_t reserve_items;
+};
+
template <typename PtrType> struct WorkBuffer
{
//! get a native pointer type to this buffer
@@ -65,68 +116,28 @@ template <typename PtrType> struct WorkBuffer
struct GRAS_API Block : Element
{
- 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
- };
+ //! Contruct an empty/null block
Block(void);
+ //! Create a new block given the name
Block(const std::string &name);
/*******************************************************************
- * Basic routines from basic block
+ * Deal with input and output port configuration
******************************************************************/
- //! Get the number of history items (default 0)
- size_t input_history(const size_t which_input = 0) const;
-
- /*!
- * Set the number of items that will be saved from the previous run.
- * Input buffers will begin with an overlap of the previous's buffer's
- * num history items. This is used to implement sample memory for
- * things like sliding dot products/FIR filters.
- */
- void set_input_history(const size_t history, const size_t which_input = 0);
-
- void set_output_multiple(const size_t multiple, const size_t which_output = 0);
-
- size_t output_multiple(const size_t which_output = 0) const;
-
- void consume(const size_t which_input, const size_t how_many_items);
-
- void consume_each(const size_t how_many_items);
+ //! Get the configuration rules of an input port
+ InputPortConfig input_config(const size_t which_input = 0) const;
- void produce(const size_t which_output, const size_t how_many_items);
+ //! Set the configuration rules for an input port
+ void set_input_config(const InputPortConfig &config, const size_t which_input = 0);
- /*!
- * Set buffer inlining for this input.
- * Inlining means that the input buffer can be used as an output buffer.
- * The goal is to make better use of cache and memory bandwidth.
- *
- * By default, inlining is disabled on all input ports.
- * The user should enable inlining on an input port
- * when it is understood that the work function will read
- * before writting to a particular section of the buffer.
- *
- * The scheduler will inline a buffer when
- * * inlining is enabled on the particular input port
- * * block holds the only buffer reference aka unique
- * * the input buffer has the same affinity as the block
- * * the input port has a buffer history of 0 items
- */
- void set_input_inline(const size_t which_input, const bool enb);
+ //! Get the configuration rules of an output port
+ OutputPortConfig output_config(const size_t which_output = 0) const;
- //! Get the buffer inlining state
- bool input_inline(const size_t which_input) const;
+ //! Set the configuration rules for an output port
+ void set_output_config(const OutputPortConfig &config, const size_t which_output = 0);
/*!
* Enable fixed rate logic.
@@ -145,9 +156,36 @@ struct GRAS_API Block : Element
double relative_rate(void) const;
/*******************************************************************
- * Tag related routines from basic block
+ * Deal with data production and consumption
******************************************************************/
+ //! Return options for the work call
+ enum
+ {
+ WORK_CALLED_PRODUCE = -2,
+ WORK_DONE = -1
+ };
+
+ //! Call during work to consume items
+ void consume(const size_t which_input, const size_t how_many_items);
+
+ //! Call during work to consume items
+ void consume_each(const size_t how_many_items);
+
+ //! Call during work to produce items, must return WORK_CALLED_PRODUCE
+ void produce(const size_t which_output, const size_t how_many_items);
+
+ /*******************************************************************
+ * 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
+ };
+
uint64_t nitems_read(const size_t which_input);
uint64_t nitems_written(const size_t which_output);
diff --git a/include/gnuradio/gr_block.h b/include/gnuradio/gr_block.h
index fc87ccf..d46e252 100644
--- a/include/gnuradio/gr_block.h
+++ b/include/gnuradio/gr_block.h
@@ -80,14 +80,28 @@ struct GRAS_API gr_block : gnuradio::Block
unsigned history(void) const
{
//implement off-by-one history compat
- return this->input_history()+1;
+ return this->input_config().lookahead_items+1;
}
void set_history(unsigned history)
{
+ gnuradio::InputPortConfig config = this->input_config();
//implement off-by-one history compat
if (history == 0) history++;
- this->set_input_history(history-1);
+ config.lookahead_items = history-1;
+ this->set_input_config(config);
+ }
+
+ unsigned output_multiple(void) const
+ {
+ return this->output_config().reserve_items+1;
+ }
+
+ void set_output_multiple(unsigned multiple)
+ {
+ gnuradio::OutputPortConfig config = this->output_config();
+ config.reserve_items = multiple;
+ this->set_output_config(config);
}
void set_alignment(const size_t alignment);
diff --git a/lib/block.cpp b/lib/block.cpp
index 75fd910..e4a0d0a 100644
--- a/lib/block.cpp
+++ b/lib/block.cpp
@@ -19,6 +19,17 @@
using namespace gnuradio;
+InputPortConfig::InputPortConfig(void)
+{
+ inline_buffer = false;
+ lookahead_items = 0;
+}
+
+OutputPortConfig::OutputPortConfig(void)
+{
+ reserve_items = 1;
+}
+
Block::Block(void)
{
//NOP
@@ -38,8 +49,8 @@ Block::Block(const std::string &name):
(*this)->block->block_state = BlockActor::BLOCK_STATE_INIT;
//call block methods to init stuff
- this->set_input_history(0);
- this->set_output_multiple(1);
+ this->set_input_config(InputPortConfig());
+ this->set_output_config(OutputPortConfig());
this->set_fixed_rate(true);
this->set_relative_rate(1.0);
this->set_tag_propagation_policy(TPP_ALL_TO_ALL);
@@ -65,26 +76,26 @@ typename V::value_type vector_get(const V &v, const size_t index)
return v[index];
}
-size_t Block::input_history(const size_t which_input) const
+InputPortConfig Block::input_config(const size_t which_input) const
{
- return vector_get((*this)->block->input_history_items, which_input);
+ return vector_get((*this)->block->input_configs, which_input);
}
-void Block::set_input_history(const size_t history, const size_t which_input)
+void Block::set_input_config(const InputPortConfig &config, const size_t which_input)
{
- vector_set((*this)->block->input_history_items, history, which_input);
+ vector_set((*this)->block->input_configs, config, which_input);
if ((*this)->block->topology_init)
(*this)->block->Push(UpdateInputsMessage(), Theron::Address());
}
-size_t Block::output_multiple(const size_t which_output) const
+OutputPortConfig Block::output_config(const size_t which_output) const
{
- return vector_get((*this)->block->output_multiple_items, which_output);
+ return vector_get((*this)->block->output_configs, which_output);
}
-void Block::set_output_multiple(const size_t multiple, const size_t which_output)
+void Block::set_output_config(const OutputPortConfig &config, const size_t which_output)
{
- vector_set((*this)->block->output_multiple_items, multiple, which_output);
+ vector_set((*this)->block->output_configs, config, which_output);
if ((*this)->block->topology_init)
(*this)->block->Push(UpdateInputsMessage(), Theron::Address());
}
@@ -109,16 +120,6 @@ void Block::produce(const size_t which_output, const size_t how_many_items)
(*this)->block->produce_items[which_output] += how_many_items;
}
-void Block::set_input_inline(const size_t which_input, const bool enb)
-{
- vector_set((*this)->block->input_inline_enables, enb, which_input);
-}
-
-bool Block::input_inline(const size_t which_input) const
-{
- return vector_get((*this)->block->input_inline_enables, which_input);
-}
-
void Block::set_fixed_rate(const bool fixed_rate)
{
(*this)->block->enable_fixed_rate = fixed_rate;
diff --git a/lib/block_allocator.cpp b/lib/block_allocator.cpp
index 950fddb..d2d7424 100644
--- a/lib/block_allocator.cpp
+++ b/lib/block_allocator.cpp
@@ -90,7 +90,7 @@ void BlockActor::handle_top_alloc(const TopAllocMessage &, const Theron::Address
const size_t bytes = recommend_length(
this->output_allocation_hints[i],
- this->output_multiple_items[i]*this->output_items_sizes[i],
+ this->output_configs[i].reserve_items*this->output_items_sizes[i],
at_least_items*this->output_items_sizes[i]
);
diff --git a/lib/block_handlers.cpp b/lib/block_handlers.cpp
index 694f781..59feecf 100644
--- a/lib/block_handlers.cpp
+++ b/lib/block_handlers.cpp
@@ -85,8 +85,8 @@ void BlockActor::handle_top_token(
//TODO, schedule this message as a pre-allocation message
//tell the upstream about the input requirements
OutputHintMessage output_hints;
- output_hints.history_bytes = this->input_history_items[i]*this->input_items_sizes[i];
- output_hints.reserve_bytes = this->input_multiple_items[i];
+ output_hints.history_bytes = this->input_configs[i].lookahead_items*this->input_items_sizes[i];
+ output_hints.reserve_bytes = this->input_reserve_items[i];
output_hints.token = this->input_tokens[i];
this->post_upstream(i, output_hints);
diff --git a/lib/block_task.cpp b/lib/block_task.cpp
index f18b9d4..960b41e 100644
--- a/lib/block_task.cpp
+++ b/lib/block_task.cpp
@@ -120,7 +120,7 @@ void BlockActor::handle_task(void)
//continue;
if (
potential_inline and
- input_inline_enables[i] and
+ input_configs[i].inline_buffer and
output_inline_index < num_outputs and
buff.get_affinity() == this->buffer_affinity
){
@@ -159,10 +159,6 @@ void BlockActor::handle_task(void)
{
forecast_again_you_jerk:
fcast_ninput_items = work_ninput_items;
- {
- num_output_items /= this->output_multiple_items.front();
- num_output_items *= this->output_multiple_items.front();
- }
block_ptr->forecast(num_output_items, fcast_ninput_items);
for (size_t i = 0; i < num_inputs; i++)
{
diff --git a/lib/gr_block.cpp b/lib/gr_block.cpp
index 20acecc..4b3335b 100644
--- a/lib/gr_block.cpp
+++ b/lib/gr_block.cpp
@@ -72,7 +72,7 @@ bool gr_block::is_unaligned(void)
size_t gr_block::fixed_rate_noutput_to_ninput(const size_t noutput_items)
{
- return (*this)->block->input_history_items[0] +
+ return (*this)->block->input_configs[0].lookahead_items +
size_t((noutput_items/this->relative_rate()));
}
diff --git a/lib/gras_impl/block_actor.hpp b/lib/gras_impl/block_actor.hpp
index 0d193b0..14bfacc 100644
--- a/lib/gras_impl/block_actor.hpp
+++ b/lib/gras_impl/block_actor.hpp
@@ -114,10 +114,9 @@ struct BlockActor : Apology::Worker
//per port properties
std::vector<size_t> input_items_sizes;
std::vector<size_t> output_items_sizes;
- std::vector<size_t> input_history_items;
- std::vector<size_t> output_multiple_items;
- std::vector<size_t> input_multiple_items;
- std::vector<bool> input_inline_enables;
+ std::vector<InputPortConfig> input_configs;
+ std::vector<OutputPortConfig> output_configs;
+ std::vector<size_t> input_reserve_items;
//keeps track of production
std::vector<uint64_t> items_consumed;
diff --git a/lib/topology_handler.cpp b/lib/topology_handler.cpp
index 555e8c9..7e0c710 100644
--- a/lib/topology_handler.cpp
+++ b/lib/topology_handler.cpp
@@ -38,7 +38,7 @@ void resize_fill_grow(V &v, const size_t new_len, const T &fill)
template <typename V>
void resize_fill_back(V &v, const size_t new_len)
{
- if (v.empty()) v.push_back(0);
+ if (v.empty()) v.resize(1);
resize_fill_grow(v, new_len, v.back());
}
@@ -59,9 +59,8 @@ void BlockActor::handle_topology(
fill_item_sizes_from_sig(this->output_items_sizes, block_ptr->output_signature(), num_outputs);
//resize and fill port properties
- resize_fill_back(this->input_history_items, num_inputs);
- resize_fill_back(this->output_multiple_items, num_outputs);
- resize_fill_grow(this->input_inline_enables, num_inputs, false);
+ resize_fill_back(this->input_configs, num_inputs);
+ resize_fill_back(this->output_configs, num_outputs);
//resize the bytes consumed/produced
resize_fill_grow(this->items_consumed, num_inputs, 0);
@@ -111,18 +110,21 @@ void BlockActor::handle_update_inputs(
const size_t num_outputs = this->get_num_outputs();
//impose input reserve requirements based on relative rate and output multiple
- resize_fill_grow(this->input_multiple_items, num_inputs, 1);
+ resize_fill_grow(this->input_reserve_items, num_inputs, 1);
+ std::vector<size_t> input_lookahead_items(num_inputs);
for (size_t i = 0; i < num_inputs; i++)
{
+ input_lookahead_items[i] = this->input_configs[i].lookahead_items;
+
//TODO, this is a little cheap, we only look at output multiple [0]
- const size_t multiple = (num_outputs)?this->output_multiple_items.front():1;
+ const size_t multiple = (num_outputs)?this->output_configs.front().reserve_items:1;
if (this->enable_fixed_rate)
{
- this->input_multiple_items[i] = size_t(std::ceil(multiple/this->relative_rate));
+ this->input_reserve_items[i] = size_t(std::ceil(multiple/this->relative_rate));
}
- if (this->input_multiple_items[i] == 0) this->input_multiple_items[i] = 1;
+ if (this->input_reserve_items[i] == 0) this->input_reserve_items[i] = 1;
}
//init the history comprehension on input queues
- this->input_queues.init(this->input_history_items, this->input_multiple_items, this->input_items_sizes);
+ this->input_queues.init(input_lookahead_items, this->input_reserve_items, this->input_items_sizes);
}