summaryrefslogtreecommitdiff
path: root/docs/doxygen/other
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2013-07-07 22:26:29 +0100
committerJohnathan Corgan <johnathan@corganlabs.com>2013-07-16 14:37:38 -0700
commit7c0b10389a609115d8c01591f2c8945a10cd7c83 (patch)
treee8a83bb9ce30560623f13a154110f2b45a35e334 /docs/doxygen/other
parent86eecfa37460080b8285395bb46baf90137e1b9e (diff)
docs: added documentation of the stream tags interface.
Diffstat (limited to 'docs/doxygen/other')
-rw-r--r--docs/doxygen/other/stream_tags.dox224
1 files changed, 224 insertions, 0 deletions
diff --git a/docs/doxygen/other/stream_tags.dox b/docs/doxygen/other/stream_tags.dox
new file mode 100644
index 0000000000..cc44d8e318
--- /dev/null
+++ b/docs/doxygen/other/stream_tags.dox
@@ -0,0 +1,224 @@
+/*! \page page_stream_tags Stream Tags
+
+\section Introduction
+
+GNU Radio was originally a streaming system with no other mechanism to
+pass data between blocks. Streams of data are a model that work well
+for samples, bits, etc., but can lack for control and meta data.
+
+Part of this is solved using the message passing interface, which
+allows blocks to subscribe to messages published by any other block in
+the flowgraph (see \ref page_msg_passing). The main drawback to the
+message passing system is that is works asynchronously, meaning that
+there is no guarantee when a message may arrive relative to the data
+stream.
+
+Stream tags are an isosynchronous data stream that runs parallel to
+the main data stream. A stream \a tag is generated by a block's work
+function and from there on flows downstream with a particular sample
+until it reaches a sink or is forced to stop propagating by another
+block.
+
+Stream tags are defined for a specific item in the data stream and are
+formed as a key:value pair. The \a key identifies what the \a value is
+while the value holds the data that the tag contains. Both \a key and
+\a value are PMTs (\ref page_pmt) where the \a key is a PMT symbol while
+the \a value any type of PMT and can therefore handle any data we wish
+to pass. A fourth part of the tag is the \a srcid, which is a PMT
+symbol and is used to identify the block that created the tag (which
+is usually the block's alias()).
+
+
+\section block_api_extensions API Extensions to the gr::block
+
+To enable the stream tags, we have extended the API of gr::block to
+understand \a absolute item numbers. In the data stream model, each
+block's work function is given a buffer in the data stream that is
+referenced from 0 to N-1. This is a \a relative offset into the data
+stream. The absolute reference starts from the beginning of the
+flowgraph and continues to count up with ever item. Each input stream
+is associated with a concept of the 'number of items read' and each
+output stream has a 'number of items written.' These are programmed
+using the two API calls:
+
+\code
+unsigned long int nitems_read(unsigned int which_input);
+unsigned long int nitems_written(unsigned int which_output);
+\endcode
+
+Each tag is associated with some item in this absolute time scale that
+is calculated using these functions.
+
+Like the rest of the data stream, the number of items read/written are
+only updated once during the call to work. So in a work function,
+nitems_read/written will refer to the state of the data stream at the
+start of the work function. We must therefore add to this value the
+current relative offset in the data stream. So if we are iterating \a
+i over all output items, we would write the stream tag to output ports
+at <em>nitems_written(0)+i</em> for the 0th output port.
+
+
+\section stream_tags_api Stream Tags API
+
+The stream tags API consists of four functions, two to add and two to
+get the stream tags. These functions are:
+
+\li add_item_tag: Adds an item tag to a particular output port using a
+gr::tag_t data type.
+\li add_item_tag: Adds an item tag to a particular output port where
+each value of the tag is explicitly given.
+\li get_tags_in_range: Gets all tags from a particular input port between
+a certain range of items (in absolute item time).
+\li get_tags_in_range: Gets any tag that has a specified key from a
+particular input port between a certain range of items (in absolute
+item time).
+
+
+\subsection add_item_tag Adding a Tag to a Stream
+
+The two function calls to add items tags are defined here. We add a
+tag to a particular output stream of the block. We can output them to
+multiple output streams if we want, but to do so means calling one of
+these functions once for each port.
+
+Again, a tag is defined as:
+
+\li offset: The offset, in absolute item time, of the tag in the data
+stream.
+\li key: the PMT symbol identifying the type of tag.
+\li value: the PMT holding the data of the tag.
+\li srcid: (optional) the PMT symbol identifying the block which
+created the tag.
+
+We can create a gr::tag_t structure to hold all of the above
+information of a tag, which is probably the easiest/best way to do
+it. The gr::tag_t struct is defined as having the same members as in
+the above list. To add a gr::tag_t tag to a stream, use the function:
+
+\code
+ void add_item_tag(unsigned int which_output, const tag_t &tag);
+\endcode
+
+The secondary API allows us to create a tag by explicitly listing all
+of the tag information in the function call:
+
+\code
+ 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);
+\endcode
+
+
+\subsection get_item_tags Getting tags from a Stream
+
+To get tags from a particular input stream, we again have two
+functions we can use. Both of these pass back vectors of
+gr::tag_t. The second function allows us to specify a particular key
+(as a PMT symbol) that filters out all but the key we are interested
+in, which reduces the effort inside the work function for getting the
+right tag's data.
+
+The first call just returns any tags between the given range of items:
+
+\code
+ void get_tags_in_range(std::vector<tag_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end);
+\endcode
+
+Adding a fifth argument to this function allows us to filter on the
+key \a key.
+
+\code
+ void get_tags_in_range(std::vector<tag_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt::pmt_t &key);
+\endcode
+
+
+\section tag_propagation Tag Propagation
+
+Tags are propagated downstream from block to block like the normal
+data streams. How blocks are actually moved depends on a specific
+propagation policy. We defined three types of policies:
+
+\li All-to-All: all tags from any input port are replicated to all
+output ports
+\li One-to-One: tags from input port \a i are only copied to output
+port \a i (depends on num inputs = num outputs).
+\li Dont: Does not propagate tags. Tags are either stopped here or the
+work function propagates them itself.
+
+The default behavior of a block is the 'All-to-All' method of
+propagation.
+
+To set a different propagation policy, use the function:
+
+\code
+ void set_tag_propagation_policy(tag_propagation_policy_t p);
+\endcode
+
+See the gr::block::tag_propagation_policy_t documentation for details
+on this enum type.
+
+
+\subsection tags_rate_changes Tag Propagation through Rate Changes
+
+When a tag is propagated through a block that has a rate change, the
+item's offset in the data stream will change. The scheduler uses the
+block's gr::block::relative_rate concept to perform the update on the
+tag's offset value. The relative rate of a block determines the
+relationship between the input rate and output rate. Decimators that
+decimate by a factor of \a D have a relative rate of <em>1/D</em>.
+
+Synchronous blocks (gr::sync_block), decimators (gr::sync_decimator),
+and interpolators (gr::sync_interpolator) all have pre-defined and
+well-understood relative rates. A standard gr::block has a default
+relative rate of 1.0, but this must be set if it does not work this
+way. Often, we use a gr::block because we have no pre-conceived notion
+of the number of input to output items. If it is important to pass
+tags through these blocks that respect the change in item value, we
+would have to use the TPP_DONT tag propagation policy and handle the
+propagation internally.
+
+
+\section tags_issues Notes on How to Use Tags
+
+Tags can be very useful to an application, and their use is
+spreading. USRP sources generate tag information on the time, sample
+rate, and frequency of the board if anything changes. We have a meta
+data file source/sink that use tags to store information about the
+data stream. But there are things to think about when using tags in a
+block.
+
+First, when tags are not being used, there is almost no effect on the
+scheduler. However, when we use tags, we add overhead by getting and
+extracting tags from a data stream. We also use overhead in
+propagating the tags. For each tag, each block must copy a vector of
+tags from the output port(s) of one block to the input port(s) of the
+next block(s). These copy operations can add up.
+
+The key is to minimize the use of tags. Use them when and only when
+necessary and try to provide some control over how tags are generated
+to control their frequency. A good example is the USRP source, which
+generates a time tag. If it generated a tag with every sample, we
+would have thousands of tags per second, which would add a significant
+amount of overhead. Conversely, if we started at time <em>t0</em> at
+sample rate <em>sr</em>, then after <em>N</em> samples, we know that
+we are now at time <em>t0 + N/sr</em>. So continuously producing new
+tags adds no information.
+
+The main issue we need to deal with in the above situation is when
+there is a discontinuity in the packets received from the USRP. Since
+we have no way of knowing in the flowgraph how many samples were
+potentially lost, we have lost track of the timing information. The
+USRP driver recognizes when packets have been dropped and uses this to
+queue another tag, which allows us to resync. Likewise, any time the
+sample rate or frequency changes, a new tag is issued.
+
+*/