diff options
53 files changed, 1696 insertions, 376 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8846513a07..858a7d6a2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,8 +46,8 @@ message(STATUS "Build type set to ${CMAKE_BUILD_TYPE}.") # Set the version information here set(VERSION_INFO_MAJOR_VERSION 3) set(VERSION_INFO_API_COMPAT 7) -set(VERSION_INFO_MINOR_VERSION 5) -set(VERSION_INFO_MAINT_VERSION 0) +set(VERSION_INFO_MINOR_VERSION 6) +set(VERSION_INFO_MAINT_VERSION git) include(GrVersion) #setup version info # Append -O2 optimization flag for Debug builds diff --git a/docs/doxygen/Doxyfile.in b/docs/doxygen/Doxyfile.in index 3b82e2c40c..3f558526e7 100644 --- a/docs/doxygen/Doxyfile.in +++ b/docs/doxygen/Doxyfile.in @@ -142,26 +142,51 @@ STRIP_FROM_PATH = # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = @CMAKE_SOURCE_DIR@/gnuradio-runtime/include \ + @CMAKE_BINARY_DIR@/gnuradio-runtime/include \ @CMAKE_SOURCE_DIR@/gr-analog/include \ + @CMAKE_BINARY_DIR@/gr-analog/include \ @CMAKE_SOURCE_DIR@/gr-atsc/include \ + @CMAKE_BINARY_DIR@/gr-atsc/include \ @CMAKE_SOURCE_DIR@/gr-audio/include \ + @CMAKE_BINARY_DIR@/gr-audio/include \ @CMAKE_SOURCE_DIR@/gr-blocks/include \ + @CMAKE_BINARY_DIR@/gr-blocks/include \ @CMAKE_SOURCE_DIR@/gr-channels/include \ + @CMAKE_BINARY_DIR@/gr-channels/include \ @CMAKE_SOURCE_DIR@/gr-comedi/include \ + @CMAKE_BINARY_DIR@/gr-comedi/include \ @CMAKE_SOURCE_DIR@/gr-digital/include \ + @CMAKE_BINARY_DIR@/gr-digital/include \ + @CMAKE_SOURCE_DIR@/gr-dtv/include \ + @CMAKE_BINARY_DIR@/gr-dtv/include \ @CMAKE_SOURCE_DIR@/gr-fcd/include \ + @CMAKE_BINARY_DIR@/gr-fcd/include \ @CMAKE_SOURCE_DIR@/gr-fec/include \ + @CMAKE_BINARY_DIR@/gr-fec/include \ @CMAKE_SOURCE_DIR@/gr-fft/include \ + @CMAKE_BINARY_DIR@/gr-fft/include \ @CMAKE_SOURCE_DIR@/gr-filter/include \ + @CMAKE_BINARY_DIR@/gr-filter/include \ @CMAKE_SOURCE_DIR@/gr-noaa/include \ + @CMAKE_BINARY_DIR@/gr-noaa/include \ @CMAKE_SOURCE_DIR@/gr-pager/include \ + @CMAKE_BINARY_DIR@/gr-pager/include \ @CMAKE_SOURCE_DIR@/gr-qtgui/include \ + @CMAKE_BINARY_DIR@/gr-qtgui/include \ @CMAKE_SOURCE_DIR@/gr-trellis/include \ + @CMAKE_BINARY_DIR@/gr-trellis/include \ @CMAKE_SOURCE_DIR@/gr-uhd/include \ + @CMAKE_BINARY_DIR@/gr-uhd/include \ @CMAKE_SOURCE_DIR@/gr-video-sdl/include \ + @CMAKE_BINARY_DIR@/gr-video-sdl/include \ @CMAKE_SOURCE_DIR@/gr-vocoder/include \ + @CMAKE_BINARY_DIR@/gr-vocoder/include \ + @CMAKE_SOURCE_DIR@/gr-wavelet/include \ + @CMAKE_BINARY_DIR@/gr-wavelet/include \ @CMAKE_SOURCE_DIR@/gr-wxgui/include \ - @CMAKE_SOURCE_DIR@/volk/include + @CMAKE_BINARY_DIR@/gr-wxgui/include \ + @CMAKE_SOURCE_DIR@/volk/include \ + @CMAKE_BINARY_DIR@/volk/include # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system diff --git a/docs/doxygen/other/stream_tags.dox b/docs/doxygen/other/stream_tags.dox index 851740984e..d48ec1ddee 100644 --- a/docs/doxygen/other/stream_tags.dox +++ b/docs/doxygen/other/stream_tags.dox @@ -61,7 +61,10 @@ 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: +get the stream tags. These functions are only meant to be accessed +within a call to general_work/work. While they can be called elsewhere +in time by a block, the behavior outside of work is undefined without +exact knowledge of the item counts in the buffers. \li gr::block::add_item_tag: Adds an item tag to a particular output port using a gr::tag_t data type. diff --git a/gnuradio-runtime/include/gnuradio/block.h b/gnuradio-runtime/include/gnuradio/block.h index a033e0ac27..43fc50c54b 100644 --- a/gnuradio-runtime/include/gnuradio/block.h +++ b/gnuradio-runtime/include/gnuradio/block.h @@ -636,7 +636,7 @@ namespace gr { void add_item_tag(unsigned int which_output, const tag_t &tag); /*! - * \brief Removes a tag from the given input buffer. + * \brief DEPRECATED. Will be removed in 3.8. * * \param which_input an integer of which input stream to remove the tag from * \param abs_offset a uint64 number of the absolute item number @@ -662,9 +662,7 @@ namespace gr { } /*! - * \brief Removes a tag from the given input buffer. - * - * If no such tag is found, does nothing. + * \brief DEPRECATED. Will be removed in 3.8. * * \param which_input an integer of which input stream to remove the tag from * \param tag the tag object to remove diff --git a/gnuradio-runtime/include/gnuradio/buffer.h b/gnuradio-runtime/include/gnuradio/buffer.h index e2d5760e59..c0c9f3d39d 100644 --- a/gnuradio-runtime/include/gnuradio/buffer.h +++ b/gnuradio-runtime/include/gnuradio/buffer.h @@ -28,7 +28,7 @@ #include <gnuradio/tags.h> #include <boost/weak_ptr.hpp> #include <gnuradio/thread/thread.h> -#include <deque> +#include <map> namespace gr { @@ -125,8 +125,10 @@ namespace gr { */ void prune_tags(uint64_t max_time); - std::deque<tag_t>::iterator get_tags_begin() { return d_item_tags.begin(); } - std::deque<tag_t>::iterator get_tags_end() { return d_item_tags.end(); } + std::multimap<uint64_t,tag_t>::iterator get_tags_begin() { return d_item_tags.begin(); } + std::multimap<uint64_t,tag_t>::iterator get_tags_end() { return d_item_tags.end(); } + std::multimap<uint64_t,tag_t>::iterator get_tags_lower_bound(uint64_t x) { return d_item_tags.lower_bound(x); } + std::multimap<uint64_t,tag_t>::iterator get_tags_upper_bound(uint64_t x) { return d_item_tags.upper_bound(x); } // ------------------------------------------------------------------------- @@ -157,7 +159,7 @@ namespace gr { unsigned int d_write_index; // in items [0,d_bufsize) uint64_t d_abs_write_offset; // num items written since the start bool d_done; - std::deque<tag_t> d_item_tags; + std::multimap<uint64_t,tag_t> d_item_tags; uint64_t d_last_min_items_read; unsigned index_add(unsigned a, unsigned b) diff --git a/gnuradio-runtime/include/pmt/pmt.h b/gnuradio-runtime/include/pmt/pmt.h index 3e17571b23..cb6fdf44d5 100644 --- a/gnuradio-runtime/include/pmt/pmt.h +++ b/gnuradio-runtime/include/pmt/pmt.h @@ -201,6 +201,7 @@ PMT_API bool is_real(pmt_t obj); //! Return the pmt value that represents double \p x. PMT_API pmt_t from_double(double x); +PMT_API pmt_t from_float(float x); /*! * \brief Convert pmt to double if possible. @@ -211,6 +212,15 @@ PMT_API pmt_t from_double(double x); */ PMT_API double to_double(pmt_t x); +/*! + * \brief Convert pmt to float if possible. + * + * This basically is to_double() with a type-cast; the PMT stores + * the value as a double in any case. Use this when strict typing + * is required. + */ +PMT_API float to_float(pmt_t x); + /* * ------------------------------------------------------------------------ * Complex diff --git a/gnuradio-runtime/lib/buffer.cc b/gnuradio-runtime/lib/buffer.cc index 162324e590..f00e9a04bf 100644 --- a/gnuradio-runtime/lib/buffer.cc +++ b/gnuradio-runtime/lib/buffer.cc @@ -23,7 +23,7 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif - +#include <algorithm> #include <gnuradio/buffer.h> #include <gnuradio/math.h> #include "vmcircbuf.h" @@ -225,16 +225,16 @@ namespace gr { buffer::add_item_tag(const tag_t &tag) { gr::thread::scoped_lock guard(*mutex()); - d_item_tags.push_back(tag); + d_item_tags.insert(std::pair<uint64_t,tag_t>(tag.offset,tag)); } void buffer::remove_item_tag(const tag_t &tag, long id) { gr::thread::scoped_lock guard(*mutex()); - for(std::deque<tag_t>::iterator it = d_item_tags.begin(); it != d_item_tags.end(); ++it) { - if(*it == tag) { - (*it).marked_deleted.push_back(id); + for(std::multimap<uint64_t,tag_t>::iterator it = d_item_tags.lower_bound(tag.offset); it != d_item_tags.upper_bound(tag.offset); ++it) { + if((*it).second == tag) { + (*it).second.marked_deleted.push_back(id); } } } @@ -250,25 +250,9 @@ namespace gr { If this function is used elsewhere, remember to lock the buffer's mutex al la the scoped_lock line below. */ - //gr::thread::scoped_lock guard(*mutex()); - std::deque<tag_t>::iterator itr = d_item_tags.begin(); - - uint64_t item_time; - - // Since tags are not guarenteed to be in any particular order, we - // need to erase here instead of pop_front. An erase in the middle - // invalidates all iterators; so this resets the iterator to find - // more. Mostly, we wil be erasing from the front and - // therefore lose little time this way. - while(itr != d_item_tags.end()) { - item_time = (*itr).offset; - if(item_time+d_max_reader_delay + bufsize() < max_time) { - d_item_tags.erase(itr); - itr = d_item_tags.begin(); - } - else - itr++; - } + std::multimap<uint64_t, tag_t>::iterator end_itr = d_item_tags.lower_bound(max_time); + std::multimap<uint64_t, tag_t>::iterator begin_itr = d_item_tags.begin(); + d_item_tags.erase(begin_itr, end_itr); } long @@ -333,30 +317,28 @@ namespace gr { buffer_reader::get_tags_in_range(std::vector<tag_t> &v, uint64_t abs_start, uint64_t abs_end, - long id) + long id) { gr::thread::scoped_lock guard(*mutex()); v.resize(0); - std::deque<tag_t>::iterator itr = d_buffer->get_tags_begin(); + std::multimap<uint64_t,tag_t>::iterator itr = d_buffer->get_tags_lower_bound(abs_start); + std::multimap<uint64_t,tag_t>::iterator itr_end = d_buffer->get_tags_upper_bound(abs_end); uint64_t item_time; - while(itr != d_buffer->get_tags_end()) { - item_time = (*itr).offset + d_attr_delay; - + while(itr != itr_end) { + item_time = (*itr).second.offset + d_attr_delay; if((item_time >= abs_start) && (item_time < abs_end)) { - std::vector<long>::iterator id_itr; - id_itr = std::find(itr->marked_deleted.begin(), itr->marked_deleted.end(), id); - + std::vector<long>::iterator id_itr; + id_itr = std::find(itr->second.marked_deleted.begin(), itr->second.marked_deleted.end(), id); // If id is not in the vector of marked blocks - if(id_itr == itr->marked_deleted.end()) { - tag_t t = *itr; + if(id_itr == itr->second.marked_deleted.end()) { + tag_t t = (*itr).second; t.offset += d_attr_delay; - v.push_back(t); - v.back().marked_deleted.clear(); - } + v.push_back(t); + v.back().marked_deleted.clear(); + } } - itr++; } } diff --git a/gnuradio-runtime/lib/pmt/pmt.cc b/gnuradio-runtime/lib/pmt/pmt.cc index 082b98a80d..da830e1aed 100644 --- a/gnuradio-runtime/lib/pmt/pmt.cc +++ b/gnuradio-runtime/lib/pmt/pmt.cc @@ -368,6 +368,12 @@ from_double(double x) return pmt_t(new pmt_real(x)); } +pmt_t +from_float(float x) +{ + return pmt_t(new pmt_real(x)); +} + double to_double(pmt_t x) { @@ -379,6 +385,12 @@ to_double(pmt_t x) throw wrong_type("pmt_to_double", x); } +float +to_float(pmt_t x) +{ + return float(to_double(x)); +} + //////////////////////////////////////////////////////////////////////////// // Complex //////////////////////////////////////////////////////////////////////////// diff --git a/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc index 2f46b014db..2b3ca32293 100644 --- a/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc +++ b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc @@ -125,6 +125,15 @@ qa_pmt_prims::test_reals() CPPUNIT_ASSERT_EQUAL(-1.0, pmt::to_double(m1)); CPPUNIT_ASSERT_EQUAL(1.0, pmt::to_double(p1)); CPPUNIT_ASSERT_EQUAL(1.0, pmt::to_double(pmt::from_long(1))); + + pmt::pmt_t p2 = pmt::from_float(1); + pmt::pmt_t m2 = pmt::from_float(-1); + CPPUNIT_ASSERT(pmt::is_real(p2)); + CPPUNIT_ASSERT(pmt::is_real(m2)); + CPPUNIT_ASSERT_THROW(pmt::to_float(pmt::PMT_T), pmt::wrong_type); + CPPUNIT_ASSERT_EQUAL(float(-1.0), pmt::to_float(m2)); + CPPUNIT_ASSERT_EQUAL(float(1.0), pmt::to_float(p2)); + CPPUNIT_ASSERT_EQUAL(float(1.0), pmt::to_float(pmt::from_long(1))); } void diff --git a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py index cbca9d44ae..ba46e3f4d9 100644 --- a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py +++ b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py @@ -89,9 +89,22 @@ def python_to_tag(tag_struct): tag.srcid = tag_struct[3] good = True + elif(len(tag_struct) == 3): + if(isinstance(tag_struct[0], (int,long))): + tag.offset = tag_struct[0] + good = True + + if(isinstance(tag_struct[1], pmt.pmt_swig.swig_int_ptr)): + tag.key = tag_struct[1] + good = True + + if(isinstance(tag_struct[2], pmt.pmt_swig.swig_int_ptr)): + tag.value = tag_struct[2] + good = True + + tag.srcid = pmt.PMT_F + if(good): return tag else: return None - - diff --git a/gnuradio-runtime/python/pmt/qa_pmt.py b/gnuradio-runtime/python/pmt/qa_pmt.py index 5c1af2c00e..32cff62f44 100755 --- a/gnuradio-runtime/python/pmt/qa_pmt.py +++ b/gnuradio-runtime/python/pmt/qa_pmt.py @@ -36,7 +36,9 @@ class test_pmt(unittest.TestCase): const = 123765 x_pmt = pmt.from_double(const) x_int = pmt.to_double(x_pmt) + x_float = pmt.to_float(x_pmt) self.assertEqual(x_int, const) + self.assertEqual(x_float, const) def test03(self): v = pmt.init_f32vector(3, [11, -22, 33]) diff --git a/gnuradio-runtime/swig/pmt_swig.i b/gnuradio-runtime/swig/pmt_swig.i index e54b544977..c4b678222d 100644 --- a/gnuradio-runtime/swig/pmt_swig.i +++ b/gnuradio-runtime/swig/pmt_swig.i @@ -111,6 +111,8 @@ namespace pmt{ bool is_real(pmt_t obj); pmt_t from_double(double x); double to_double(pmt_t x); + pmt_t from_float(double x); + double to_float(pmt_t x); bool is_complex(pmt_t obj); pmt_t make_rectangular(double re, double im); diff --git a/gr-blocks/examples/CMakeLists.txt b/gr-blocks/examples/CMakeLists.txt index c9829661b6..bb07cdc2b5 100644 --- a/gr-blocks/examples/CMakeLists.txt +++ b/gr-blocks/examples/CMakeLists.txt @@ -17,6 +17,14 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. +install( + FILES + matrix_multiplexer.grc + vector_source_with_tags.grc + DESTINATION ${GR_PKG_DATA_DIR}/examples/blocks + COMPONENT "runtime_python" +) + add_subdirectory(metadata) add_subdirectory(tags) diff --git a/gr-blocks/examples/vector_source_with_tags.grc b/gr-blocks/examples/vector_source_with_tags.grc new file mode 100644 index 0000000000..e266b91f85 --- /dev/null +++ b/gr-blocks/examples/vector_source_with_tags.grc @@ -0,0 +1,698 @@ +<?xml version='1.0' encoding='ASCII'?> +<?grc format='1' created='3.7.6'?> +<flow_graph> + <timestamp>Mon Sep 22 11:59:58 2014</timestamp> + <block> + <key>options</key> + <param> + <key>id</key> + <value>vector_source_with_tags</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value></value> + </param> + <param> + <key>author</key> + <value></value> + </param> + <param> + <key>description</key> + <value>Shows how to use tags in a vector_source</value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>generate_options</key> + <value>qt_gui</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run_options</key> + <value>prompt</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>max_nouts</key> + <value>0</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>tag1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>gr.tag_utils.python_to_tag((1, pmt.intern('mark'), pmt.PMT_T))</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(16, 267)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>tag0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>gr.tag_utils.python_to_tag((0, pmt.intern('mark'), pmt.PMT_T, pmt.intern("src")))</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(16, 203)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>samp_rate</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>32000</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(184, 11)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_pmt</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import pmt</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(280, 11)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_throttle</key> + <param> + <key>id</key> + <value>blocks_throttle_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>samples_per_second</key> + <value>samp_rate</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>ignoretag</key> + <value>True</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(272, 123)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_tag_debug</key> + <param> + <key>id</key> + <value>blocks_tag_debug_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>name</key> + <value></value> + </param> + <param> + <key>filter</key> + <value>""</value> + </param> + <param> + <key>num_inputs</key> + <value>1</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>display</key> + <value>True</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(456, 195)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_vector_source_x</key> + <param> + <key>id</key> + <value>blocks_vector_source_x_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>vector</key> + <value>(-0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 0.0)</value> + </param> + <param> + <key>tags</key> + <value>[tag0, tag1]</value> + </param> + <param> + <key>repeat</key> + <value>True</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>maxoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(16, 107)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>qtgui_time_sink_x</key> + <param> + <key>id</key> + <value>qtgui_time_sink_x_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>name</key> + <value>""</value> + </param> + <param> + <key>ylabel</key> + <value>Amplitude</value> + </param> + <param> + <key>yunit</key> + <value>""</value> + </param> + <param> + <key>size</key> + <value>60</value> + </param> + <param> + <key>srate</key> + <value>samp_rate</value> + </param> + <param> + <key>grid</key> + <value>True</value> + </param> + <param> + <key>autoscale</key> + <value>False</value> + </param> + <param> + <key>ymin</key> + <value>-1</value> + </param> + <param> + <key>ymax</key> + <value>1</value> + </param> + <param> + <key>nconnections</key> + <value>1</value> + </param> + <param> + <key>update_time</key> + <value>0.10</value> + </param> + <param> + <key>entags</key> + <value>True</value> + </param> + <param> + <key>gui_hint</key> + <value></value> + </param> + <param> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_TAG</value> + </param> + <param> + <key>tr_slope</key> + <value>qtgui.TRIG_SLOPE_POS</value> + </param> + <param> + <key>tr_level</key> + <value>0.0</value> + </param> + <param> + <key>tr_delay</key> + <value>0</value> + </param> + <param> + <key>tr_chan</key> + <value>0</value> + </param> + <param> + <key>tr_tag</key> + <value>mark</value> + </param> + <param> + <key>label1</key> + <value></value> + </param> + <param> + <key>width1</key> + <value>1</value> + </param> + <param> + <key>color1</key> + <value>"blue"</value> + </param> + <param> + <key>style1</key> + <value>1</value> + </param> + <param> + <key>marker1</key> + <value>0</value> + </param> + <param> + <key>alpha1</key> + <value>1.0</value> + </param> + <param> + <key>label2</key> + <value></value> + </param> + <param> + <key>width2</key> + <value>1</value> + </param> + <param> + <key>color2</key> + <value>"red"</value> + </param> + <param> + <key>style2</key> + <value>1</value> + </param> + <param> + <key>marker2</key> + <value>-1</value> + </param> + <param> + <key>alpha2</key> + <value>1.0</value> + </param> + <param> + <key>label3</key> + <value></value> + </param> + <param> + <key>width3</key> + <value>1</value> + </param> + <param> + <key>color3</key> + <value>"green"</value> + </param> + <param> + <key>style3</key> + <value>1</value> + </param> + <param> + <key>marker3</key> + <value>-1</value> + </param> + <param> + <key>alpha3</key> + <value>1.0</value> + </param> + <param> + <key>label4</key> + <value></value> + </param> + <param> + <key>width4</key> + <value>1</value> + </param> + <param> + <key>color4</key> + <value>"black"</value> + </param> + <param> + <key>style4</key> + <value>1</value> + </param> + <param> + <key>marker4</key> + <value>-1</value> + </param> + <param> + <key>alpha4</key> + <value>1.0</value> + </param> + <param> + <key>label5</key> + <value></value> + </param> + <param> + <key>width5</key> + <value>1</value> + </param> + <param> + <key>color5</key> + <value>"cyan"</value> + </param> + <param> + <key>style5</key> + <value>1</value> + </param> + <param> + <key>marker5</key> + <value>-1</value> + </param> + <param> + <key>alpha5</key> + <value>1.0</value> + </param> + <param> + <key>label6</key> + <value></value> + </param> + <param> + <key>width6</key> + <value>1</value> + </param> + <param> + <key>color6</key> + <value>"magenta"</value> + </param> + <param> + <key>style6</key> + <value>1</value> + </param> + <param> + <key>marker6</key> + <value>-1</value> + </param> + <param> + <key>alpha6</key> + <value>1.0</value> + </param> + <param> + <key>label7</key> + <value></value> + </param> + <param> + <key>width7</key> + <value>1</value> + </param> + <param> + <key>color7</key> + <value>"yellow"</value> + </param> + <param> + <key>style7</key> + <value>1</value> + </param> + <param> + <key>marker7</key> + <value>-1</value> + </param> + <param> + <key>alpha7</key> + <value>1.0</value> + </param> + <param> + <key>label8</key> + <value></value> + </param> + <param> + <key>width8</key> + <value>1</value> + </param> + <param> + <key>color8</key> + <value>"dark red"</value> + </param> + <param> + <key>style8</key> + <value>1</value> + </param> + <param> + <key>marker8</key> + <value>-1</value> + </param> + <param> + <key>alpha8</key> + <value>1.0</value> + </param> + <param> + <key>label9</key> + <value></value> + </param> + <param> + <key>width9</key> + <value>1</value> + </param> + <param> + <key>color9</key> + <value>"dark green"</value> + </param> + <param> + <key>style9</key> + <value>1</value> + </param> + <param> + <key>marker9</key> + <value>-1</value> + </param> + <param> + <key>alpha9</key> + <value>1.0</value> + </param> + <param> + <key>label10</key> + <value></value> + </param> + <param> + <key>width10</key> + <value>1</value> + </param> + <param> + <key>color10</key> + <value>"blue"</value> + </param> + <param> + <key>style10</key> + <value>1</value> + </param> + <param> + <key>marker10</key> + <value>-1</value> + </param> + <param> + <key>alpha10</key> + <value>1.0</value> + </param> + <param> + <key>alias</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(456, 107)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>qtgui_time_sink_x_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_vector_source_x_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>blocks_tag_debug_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> diff --git a/gr-blocks/grc/blocks_abs_xx.xml b/gr-blocks/grc/blocks_abs_xx.xml index 65ef97ddff..77298716c8 100644 --- a/gr-blocks/grc/blocks_abs_xx.xml +++ b/gr-blocks/grc/blocks_abs_xx.xml @@ -8,7 +8,13 @@ <name>Abs</name> <key>blocks_abs_xx</key> <import>from gnuradio import blocks</import> - <make>blocks.abs_$(type.fcn)()</make> + <make>blocks.abs_$(type.fcn)($vlen)</make> + <param> + <name>Vec Length</name> + <key>vlen</key> + <value>1</value> + <type>int</type> + </param> <param> <name>IO Type</name> <key>type</key> @@ -29,21 +35,14 @@ <opt>fcn:ff</opt> </option> </param> - <param> - <name>Num Inputs</name> - <key>num_inputs</key> - <value>1</value> - <type>int</type> - </param> - <check>$num_inputs >= 1</check> <sink> <name>in</name> <type>$type</type> - <nports>$num_inputs</nports> + <vlen>$vlen</vlen> </sink> <source> <name>out</name> <type>$type</type> - <nports>$num_inputs</nports> + <vlen>$vlen</vlen> </source> </block> diff --git a/gr-blocks/grc/blocks_tagged_stream_to_pdu.xml b/gr-blocks/grc/blocks_tagged_stream_to_pdu.xml index f85b47fb19..ae8ad3b6c5 100644 --- a/gr-blocks/grc/blocks_tagged_stream_to_pdu.xml +++ b/gr-blocks/grc/blocks_tagged_stream_to_pdu.xml @@ -42,5 +42,6 @@ <source> <name>pdus</name> <type>message</type> + <optional>1</optional> </source> </block> diff --git a/gr-blocks/include/gnuradio/blocks/abs_XX.h.t b/gr-blocks/include/gnuradio/blocks/abs_XX.h.t index f8688edcd3..541716296f 100644 --- a/gr-blocks/include/gnuradio/blocks/abs_XX.h.t +++ b/gr-blocks/include/gnuradio/blocks/abs_XX.h.t @@ -49,7 +49,7 @@ namespace gr { /*! * \brief Create an instance of @NAME@ */ - static sptr make(); + static sptr make(size_t vlen=1); }; } /* namespace blocks */ diff --git a/gr-blocks/lib/abs_XX_impl.cc.t b/gr-blocks/lib/abs_XX_impl.cc.t index 6bb9f149fd..195d8dff3d 100644 --- a/gr-blocks/lib/abs_XX_impl.cc.t +++ b/gr-blocks/lib/abs_XX_impl.cc.t @@ -32,15 +32,16 @@ namespace gr { namespace blocks { - @NAME@::sptr @NAME@::make() + @NAME@::sptr @NAME@::make(size_t vlen) { - return gnuradio::get_initial_sptr(new @NAME_IMPL@()); + return gnuradio::get_initial_sptr(new @NAME_IMPL@(vlen)); } - @NAME_IMPL@::@NAME_IMPL@() + @NAME_IMPL@::@NAME_IMPL@(size_t vlen) : sync_block ("@NAME@", - io_signature::make (1, 1, sizeof (@I_TYPE@)), - io_signature::make (1, 1, sizeof (@O_TYPE@))) + io_signature::make (1, 1, sizeof (@I_TYPE@)*vlen), + io_signature::make (1, 1, sizeof (@O_TYPE@)*vlen)), + d_vlen(vlen) { } @@ -52,7 +53,7 @@ namespace gr { @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; - for(int i=0; i<noutput_items; i++) { + for(size_t i=0; i<noutput_items*d_vlen; i++) { @I_TYPE@ val = iptr[i]; optr[i] = ((val < ((@I_TYPE@)0)) ? -val : val); } diff --git a/gr-blocks/lib/abs_XX_impl.h.t b/gr-blocks/lib/abs_XX_impl.h.t index b31ef5fb31..fa96c84073 100644 --- a/gr-blocks/lib/abs_XX_impl.h.t +++ b/gr-blocks/lib/abs_XX_impl.h.t @@ -32,8 +32,11 @@ namespace gr { class BLOCKS_API @NAME_IMPL@ : public @NAME@ { + private: + size_t d_vlen; + public: - @NAME_IMPL@(); + @NAME_IMPL@(size_t vlen); int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gr-blocks/lib/deinterleave_impl.cc b/gr-blocks/lib/deinterleave_impl.cc index c9d0e9aeda..9e18c35e58 100644 --- a/gr-blocks/lib/deinterleave_impl.cc +++ b/gr-blocks/lib/deinterleave_impl.cc @@ -41,13 +41,20 @@ namespace gr { io_signature::make (1, io_signature::IO_INFINITE, itemsize)), d_itemsize(itemsize), d_blocksize(blocksize), d_current_output(0) { + d_size_bytes = d_itemsize * d_blocksize; set_output_multiple(blocksize); } + void + deinterleave_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items * d_noutputs; + } + bool deinterleave_impl::check_topology(int ninputs, int noutputs) { - set_relative_rate((double)noutputs); + set_relative_rate(1.0/(double)noutputs); d_noutputs = noutputs; return true; } @@ -61,10 +68,29 @@ namespace gr { const char *in = (const char*)input_items[0]; char **out = (char**)&output_items[0]; - memcpy(out[d_current_output], in, d_itemsize * d_blocksize); - consume_each(d_blocksize); - produce(d_current_output, d_blocksize); - d_current_output = (d_current_output + 1) % d_noutputs; + int count = 0, totalcount = noutput_items*d_noutputs; + unsigned int skip = 0; + unsigned int acc = 0; + while(count < totalcount) { + memcpy(out[d_current_output]+skip*d_size_bytes, in, d_size_bytes); + in += d_size_bytes; + produce(d_current_output, d_blocksize); + d_current_output = (d_current_output + 1) % d_noutputs; + + // accumulate times through the loop; increment skip after a + // full pass over the output streams. + // This is separate than d_current_output since we could be in + // the middle of a loop when we exit. + acc++; + if(acc >= d_noutputs) { + skip++; + acc = 0; + } + + // Keep track of our loop counter + count+=d_blocksize; + } + consume_each(totalcount); return WORK_CALLED_PRODUCE; } diff --git a/gr-blocks/lib/deinterleave_impl.h b/gr-blocks/lib/deinterleave_impl.h index 247ee3a018..71a551a69c 100644 --- a/gr-blocks/lib/deinterleave_impl.h +++ b/gr-blocks/lib/deinterleave_impl.h @@ -35,11 +35,12 @@ namespace gr { unsigned int d_blocksize; unsigned int d_current_output; unsigned int d_noutputs; - + unsigned int d_size_bytes; // block size in bytes public: deinterleave_impl(size_t itemsize, unsigned int blocksize); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); bool check_topology(int ninputs, int noutputs); int general_work(int noutput_items, diff --git a/gr-blocks/lib/message_strobe_impl.cc b/gr-blocks/lib/message_strobe_impl.cc index bd0ad80142..b3f1782229 100644 --- a/gr-blocks/lib/message_strobe_impl.cc +++ b/gr-blocks/lib/message_strobe_impl.cc @@ -47,15 +47,15 @@ namespace gr { message_strobe_impl::message_strobe_impl(pmt::pmt_t msg, float period_ms) : block("message_strobe", - io_signature::make(0, 0, 0), - io_signature::make(0, 0, 0)), + io_signature::make(0, 0, 0), + io_signature::make(0, 0, 0)), d_finished(false), d_period_ms(period_ms), d_msg(msg) { message_port_register_out(pmt::mp("strobe")); - d_thread = boost::shared_ptr<boost::thread> - (new boost::thread(boost::bind(&message_strobe_impl::run, this))); + d_thread = boost::shared_ptr<gr::thread::thread> + (new gr::thread::thread(boost::bind(&message_strobe_impl::run, this))); message_port_register_in(pmt::mp("set_msg")); set_msg_handler(pmt::mp("set_msg"), diff --git a/gr-blocks/lib/message_strobe_impl.h b/gr-blocks/lib/message_strobe_impl.h index 7a54680286..0f37cd2e0e 100644 --- a/gr-blocks/lib/message_strobe_impl.h +++ b/gr-blocks/lib/message_strobe_impl.h @@ -31,7 +31,7 @@ namespace gr { class BLOCKS_API message_strobe_impl : public message_strobe { private: - boost::shared_ptr<boost::thread> d_thread; + boost::shared_ptr<gr::thread::thread> d_thread; bool d_finished; float d_period_ms; pmt::pmt_t d_msg; diff --git a/gr-blocks/lib/message_strobe_random_impl.cc b/gr-blocks/lib/message_strobe_random_impl.cc index 80819fc2fc..c62aad1c7a 100644 --- a/gr-blocks/lib/message_strobe_random_impl.cc +++ b/gr-blocks/lib/message_strobe_random_impl.cc @@ -61,8 +61,8 @@ namespace gr { // set up ports message_port_register_out(pmt::mp("strobe")); - d_thread = boost::shared_ptr<boost::thread> - (new boost::thread(boost::bind(&message_strobe_random_impl::run, this))); + d_thread = boost::shared_ptr<gr::thread::thread> + (new gr::thread::thread(boost::bind(&message_strobe_random_impl::run, this))); message_port_register_in(pmt::mp("set_msg")); set_msg_handler(pmt::mp("set_msg"), diff --git a/gr-blocks/lib/message_strobe_random_impl.h b/gr-blocks/lib/message_strobe_random_impl.h index 32eddb592c..2dcaa7effa 100644 --- a/gr-blocks/lib/message_strobe_random_impl.h +++ b/gr-blocks/lib/message_strobe_random_impl.h @@ -36,7 +36,7 @@ namespace gr { class BLOCKS_API message_strobe_random_impl : public message_strobe_random { private: - boost::shared_ptr<boost::thread> d_thread; + boost::shared_ptr<gr::thread::thread> d_thread; bool d_finished; float d_mean_ms; float d_std_ms; diff --git a/gr-blocks/lib/qa_block_tags.cc b/gr-blocks/lib/qa_block_tags.cc index c554425f8e..d794f8edfe 100644 --- a/gr-blocks/lib/qa_block_tags.cc +++ b/gr-blocks/lib/qa_block_tags.cc @@ -33,20 +33,32 @@ #include <gnuradio/blocks/annotator_alltoall.h> #include <gnuradio/blocks/annotator_1to1.h> #include <gnuradio/blocks/keep_one_in_n.h> -#include <gnuradio/tags.h> // ---------------------------------------------------------------- // set to 1 to turn on debug output // The debug output fully checks that the tags seen are what are expected. While -// this behavior currently works with our implementation, there is no guarentee +// this behavior currently works with our implementation, there is no guarantee // that the tags will be coming in this specific order, so it's dangerous to // rely on this as a test of the tag system working. We would really want to // tags we know we should see and then test that they all occur once, but in no // particular order. #define QA_TAGS_DEBUG 0 +gr::tag_t make_tag(uint64_t offset, pmt::pmt_t key, pmt::pmt_t value, pmt::pmt_t srcid) { + gr::tag_t result; + result.offset = offset; + result.key = key; + result.value = value; + result.srcid = srcid; + return result; +} + +std::ostream& +operator << (std::ostream& os, const gr::tag_t &t) { + return os; +} void qa_block_tags::t0() { @@ -59,8 +71,6 @@ qa_block_tags::t0() tb->connect(src, 0, head, 0); tb->connect(head, 0, snk, 0); - //CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::runtime_error); - //CPPUNIT_ASSERT_THROW(src->nitems_written(0), std::runtime_error); CPPUNIT_ASSERT_EQUAL(src->nitems_read(0), (uint64_t)0); CPPUNIT_ASSERT_EQUAL(src->nitems_written(0), (uint64_t)0); @@ -117,39 +127,39 @@ qa_block_tags::t1() str1 << ann1->name() << ann1->unique_id(); str2 << ann2->name() << ann2->unique_id(); - pmt::pmt_t expected_tags3[8]; - expected_tags3[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags3[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags3[2] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); - expected_tags3[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags3[4] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); - expected_tags3[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags3[6] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags3[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - - pmt::pmt_t expected_tags4[8]; - expected_tags4[0] = mp(pmt::from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); - expected_tags4[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags4[2] = mp(pmt::from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); - expected_tags4[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags4[4] = mp(pmt::from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); - expected_tags4[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags4[6] = mp(pmt::from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); - expected_tags4[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + gr::tag_t expected_tags3[8]; + expected_tags3[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags3[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags3[2] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags3[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags3[4] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags3[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags3[6] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags3[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6)); + + gr::tag_t expected_tags4[8]; + expected_tags4[0] = make_tag(0, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags4[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[2] = make_tag(10000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[4] = make_tag(20000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags4[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags4[6] = make_tag(30000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7)); std::cout << std::endl << "qa_block_tags::t1" << std::endl; // For annotator 3, we know it gets tags from ann0 and ann1, test this for(size_t i = 0; i < tags3.size(); i++) { std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags3[i]), pmt::write_string(expected_tags3[i])); + CPPUNIT_ASSERT_EQUAL(tags3[i], expected_tags3[i]); } // For annotator 4, we know it gets tags from ann0 and ann2, test this std::cout << std::endl; for(size_t i = 0; i < tags4.size(); i++) { std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags4[i]), pmt::write_string(expected_tags4[i])); + CPPUNIT_ASSERT_EQUAL(tags4[i], expected_tags4[i]); } #endif } @@ -207,33 +217,33 @@ qa_block_tags::t2 () str0 << ann0->name() << ann0->unique_id(); str1 << ann1->name() << ann1->unique_id(); - pmt::pmt_t expected_tags2[12]; - expected_tags2[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags2[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags2[2] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags2[3] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags2[4] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags2[5] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags2[6] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(6)); - expected_tags2[7] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags2[8] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags2[9] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(9)); - expected_tags2[10] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - expected_tags2[11] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); - - pmt::pmt_t expected_tags4[12]; - expected_tags4[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(2)); - expected_tags4[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags4[2] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags4[3] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(5)); - expected_tags4[4] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags4[5] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags4[6] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(8)); - expected_tags4[7] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags4[8] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags4[9] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(11)); - expected_tags4[10] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - expected_tags4[11] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + gr::tag_t expected_tags2[12]; + expected_tags2[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags2[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags2[2] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags2[3] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags2[4] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags2[5] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags2[6] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(6)); + expected_tags2[7] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags2[8] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags2[9] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(9)); + expected_tags2[10] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6)); + expected_tags2[11] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7)); + + gr::tag_t expected_tags4[12]; + expected_tags4[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags4[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags4[2] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[3] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags4[4] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags4[5] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[6] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(8)); + expected_tags4[7] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags4[8] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags4[9] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(11)); + expected_tags4[10] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6)); + expected_tags4[11] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7)); std::cout << std::endl << "qa_block_tags::t2" << std::endl; @@ -243,13 +253,13 @@ qa_block_tags::t2 () // inconceivable for ann3 to have it wrong. for(size_t i = 0; i < tags2.size(); i++) { std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags2[i]), pmt::write_string(expected_tags2[i])); + CPPUNIT_ASSERT_EQUAL(tags2[i], expected_tags2[i]); } std::cout << std::endl; for(size_t i = 0; i < tags4.size(); i++) { std::cout << "tags2[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags4[i]), pmt::write_string(expected_tags4[i])); + CPPUNIT_ASSERT_EQUAL(tags4[i], expected_tags4[i]); } #endif } @@ -301,39 +311,39 @@ qa_block_tags::t3() str1 << ann1->name() << ann1->unique_id(); str2 << ann2->name() << ann2->unique_id(); - pmt::pmt_t expected_tags3[8]; - expected_tags3[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags3[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags3[2] = mp(pmt::from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); - expected_tags3[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags3[4] = mp(pmt::from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); - expected_tags3[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); - expected_tags3[6] = mp(pmt::from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags3[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); - - pmt::pmt_t expected_tags4[8]; - expected_tags4[0] = mp(pmt::from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); - expected_tags4[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); - expected_tags4[2] = mp(pmt::from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); - expected_tags4[3] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags4[4] = mp(pmt::from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); - expected_tags4[5] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); - expected_tags4[6] = mp(pmt::from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); - expected_tags4[7] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + gr::tag_t expected_tags3[8]; + expected_tags3[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags3[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags3[2] = make_tag(10000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags3[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags3[4] = make_tag(20000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags3[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags3[6] = make_tag(30000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags3[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(6)); + + gr::tag_t expected_tags4[8]; + expected_tags4[0] = make_tag(0, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags4[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[2] = make_tag(10000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags4[3] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[4] = make_tag(20000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags4[5] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(5)); + expected_tags4[6] = make_tag(30000, pmt::mp(str2.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags4[7] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(7)); std::cout << std::endl << "qa_block_tags::t3" << std::endl; // For annotator 3, we know it gets tags from ann0 and ann1, test this for(size_t i = 0; i < tags3.size(); i++) { std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags3[i]), pmt::write_string(expected_tags3[i])); + CPPUNIT_ASSERT_EQUAL(tags3[i], expected_tags3[i]); } // For annotator 4, we know it gets tags from ann0 and ann2, test this std::cout << std::endl; for(size_t i = 0; i < tags4.size(); i++) { std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags4[i]), pmt::write_string(expected_tags4[i])); + CPPUNIT_ASSERT_EQUAL(tags4[i], expected_tags4[i]); } #endif } @@ -409,23 +419,23 @@ qa_block_tags::t5() str1 << ann1->name() << ann1->unique_id(); str2 << ann2->name() << ann2->unique_id(); - pmt_t expected_tags1[5]; - expected_tags1[0] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags1[1] = mp(pmt::from_uint64(10000), mp(str0.str()), mp("seq"), mp(1)); - expected_tags1[2] = mp(pmt::from_uint64(20000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags1[3] = mp(pmt::from_uint64(30000), mp(str0.str()), mp("seq"), mp(3)); - - pmt_t expected_tags2[10]; - expected_tags2[0] = mp(pmt::from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); - expected_tags2[1] = mp(pmt::from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); - expected_tags2[2] = mp(pmt::from_uint64(1000), mp(str1.str()), mp("seq"), mp(1)); - expected_tags2[3] = mp(pmt::from_uint64(1000), mp(str0.str()), mp("seq"), mp(1)); - expected_tags2[4] = mp(pmt::from_uint64(2000), mp(str1.str()), mp("seq"), mp(2)); - expected_tags2[5] = mp(pmt::from_uint64(2000), mp(str0.str()), mp("seq"), mp(2)); - expected_tags2[6] = mp(pmt::from_uint64(3000), mp(str1.str()), mp("seq"), mp(3)); - expected_tags2[7] = mp(pmt::from_uint64(3000), mp(str0.str()), mp("seq"), mp(3)); - expected_tags2[8] = mp(pmt::from_uint64(4000), mp(str1.str()), mp("seq"), mp(4)); - expected_tags2[9] = mp(pmt::from_uint64(4000), mp(str0.str()), mp("seq"), mp(4)); + gr::tag_t expected_tags1[5]; + expected_tags1[0] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags1[1] = make_tag(10000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags1[2] = make_tag(20000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags1[3] = make_tag(30000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + + gr::tag_t expected_tags2[10]; + expected_tags2[0] = make_tag(0, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags2[1] = make_tag(0, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(0)); + expected_tags2[2] = make_tag(1000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags2[3] = make_tag(1000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(1)); + expected_tags2[4] = make_tag(2000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags2[5] = make_tag(2000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(2)); + expected_tags2[6] = make_tag(3000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags2[7] = make_tag(3000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(3)); + expected_tags2[8] = make_tag(4000, pmt::mp(str1.str()), pmt::mp("seq"), pmt::mp(4)); + expected_tags2[9] = make_tag(4000, pmt::mp(str0.str()), pmt::mp("seq"), pmt::mp(4)); std::cout << std::endl << "qa_block_tags::t5" << std::endl; @@ -433,7 +443,7 @@ qa_block_tags::t5() std::cout << "tags1.size(): " << tags1.size() << std::endl; for(size_t i = 0; i < tags1.size(); i++) { std::cout << "tags1[" << i << "] = " << tags1[i] << "\t\t" << expected_tags1[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags1[i]), pmt::write_string(expected_tags1[i])); + CPPUNIT_ASSERT_EQUAL(tags1[i], expected_tags1[i]); } // annotator 2 gets tags from annotators 0 and 1 @@ -441,7 +451,7 @@ qa_block_tags::t5() std::cout << "tags2.size(): " << tags2.size() << std::endl; for(size_t i = 0; i < tags2.size(); i++) { std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; - CPPUNIT_ASSERT_EQUAL(pmt::write_string(tags2[i]), pmt::write_string(expected_tags2[i])); + CPPUNIT_ASSERT_EQUAL(tags2[i], expected_tags2[i]); } #endif } diff --git a/gr-blocks/lib/throttle_impl.cc b/gr-blocks/lib/throttle_impl.cc index f46decee11..7c24f80ae1 100644 --- a/gr-blocks/lib/throttle_impl.cc +++ b/gr-blocks/lib/throttle_impl.cc @@ -57,6 +57,14 @@ namespace gr { { } + bool + throttle_impl::start() + { + d_start = boost::get_system_time(); + d_total_samples = 0; + return block::start(); + } + void throttle_impl::set_sample_rate(double rate) { diff --git a/gr-blocks/lib/throttle_impl.h b/gr-blocks/lib/throttle_impl.h index c5e43d7564..6afacbba5d 100644 --- a/gr-blocks/lib/throttle_impl.h +++ b/gr-blocks/lib/throttle_impl.h @@ -41,6 +41,9 @@ namespace gr { throttle_impl(size_t itemsize, double samples_per_sec, bool ignore_tags=true); ~throttle_impl(); + // Overloading gr::block::start to reset timer + bool start(); + void setup_rpc(); void set_sample_rate(double rate); diff --git a/gr-blocks/lib/vector_source_X_impl.cc.t b/gr-blocks/lib/vector_source_X_impl.cc.t index 93f672bfb9..cb17c70d63 100644 --- a/gr-blocks/lib/vector_source_X_impl.cc.t +++ b/gr-blocks/lib/vector_source_X_impl.cc.t @@ -106,7 +106,7 @@ namespace gr { optr += size; for(unsigned t = 0; t < d_tags.size(); t++) { add_item_tag(0, nitems_written(0)+i+d_tags[t].offset, - d_tags[t].key, d_tags[t].value); + d_tags[t].key, d_tags[t].value, d_tags[t].srcid); } } } diff --git a/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h b/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h index 2715316a93..be38b6f8ae 100644 --- a/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h +++ b/gr-digital/include/gnuradio/digital/ofdm_frame_equalizer_vcvc.h @@ -58,18 +58,19 @@ namespace gr { /*! * \param equalizer The equalizer object that will do the actual work * \param cp_len Length of the cyclic prefix in samples (required to correct the frequency offset) - * \param len_tag_key Length tag key + * \param tsb_key TSB key * \param propagate_channel_state If true, the channel state after the last symbol * will be added to the first symbol as a tag - * \param fixed_frame_len Set if the frame length is fixed throughout, - * helps with book keeping. + * \param fixed_frame_len Set if the frame length is fixed. When this value is given, + * the TSB tag key can be left empty, but it is useful even + * when using tagged streams at the input. */ static sptr make( - ofdm_equalizer_base::sptr equalizer, - int cp_len, - const std::string &len_tag_key = "frame_len", - bool propagate_channel_state=false, - int fixed_frame_len=0 + ofdm_equalizer_base::sptr equalizer, + int cp_len, + const std::string &tsb_key="frame_len", + bool propagate_channel_state=false, + int fixed_frame_len=0 ); }; diff --git a/gr-digital/lib/header_payload_demux_impl.cc b/gr-digital/lib/header_payload_demux_impl.cc index 15308c0be1..160f54036d 100644 --- a/gr-digital/lib/header_payload_demux_impl.cc +++ b/gr-digital/lib/header_payload_demux_impl.cc @@ -1,5 +1,5 @@ /* -*- c++ -*- */ -/* Copyright 2012,2013 Free Software Foundation, Inc. +/* Copyright 2012-2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -300,20 +300,19 @@ namespace gr { } } if (d_uses_trigger_tag) { - std::vector<tag_t> tags; - get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+noutput_items, d_trigger_tag_key); - uint64_t min_offset = ULLONG_MAX; - int tag_index = -1; - for (unsigned i = 0; i < tags.size(); i++) { - if (tags[i].offset < min_offset) { - tag_index = (int) i; - min_offset = tags[i].offset; - } - } - if (tag_index != -1) { - remove_item_tag(0, tags[tag_index]); - return min_offset - nitems_read(0); - } + std::vector<tag_t> tags; + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+noutput_items, d_trigger_tag_key); + uint64_t min_offset = ULLONG_MAX; + int tag_index = -1; + for (unsigned i = 0; i < tags.size(); i++) { + if (tags[i].offset < min_offset) { + tag_index = (int) i; + min_offset = tags[i].offset; + } + } + if (tag_index != -1) { + return min_offset - nitems_read(0); + } } return -1; } /* find_trigger_signal() */ @@ -388,26 +387,30 @@ namespace gr { // Copy tags std::vector<tag_t> tags; get_tags_in_range( - tags, 0, - nitems_read(0), - nitems_read(0) + n_symbols * (d_items_per_symbol + d_gi) + tags, 0, + nitems_read(0), + nitems_read(0) + n_symbols * (d_items_per_symbol + d_gi) ); - for (unsigned t = 0; t < tags.size(); t++) { - int new_offset = tags[t].offset - nitems_read(0); - if (d_output_symbols) { - new_offset /= (d_items_per_symbol + d_gi); - } else if (d_gi) { - int pos_on_symbol = (new_offset % (d_items_per_symbol + d_gi)) - d_gi; - if (pos_on_symbol < 0) { - pos_on_symbol = 0; - } - new_offset = (new_offset / (d_items_per_symbol + d_gi)) + pos_on_symbol; - } - add_item_tag(port, - nitems_written(port) + new_offset, - tags[t].key, - tags[t].value - ); + for (size_t t = 0; t < tags.size(); t++) { + // The trigger tag is *not* propagated + if (tags[t].key == d_trigger_tag_key) { + continue; + } + int new_offset = tags[t].offset - nitems_read(0); + if (d_output_symbols) { + new_offset /= (d_items_per_symbol + d_gi); + } else if (d_gi) { + int pos_on_symbol = (new_offset % (d_items_per_symbol + d_gi)) - d_gi; + if (pos_on_symbol < 0) { + pos_on_symbol = 0; + } + new_offset = (new_offset / (d_items_per_symbol + d_gi)) + pos_on_symbol; + } + add_item_tag(port, + nitems_written(port) + new_offset, + tags[t].key, + tags[t].value + ); } } /* copy_n_symbols() */ diff --git a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc index 4446306a8b..70e840d778 100644 --- a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc +++ b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc @@ -29,6 +29,9 @@ #define M_TWOPI (2*M_PI) +static const pmt::pmt_t CARR_OFFSET_KEY = pmt::mp("ofdm_sync_carr_offset"); +static const pmt::pmt_t CHAN_TAPS_KEY = pmt::mp("ofdm_sync_chan_taps"); + namespace gr { namespace digital { @@ -36,14 +39,14 @@ namespace gr { ofdm_frame_equalizer_vcvc::make( ofdm_equalizer_base::sptr equalizer, int cp_len, - const std::string &len_tag_key, + const std::string &tsb_key, bool propagate_channel_state, int fixed_frame_len ) { return gnuradio::get_initial_sptr ( new ofdm_frame_equalizer_vcvc_impl( - equalizer, cp_len, len_tag_key, propagate_channel_state, fixed_frame_len + equalizer, cp_len, tsb_key, propagate_channel_state, fixed_frame_len ) ); } @@ -51,13 +54,13 @@ namespace gr { ofdm_frame_equalizer_vcvc_impl::ofdm_frame_equalizer_vcvc_impl( ofdm_equalizer_base::sptr equalizer, int cp_len, - const std::string &len_tag_key, + const std::string &tsb_key, bool propagate_channel_state, int fixed_frame_len ) : tagged_stream_block("ofdm_frame_equalizer_vcvc", io_signature::make(1, 1, sizeof (gr_complex) * equalizer->fft_len()), io_signature::make(1, 1, sizeof (gr_complex) * equalizer->fft_len()), - len_tag_key), + tsb_key), d_fft_len(equalizer->fft_len()), d_cp_len(cp_len), d_eq(equalizer), @@ -65,16 +68,18 @@ namespace gr { d_fixed_frame_len(fixed_frame_len), d_channel_state(equalizer->fft_len(), gr_complex(1, 0)) { - if (len_tag_key.empty() && fixed_frame_len == 0) { - throw std::invalid_argument("Either specify a length tag or a frame length!"); + if (tsb_key.empty() && fixed_frame_len == 0) { + throw std::invalid_argument("Either specify a TSB tag or a fixed frame length!"); } if (d_fixed_frame_len < 0) { - throw std::invalid_argument("Invalid frame length!"); + throw std::invalid_argument("Invalid frame length!"); } if (d_fixed_frame_len) { - set_output_multiple(d_fixed_frame_len); + set_output_multiple(d_fixed_frame_len); } set_relative_rate(1.0); + // Really, we have TPP_ONE_TO_ONE, but the channel state is not propagated + set_tag_propagation_policy(TPP_DONT); } ofdm_frame_equalizer_vcvc_impl::~ofdm_frame_equalizer_vcvc_impl() @@ -83,18 +88,17 @@ namespace gr { void ofdm_frame_equalizer_vcvc_impl::parse_length_tags( - const std::vector<std::vector<tag_t> > &tags, - gr_vector_int &n_input_items_reqd - ){ + const std::vector<std::vector<tag_t> > &tags, + gr_vector_int &n_input_items_reqd + ) { if (d_fixed_frame_len) { - n_input_items_reqd[0] = d_fixed_frame_len; + n_input_items_reqd[0] = d_fixed_frame_len; } else { - for (unsigned k = 0; k < tags[0].size(); k++) { - if (tags[0][k].key == pmt::string_to_symbol(d_length_tag_key_str)) { - n_input_items_reqd[0] = pmt::to_long(tags[0][k].value); - remove_item_tag(0, tags[0][k]); - } - } + for (unsigned k = 0; k < tags[0].size(); k++) { + if (tags[0][k].key == pmt::string_to_symbol(d_length_tag_key_str)) { + n_input_items_reqd[0] = pmt::to_long(tags[0][k].value); + } + } } } @@ -114,15 +118,14 @@ namespace gr { } std::vector<tag_t> tags; - get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1); + get_tags_in_window(tags, 0, 0, 1); for (unsigned i = 0; i < tags.size(); i++) { - if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_chan_taps") { - d_channel_state = pmt::c32vector_elements(tags[i].value); - remove_item_tag(0, tags[i]); - } - if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_carr_offset") { - carrier_offset = pmt::to_long(tags[i].value); - } + if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_chan_taps") { + d_channel_state = pmt::c32vector_elements(tags[i].value); + } + if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_carr_offset") { + carrier_offset = pmt::to_long(tags[i].value); + } } // Copy the frame and the channel state vector such that the symbols are shifted to the correct position @@ -157,7 +160,16 @@ namespace gr { // Update the channel state regarding the frequency offset phase_correction = gr_expj(M_TWOPI * carrier_offset * d_cp_len / d_fft_len * frame_len); for (int k = 0; k < d_fft_len; k++) { - d_channel_state[k] *= phase_correction; + d_channel_state[k] *= phase_correction; + } + + // Propagate tags (except for the channel state and the TSB tag) + get_tags_in_window(tags, 0, 0, frame_len); + for (size_t i = 0; i < tags.size(); i++) { + if (tags[i].key != CHAN_TAPS_KEY + and tags[i].key != pmt::mp(d_length_tag_key_str)) { + add_item_tag(0, tags[i]); + } } // Housekeeping diff --git a/gr-digital/lib/ofdm_serializer_vcc_impl.cc b/gr-digital/lib/ofdm_serializer_vcc_impl.cc index f6c796d3c5..1398dcd2a1 100644 --- a/gr-digital/lib/ofdm_serializer_vcc_impl.cc +++ b/gr-digital/lib/ofdm_serializer_vcc_impl.cc @@ -1,5 +1,5 @@ /* -*- c++ -*- */ -/* Copyright 2012 Free Software Foundation, Inc. +/* Copyright 2012,2014 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -157,55 +157,57 @@ namespace gr { std::vector<tag_t> tags; // Packet mode if (!d_length_tag_key_str.empty()) { - get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1); - for (unsigned i = 0; i < tags.size(); i++) { - if (tags[i].key == d_carr_offset_key) { - carr_offset = pmt::to_long(tags[i].value); - } - if (tags[i].key == d_packet_len_tag_key) { - packet_length = pmt::to_long(tags[i].value); - remove_item_tag(0, tags[i]); - } - } + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1); + for (unsigned i = 0; i < tags.size(); i++) { + if (tags[i].key == d_carr_offset_key) { + carr_offset = pmt::to_long(tags[i].value); + } + if (tags[i].key == d_packet_len_tag_key) { + packet_length = pmt::to_long(tags[i].value); + } + } } else { - // recalc frame length from noutput_items - frame_length = 0; - int sym_per_frame = 0; - while ((sym_per_frame + d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size()) < (size_t)noutput_items) { - frame_length++; - sym_per_frame += d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size(); - } + // recalc frame length from noutput_items + frame_length = 0; + int sym_per_frame = 0; + while ((sym_per_frame + d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size()) < (size_t)noutput_items) { + frame_length++; + sym_per_frame += d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size(); + } } // Copy symbols int n_out_symbols = 0; for (int i = 0; i < frame_length; i++) { - // Copy all tags associated with this input OFDM symbol onto the first output symbol - get_tags_in_range(tags, 0, - nitems_read(0)+i, - nitems_read(0)+i+1 - ); - for (unsigned t = 0; t < tags.size(); t++) { - add_item_tag(0, nitems_written(0)+n_out_symbols, - tags[t].key, - tags[t].value - ); - } - for (unsigned k = 0; k < d_occupied_carriers[d_curr_set].size(); k++) { - out[n_out_symbols++] = in[i * d_fft_len + d_occupied_carriers[d_curr_set][k] + carr_offset]; - } - if (packet_length && n_out_symbols > packet_length) { - n_out_symbols = packet_length; - break; - } - d_curr_set = (d_curr_set + 1) % d_occupied_carriers.size(); + // Copy all tags associated with this input OFDM symbol onto the first output symbol + get_tags_in_range(tags, 0, + nitems_read(0)+i, + nitems_read(0)+i+1 + ); + for (size_t t = 0; t < tags.size(); t++) { + // The packet length tag is not propagated + if (tags[t].key != d_packet_len_tag_key) { + add_item_tag(0, nitems_written(0)+n_out_symbols, + tags[t].key, + tags[t].value + ); + } + } + for (unsigned k = 0; k < d_occupied_carriers[d_curr_set].size(); k++) { + out[n_out_symbols++] = in[i * d_fft_len + d_occupied_carriers[d_curr_set][k] + carr_offset]; + } + if (packet_length && n_out_symbols > packet_length) { + n_out_symbols = packet_length; + break; + } + d_curr_set = (d_curr_set + 1) % d_occupied_carriers.size(); } // Housekeeping if (d_length_tag_key_str.empty()) { - consume_each(frame_length); + consume_each(frame_length); } else { - d_curr_set = d_symbols_skipped; + d_curr_set = d_symbols_skipped; } return n_out_symbols; diff --git a/gr-digital/python/digital/qa_header_payload_demux.py b/gr-digital/python/digital/qa_header_payload_demux.py index 0b754fe248..8006d4442e 100755 --- a/gr-digital/python/digital/qa_header_payload_demux.py +++ b/gr-digital/python/digital/qa_header_payload_demux.py @@ -113,6 +113,86 @@ class qa_header_payload_demux (gr_unittest.TestCase): ] self.assertEqual(expected_tags_payload, ptags_payload) + def test_001_t_tags (self): + """ Like the previous test, but use a trigger tag instead of + a trigger signal. + """ + n_zeros = 1 + header = (1, 2, 3) + payload = tuple(range(5, 20)) + data_signal = (0,) * n_zeros + header + payload + # Trigger tag + trigger_tag = gr.tag_t() + trigger_tag.offset = n_zeros + trigger_tag.key = pmt.string_to_symbol('detect') + trigger_tag.value = pmt.PMT_T + # This is dropped: + testtag1 = gr.tag_t() + testtag1.offset = 0 + testtag1.key = pmt.string_to_symbol('tag1') + testtag1.value = pmt.from_long(0) + # This goes on output 0, item 0: + testtag2 = gr.tag_t() + testtag2.offset = n_zeros + testtag2.key = pmt.string_to_symbol('tag2') + testtag2.value = pmt.from_long(23) + # This goes on output 0, item 2: + testtag3 = gr.tag_t() + testtag3.offset = n_zeros + len(header) - 1 + testtag3.key = pmt.string_to_symbol('tag3') + testtag3.value = pmt.from_long(42) + # This goes on output 1, item 3: + testtag4 = gr.tag_t() + testtag4.offset = n_zeros + len(header) + 3 + testtag4.key = pmt.string_to_symbol('tag4') + testtag4.value = pmt.from_long(314) + data_src = blocks.vector_source_f( + data_signal, + False, + tags=(trigger_tag, testtag1, testtag2, testtag3, testtag4) + ) + hpd = digital.header_payload_demux( + len(header), 1, 0, "frame_len", "detect", False, gr.sizeof_float + ) + self.assertEqual(pmt.length(hpd.message_ports_in()), 2) #extra system port defined for you + header_sink = blocks.vector_sink_f() + payload_sink = blocks.vector_sink_f() + + self.tb.connect(data_src, (hpd, 0)) + self.tb.connect((hpd, 0), header_sink) + self.tb.connect((hpd, 1), payload_sink) + self.tb.start() + time.sleep(.2) # Need this, otherwise, the next message is ignored + hpd.to_basic_block()._post( + pmt.intern('header_data'), + pmt.from_long(len(payload)) + ) + while len(payload_sink.data()) < len(payload): + time.sleep(.2) + self.tb.stop() + self.tb.wait() + + self.assertEqual(header_sink.data(), header) + self.assertEqual(payload_sink.data(), payload) + ptags_header = [] + for tag in header_sink.tags(): + ptag = gr.tag_to_python(tag) + ptags_header.append({'key': ptag.key, 'offset': ptag.offset}) + expected_tags_header = [ + {'key': 'tag2', 'offset': 0}, + {'key': 'tag3', 'offset': 2}, + ] + self.assertEqual(expected_tags_header, ptags_header) + ptags_payload = [] + for tag in payload_sink.tags(): + ptag = gr.tag_to_python(tag) + ptags_payload.append({'key': ptag.key, 'offset': ptag.offset}) + expected_tags_payload = [ + {'key': 'frame_len', 'offset': 0}, + {'key': 'tag4', 'offset': 3}, + ] + self.assertEqual(expected_tags_payload, ptags_payload) + def test_002_symbols (self): """ Same as before, but operate on symbols diff --git a/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py index c42fb2b907..1b3ffb7738 100755 --- a/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py +++ b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py @@ -72,7 +72,7 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase): ptag = gr.tag_to_python(tag) tag_dict[ptag.key] = ptag.value expected_dict = { - 'foo': 42 + 'foo': 42 } self.assertEqual(tag_dict, expected_dict) diff --git a/gr-fec/lib/decoder_impl.cc b/gr-fec/lib/decoder_impl.cc index ba8a7d000e..62c301d501 100644 --- a/gr-fec/lib/decoder_impl.cc +++ b/gr-fec/lib/decoder_impl.cc @@ -95,8 +95,8 @@ namespace gr { noutput_items/(output_multiple() - d_decoder->get_history()) : innum; - GR_LOG_DEBUG(d_debug_logger, boost::format("%1%, %2%, %3%") \ - % outnum % ninput_items[0] % items); + //GR_LOG_DEBUG(d_debug_logger, boost::format("%1%, %2%, %3%") \ + // % outnum % ninput_items[0] % items); for(int i = 0; i < items; ++i) { d_decoder->generic_work((void*)(in+(i*d_decoder->get_input_size()*d_input_item_size)), @@ -109,8 +109,8 @@ namespace gr { int consumed = static_cast<int>(items/relative_rate()*(output_multiple() - d_decoder->get_history()) + 0.5); int returned = items*(output_multiple() - d_decoder->get_history()); - GR_LOG_DEBUG(d_debug_logger, boost::format("consumed %1%") % consumed); - GR_LOG_DEBUG(d_debug_logger, boost::format("returned %1%") % returned); + //GR_LOG_DEBUG(d_debug_logger, boost::format("consumed %1%") % consumed); + //GR_LOG_DEBUG(d_debug_logger, boost::format("returned %1%") % returned); consume_each(consumed); return returned; diff --git a/gr-fec/lib/encoder_impl.cc b/gr-fec/lib/encoder_impl.cc index 399bcc41cf..af72f31133 100644 --- a/gr-fec/lib/encoder_impl.cc +++ b/gr-fec/lib/encoder_impl.cc @@ -91,8 +91,8 @@ namespace gr { char *inbuffer = (char*)input_items[0]; char *outbuffer = (char*)output_items[0]; - GR_LOG_DEBUG(d_debug_logger, boost::format("%1%, %2%, %3%") \ - % noutput_items % ninput_items[0] % (noutput_items/output_multiple())); + //GR_LOG_DEBUG(d_debug_logger, boost::format("%1%, %2%, %3%") \ + // % noutput_items % ninput_items[0] % (noutput_items/output_multiple())); for(int i = 0; i < noutput_items/output_multiple(); i++) { @@ -100,10 +100,10 @@ namespace gr { (void*)(outbuffer+(i*d_output_size))); } - GR_LOG_DEBUG(d_debug_logger, boost::format("consuming: %1%") \ - % (fixed_rate_noutput_to_ninput(noutput_items))); - GR_LOG_DEBUG(d_debug_logger, boost::format("returning: %1%") \ - % (noutput_items)); + //GR_LOG_DEBUG(d_debug_logger, boost::format("consuming: %1%") \ + // % (fixed_rate_noutput_to_ninput(noutput_items))); + //GR_LOG_DEBUG(d_debug_logger, boost::format("returning: %1%") \ + // % (noutput_items)); consume_each(fixed_rate_noutput_to_ninput(noutput_items)); return noutput_items; diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc index 1a17e87775..c184f0a406 100644 --- a/gr-uhd/lib/usrp_sink_impl.cc +++ b/gr-uhd/lib/usrp_sink_impl.cc @@ -88,7 +88,7 @@ namespace gr { { bool clocks_locked = true; - // 1) Check ref lock for all mboards + // Check ref lock for all mboards for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) { std::string sensor_name = "ref_locked"; if (_dev->get_clock_source(mboard_index) == "internal") { @@ -107,19 +107,6 @@ namespace gr { } } - // 2) Check LO for all channels - for (size_t i = 0; i < _nchan; i++) { - size_t chan_index = _stream_args.channels[i]; - if (not _wait_for_locked_sensor( - get_sensor_names(chan_index), - "lo_locked", - boost::bind(&usrp_sink_impl::get_sensor, this, _1, chan_index) - )) { - GR_LOG_WARN(d_logger, boost::format("Sensor 'lo_locked' failed to lock within timeout on channel %d.") % chan_index); - clocks_locked = false; - } - } - return clocks_locked; } diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc index 6be0bac9ca..3142627952 100644 --- a/gr-uhd/lib/usrp_source_impl.cc +++ b/gr-uhd/lib/usrp_source_impl.cc @@ -87,7 +87,7 @@ namespace gr { { bool clocks_locked = true; - // 1) Check ref lock for all mboards + // Check ref lock for all mboards for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) { std::string sensor_name = "ref_locked"; if (_dev->get_clock_source(mboard_index) == "internal") { @@ -106,19 +106,6 @@ namespace gr { } } - // 2) Check LO for all channels - for (size_t i = 0; i < _nchan; i++) { - size_t chan_index = _stream_args.channels[i]; - if (not _wait_for_locked_sensor( - get_sensor_names(chan_index), - "lo_locked", - boost::bind(&usrp_source_impl::get_sensor, this, _1, chan_index) - )) { - GR_LOG_WARN(d_logger, boost::format("Sensor 'lo_locked' failed to lock within timeout on channel %d.") % chan_index); - clocks_locked = false; - } - } - return clocks_locked; } diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py index 02d1b112c4..fb25b46821 100644 --- a/grc/base/FlowGraph.py +++ b/grc/base/FlowGraph.py @@ -17,11 +17,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +import time from . import odict from Element import Element from .. gui import Messages from . Constants import FLOW_GRAPH_FILE_FORMAT_VERSION + class FlowGraph(Element): def __init__(self, platform): @@ -36,6 +38,8 @@ class FlowGraph(Element): """ #initialize Element.__init__(self, platform) + self._elements = [] + self._timestamp = time.ctime() #inital blank import self.import_data() @@ -51,12 +55,14 @@ class FlowGraph(Element): """ index = 0 while True: - id = '%s_%d'%(base_id, index) - index = index + 1 + id = '%s_%d' % (base_id, index) + index += 1 #make sure that the id is not used by another block if not filter(lambda b: b.get_id() == id, self.get_blocks()): return id - def __str__(self): return 'FlowGraph - %s(%s)'%(self.get_option('title'), self.get_option('id')) + def __str__(self): + return 'FlowGraph - %s(%s)' % (self.get_option('title'), self.get_option('id')) + def rewrite(self): def refactor_bus_structure(): @@ -242,9 +248,8 @@ class FlowGraph(Element): Returns: a nested data odict """ - import time n = odict() - n['timestamp'] = time.ctime() + n['timestamp'] = self._timestamp n['block'] = [block.export_data() for block in self.get_blocks()] n['connection'] = [connection.export_data() for connection in self.get_connections()] instructions = odict({ @@ -273,6 +278,7 @@ class FlowGraph(Element): file_format = 0 #use blank data if none provided fg_n = n and n.find('flow_graph') or odict() + self._timestamp = fg_n.find('timestamp') or time.ctime() blocks_n = fg_n.findall('block') connections_n = fg_n.findall('connection') #create option block @@ -384,7 +390,7 @@ def _initialize_dummy_block(block, block_n): """ block._key = block_n.find('key') block.is_dummy_block = lambda: True - block.is_valid = lambda: False + block.is_valid = lambda: False block.get_enabled = lambda: False for param_n in block_n.findall('param'): if param_n['key'] not in block.get_param_keys(): @@ -393,7 +399,7 @@ def _initialize_dummy_block(block, block_n): def _dummy_block_add_port(block, key, dir): - """This is so ugly... Add a port to a dummy-fied block""" + """This is so ugly... Add a port to a dummy-field block""" port_n = odict({'name': '?', 'key': key, 'type': ''}) port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir) if port.is_source(): diff --git a/grc/blocks/options.xml b/grc/blocks/options.xml index 0c3a804fd7..c1c94e4e24 100644 --- a/grc/blocks/options.xml +++ b/grc/blocks/options.xml @@ -58,17 +58,17 @@ else: self.stop(); self.wait()</callback> <param> <name>Generate Options</name> <key>generate_options</key> - <value>wx_gui</value> + <value>qt_gui</value> <type>enum</type> <option> - <name>WX GUI</name> - <key>wx_gui</key> - </option> - <option> <name>QT GUI</name> <key>qt_gui</key> </option> <option> + <name>WX GUI</name> + <key>wx_gui</key> + </option> + <option> <name>No GUI</name> <key>no_gui</key> </option> diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index f8963fa472..6c56a94e9c 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -495,9 +495,11 @@ class ActionHandler: ExecFlowGraphThread(self) elif action == Actions.FLOW_GRAPH_KILL: if self.get_page().get_proc(): - try: self.get_page().get_proc().kill() - except: print "could not kill process: %d"%self.get_page().get_proc().pid - elif action == Actions.PAGE_CHANGE: #pass and run the global actions + try: + self.get_page().get_proc().kill() + except: + print "could not kill process: %d" % self.get_page().get_proc().pid + elif action == Actions.PAGE_CHANGE: # pass and run the global actions pass elif action == Actions.RELOAD_BLOCKS: self.platform.load_blocks() @@ -583,7 +585,7 @@ class ActionHandler: sensitive = self.get_flow_graph().is_valid() and not self.get_page().get_proc() Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive) Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive) - Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() != None) + Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() is not None) class ExecFlowGraphThread(Thread): """Execute the flow graph as a new process and wait on it to finish.""" @@ -619,13 +621,14 @@ class ExecFlowGraphThread(Thread): """ #handle completion r = "\n" - while(r): + while r: gobject.idle_add(Messages.send_verbose_exec, r) r = os.read(self.p.stdout.fileno(), 1024) + self.p.poll() gobject.idle_add(self.done) def done(self): """Perform end of execution tasks.""" - Messages.send_end_exec() + Messages.send_end_exec(self.p.returncode) self.page.set_proc(None) self.update_exec_stop() diff --git a/grc/gui/Block.py b/grc/gui/Block.py index 1a32f6c2ba..9b8d3b1b56 100644 --- a/grc/gui/Block.py +++ b/grc/gui/Block.py @@ -25,7 +25,7 @@ from Constants import BORDER_PROXIMITY_SENSITIVITY from Constants import \ BLOCK_LABEL_PADDING, \ PORT_SEPARATION, LABEL_SEPARATION, \ - PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS + PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS, BLOCK_FONT, PARAM_FONT import Actions import pygtk pygtk.require('2.0') @@ -34,7 +34,7 @@ import pango BLOCK_MARKUP_TMPL="""\ #set $foreground = $block.is_valid() and 'black' or 'red' -<span foreground="$foreground" font_desc="Sans 8"><b>$encode($block.get_name())</b></span>""" +<span foreground="$foreground" font_desc="$font"><b>$encode($block.get_name())</b></span>""" class Block(Element): """The graphical signal block.""" @@ -146,11 +146,13 @@ class Block(Element): #create the main layout layout = gtk.DrawingArea().create_pango_layout('') layouts.append(layout) - layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self)) + layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self, font=BLOCK_FONT)) self.label_width, self.label_height = layout.get_pixel_size() #display the params if self.is_dummy_block(): - markups = ['<span foreground="black" font_desc="Sans 7.5"><b>key: </b>{}</span>'.format(self._key)] + markups = [ + '<span foreground="black" font_desc="$font"><b>key: </b>{key}</span>'.format(font=PARAM_FONT, key=self._key) + ] else: markups = [param.get_markup() for param in self.get_params() if param.get_hide() not in ('all', 'part')] if markups: diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py index 7db291df99..0dc6279fd2 100644 --- a/grc/gui/Constants.py +++ b/grc/gui/Constants.py @@ -41,6 +41,13 @@ MIN_DIALOG_HEIGHT = 500 ##default sizes DEFAULT_BLOCKS_WINDOW_WIDTH = 100 DEFAULT_REPORTS_WINDOW_WIDTH = 100 +## flow-graph canvas fonts +FONT_FAMILY = "Sans" +FONT_SIZE = 8 +BLOCK_FONT = "%s %f" % (FONT_FAMILY, FONT_SIZE) +PORT_FONT = BLOCK_FONT +PARAM_FONT = "%s %f" % (FONT_FAMILY, FONT_SIZE - 0.5) + ##The size of the state saving cache in the flow graph (for undo/redo functionality) STATE_CACHE_SIZE = 42 diff --git a/grc/gui/Messages.py b/grc/gui/Messages.py index f220b6dd06..90f508d770 100644 --- a/grc/gui/Messages.py +++ b/grc/gui/Messages.py @@ -24,15 +24,17 @@ import os ## A list of functions that can receive a message. MESSENGERS_LIST = list() + def register_messenger(messenger): """ Append the given messenger to the list of messengers. Args: - messenger: a method thats takes a string + messenger: a method that takes a string """ MESSENGERS_LIST.append(messenger) + def send(message): """ Give the message to each of the messengers. @@ -102,8 +104,8 @@ def send_start_exec(file_path): def send_verbose_exec(verbose): send(verbose) -def send_end_exec(): - send('\n>>> Done\n') +def send_end_exec(returncode=0): + send('\n>>> Done%s\n' % (" (return code %s)" % returncode if returncode else "")) ################# functions for saving flow graphs ######################################## def send_fail_save(file_path): diff --git a/grc/gui/Param.py b/grc/gui/Param.py index 499af2e2ed..76dafdf3cc 100644 --- a/grc/gui/Param.py +++ b/grc/gui/Param.py @@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import Utils from Element import Element +from . Constants import PARAM_FONT import pygtk pygtk.require('2.0') import gtk @@ -184,7 +185,7 @@ class FileParam(EntryParam): PARAM_MARKUP_TMPL="""\ #set $foreground = $param.is_valid() and 'black' or 'red' -<span foreground="$foreground" font_desc="Sans 7.5"><b>$encode($param.get_name()): </b>$encode(repr($param))</span>""" +<span foreground="$foreground" font_desc="$font"><b>$encode($param.get_name()): </b>$encode(repr($param))</span>""" PARAM_LABEL_MARKUP_TMPL="""\ #set $foreground = $modified and 'blue' or $param.is_valid() and 'black' or 'red' @@ -249,4 +250,4 @@ class Param(Element): Returns: a pango markup string """ - return Utils.parse_template(PARAM_MARKUP_TMPL, param=self) + return Utils.parse_template(PARAM_MARKUP_TMPL, param=self, font=PARAM_FONT) diff --git a/grc/gui/Port.py b/grc/gui/Port.py index 364ca6a5b9..2a87573911 100644 --- a/grc/gui/Port.py +++ b/grc/gui/Port.py @@ -21,7 +21,7 @@ from Element import Element from Constants import \ PORT_SEPARATION, CONNECTOR_EXTENSION_MINIMAL, \ CONNECTOR_EXTENSION_INCREMENT, \ - PORT_LABEL_PADDING, PORT_MIN_WIDTH, PORT_LABEL_HIDDEN_WIDTH + PORT_LABEL_PADDING, PORT_MIN_WIDTH, PORT_LABEL_HIDDEN_WIDTH, PORT_FONT import Utils import Actions import Colors @@ -29,10 +29,8 @@ import pygtk pygtk.require('2.0') import gtk -PORT_HIDDEN_MARKUP_TMPL="""\ -<span foreground="black" font_desc="Sans 7.5"> </span>""" PORT_MARKUP_TMPL="""\ -<span foreground="black" font_desc="Sans 7.5">$encode($port.get_name())</span>""" +<span foreground="black" font_desc="$font">$encode($port.get_name())</span>""" class Port(Element): @@ -115,7 +113,7 @@ class Port(Element): self._bg_color = Colors.get_color(self.get_color()) #create the layout layout = gtk.DrawingArea().create_pango_layout('') - layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self)) + layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self, font=PORT_FONT)) self.w, self.h = layout.get_pixel_size() self.W, self.H = 2*PORT_LABEL_PADDING + self.w, 2*PORT_LABEL_PADDING+self.h self.H = self.modify_height(self.H) diff --git a/volk/apps/volk_profile.cc b/volk/apps/volk_profile.cc index 074d1e7be4..416884734d 100644 --- a/volk/apps/volk_profile.cc +++ b/volk/apps/volk_profile.cc @@ -37,6 +37,49 @@ namespace fs = boost::filesystem; +void write_json(std::ofstream &json_file, std::vector<volk_test_results_t> results) { + json_file << "{" << std::endl; + json_file << " \"volk_tests\": [" << std::endl; + size_t len = results.size(); + size_t i = 0; + BOOST_FOREACH(volk_test_results_t &result, results) { + json_file << " {" << std::endl; + json_file << " \"name\": \"" << result.name << "\"," << std::endl; + json_file << " \"vlen\": " << result.vlen << "," << std::endl; + json_file << " \"iter\": " << result.iter << "," << std::endl; + json_file << " \"best_arch_a\": \"" << result.best_arch_a + << "\"," << std::endl; + json_file << " \"best_arch_u\": \"" << result.best_arch_u + << "\"," << std::endl; + json_file << " \"results\": {" << std::endl; + size_t results_len = result.results.size(); + size_t ri = 0; + typedef std::pair<std::string, volk_test_time_t> tpair; + BOOST_FOREACH(tpair pair, result.results) { + volk_test_time_t time = pair.second; + json_file << " \"" << time.name << "\": {" << std::endl; + json_file << " \"name\": \"" << time.name << "\"," << std::endl; + json_file << " \"time\": " << time.time << "," << std::endl; + json_file << " \"units\": \"" << time.units << "\"" << std::endl; + json_file << " }" ; + if(ri+1 != results_len) { + json_file << ","; + } + json_file << std::endl; + ri++; + } + json_file << " }" << std::endl; + json_file << " }"; + if(i+1 != len) { + json_file << ","; + } + json_file << std::endl; + i++; + } + json_file << " ]" << std::endl; + json_file << "}" << std::endl; +} + int main(int argc, char *argv[]) { // Adding program options boost::program_options::options_description desc("Options"); @@ -49,6 +92,9 @@ int main(int argc, char *argv[]) { ("tests-regex,R", boost::program_options::value<std::string>(), "Run tests matching regular expression.") + ("json,j", + boost::program_options::value<std::string>(), + "JSON output file") ; // Handle the options that were given @@ -56,6 +102,8 @@ int main(int argc, char *argv[]) { bool benchmark_mode; std::string kernel_regex; bool store_results = true; + std::ofstream json_file; + try { boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); boost::program_options::notify(vm); @@ -83,9 +131,14 @@ int main(int argc, char *argv[]) { return 0; } + if ( vm.count("json") ) + { + json_file.open( vm["json"].as<std::string>().c_str() ); + } + // Run tests - std::vector<std::string> results; + std::vector<volk_test_results_t> results; //VOLK_PROFILE(volk_16i_x5_add_quad_16i_x4, 1e-4, 2046, 10000, &results, benchmark_mode, kernel_regex); //VOLK_PROFILE(volk_16i_branch_4_state_8, 1e-4, 2046, 10000, &results, benchmark_mode, kernel_regex); @@ -178,6 +231,7 @@ int main(int argc, char *argv[]) { VOLK_PROFILE(volk_32f_s32f_multiply_32f, 1e-4, 1.0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32f_binary_slicer_32i, 0, 1.0, 204602, 10000, &results, benchmark_mode, kernel_regex); VOLK_PROFILE(volk_32f_binary_slicer_8i, 0, 1.0, 204602, 10000, &results, benchmark_mode, kernel_regex); + VOLK_PROFILE(volk_32f_tanh_32f, 1e-6, 0, 204602, 1000, &results, benchmark_mode, kernel_regex); // Until we can update the config on a kernel by kernel basis // do not overwrite volk_config when using a regex. @@ -204,8 +258,10 @@ int main(int argc, char *argv[]) { #the function name is followed by the preferred architecture.\n\ "; - BOOST_FOREACH(std::string result, results) { - config << result << std::endl; + BOOST_FOREACH(volk_test_results_t result, results) { + config << result.config_name << " " + << result.best_arch_a << " " + << result.best_arch_u << std::endl; } config.close(); } diff --git a/volk/kernels/volk/volk_32f_tanh_32f.h b/volk/kernels/volk/volk_32f_tanh_32f.h new file mode 100644 index 0000000000..3f407d4656 --- /dev/null +++ b/volk/kernels/volk/volk_32f_tanh_32f.h @@ -0,0 +1,296 @@ +#ifndef INCLUDED_volk_32f_tanh_32f_a_H +#define INCLUDED_volk_32f_tanh_32f_a_H + +#include <inttypes.h> +#include <stdio.h> +#include <math.h> +#include <string.h> + +#ifdef LV_HAVE_GENERIC +/*! +\brief Calculates tanh(x) +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_generic(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + float* cPtr = cVector; + const float* aPtr = aVector; + for(; number < num_points; number++) { + *cPtr++ = tanh(*aPtr++); + } +} + +#endif /* LV_HAVE_GENERIC */ + + +#ifdef LV_HAVE_GENERIC +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_series(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + float* cPtr = cVector; + const float* aPtr = aVector; + for(; number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} + +#endif /* LV_HAVE_GENERIC */ + + + +#ifdef LV_HAVE_SSE +#include <xmmintrin.h> +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_a_sse(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + float* cPtr = cVector; + const float* aPtr = aVector; + + __m128 aVal, cVal, x2, a, b; + __m128 const1, const2, const3, const4, const5, const6; + const1 = _mm_set_ps1(135135.0f); + const2 = _mm_set_ps1(17325.0f); + const3 = _mm_set_ps1(378.0f); + const4 = _mm_set_ps1(62370.0f); + const5 = _mm_set_ps1(3150.0f); + const6 = _mm_set_ps1(28.0f); + for(;number < quarterPoints; number++){ + + aVal = _mm_load_ps(aPtr); + x2 = _mm_mul_ps(aVal, aVal); + a = _mm_mul_ps(aVal, _mm_add_ps(const1, _mm_mul_ps(x2, _mm_add_ps(const2, _mm_mul_ps(x2, _mm_add_ps(const3, x2)))))); + b = _mm_add_ps(const1, _mm_mul_ps(x2, _mm_add_ps(const4, _mm_mul_ps(x2, _mm_add_ps(const5, _mm_mul_ps(x2, const6)))))); + + cVal = _mm_div_ps(a, b); + + _mm_store_ps(cPtr, cVal); // Store the results back into the C container + + aPtr += 4; + cPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} +#endif /* LV_HAVE_SSE */ + + +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_a_avx(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + float* cPtr = cVector; + const float* aPtr = aVector; + + __m256 aVal, cVal, x2, a, b; + __m256 const1, const2, const3, const4, const5, const6; + const1 = _mm256_set1_ps(135135.0f); + const2 = _mm256_set1_ps(17325.0f); + const3 = _mm256_set1_ps(378.0f); + const4 = _mm256_set1_ps(62370.0f); + const5 = _mm256_set1_ps(3150.0f); + const6 = _mm256_set1_ps(28.0f); + for(;number < eighthPoints; number++){ + + aVal = _mm256_load_ps(aPtr); + x2 = _mm256_mul_ps(aVal, aVal); + a = _mm256_mul_ps(aVal, _mm256_add_ps(const1, _mm256_mul_ps(x2, _mm256_add_ps(const2, _mm256_mul_ps(x2, _mm256_add_ps(const3, x2)))))); + b = _mm256_add_ps(const1, _mm256_mul_ps(x2, _mm256_add_ps(const4, _mm256_mul_ps(x2, _mm256_add_ps(const5, _mm256_mul_ps(x2, const6)))))); + + cVal = _mm256_div_ps(a, b); + + _mm256_store_ps(cPtr, cVal); // Store the results back into the C container + + aPtr += 8; + cPtr += 8; + } + + number = eighthPoints * 8; + for(;number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} +#endif /* LV_HAVE_AVX */ + + + + +#ifdef LV_HAVE_SSE +#include <xmmintrin.h> +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_u_sse(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + const unsigned int quarterPoints = num_points / 4; + + float* cPtr = cVector; + const float* aPtr = aVector; + + __m128 aVal, cVal, x2, a, b; + __m128 const1, const2, const3, const4, const5, const6; + const1 = _mm_set_ps1(135135.0f); + const2 = _mm_set_ps1(17325.0f); + const3 = _mm_set_ps1(378.0f); + const4 = _mm_set_ps1(62370.0f); + const5 = _mm_set_ps1(3150.0f); + const6 = _mm_set_ps1(28.0f); + for(;number < quarterPoints; number++){ + + aVal = _mm_loadu_ps(aPtr); + x2 = _mm_mul_ps(aVal, aVal); + a = _mm_mul_ps(aVal, _mm_add_ps(const1, _mm_mul_ps(x2, _mm_add_ps(const2, _mm_mul_ps(x2, _mm_add_ps(const3, x2)))))); + b = _mm_add_ps(const1, _mm_mul_ps(x2, _mm_add_ps(const4, _mm_mul_ps(x2, _mm_add_ps(const5, _mm_mul_ps(x2, const6)))))); + + cVal = _mm_div_ps(a, b); + + _mm_storeu_ps(cPtr, cVal); // Store the results back into the C container + + aPtr += 4; + cPtr += 4; + } + + number = quarterPoints * 4; + for(;number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} +#endif /* LV_HAVE_SSE */ + + + +#ifdef LV_HAVE_AVX +#include <immintrin.h> +/*! +\brief Calculates tanh(x) using a series approximation, good to within 1e-6 of the actual tanh. +\param cVector The vector where the results will be stored +\param aVector Input vector +\param num_points The number of values to calulate +*/ +static inline void volk_32f_tanh_32f_u_avx(float* cVector, const float* aVector, + unsigned int num_points) +{ + unsigned int number = 0; + const unsigned int eighthPoints = num_points / 8; + + float* cPtr = cVector; + const float* aPtr = aVector; + + __m256 aVal, cVal, x2, a, b; + __m256 const1, const2, const3, const4, const5, const6; + const1 = _mm256_set1_ps(135135.0f); + const2 = _mm256_set1_ps(17325.0f); + const3 = _mm256_set1_ps(378.0f); + const4 = _mm256_set1_ps(62370.0f); + const5 = _mm256_set1_ps(3150.0f); + const6 = _mm256_set1_ps(28.0f); + for(;number < eighthPoints; number++){ + + aVal = _mm256_loadu_ps(aPtr); + x2 = _mm256_mul_ps(aVal, aVal); + a = _mm256_mul_ps(aVal, _mm256_add_ps(const1, _mm256_mul_ps(x2, _mm256_add_ps(const2, _mm256_mul_ps(x2, _mm256_add_ps(const3, x2)))))); + b = _mm256_add_ps(const1, _mm256_mul_ps(x2, _mm256_add_ps(const4, _mm256_mul_ps(x2, _mm256_add_ps(const5, _mm256_mul_ps(x2, const6)))))); + + cVal = _mm256_div_ps(a, b); + + _mm256_storeu_ps(cPtr, cVal); // Store the results back into the C container + + aPtr += 8; + cPtr += 8; + } + + number = eighthPoints * 8; + for(;number < num_points; number++) { + if(*aPtr > 4.97) + *cPtr++ = 1; + else if(*aPtr <= -4.97) + *cPtr++ = -1; + else { + float x2 = (*aPtr) * (*aPtr); + float a = (*aPtr) * (135135.0f + x2 * (17325.0f + x2 * (378.0f + x2))); + float b = 135135.0f + x2 * (62370.0f + x2 * (3150.0f + x2 * 28.0f)); + *cPtr++ = a / b; + aPtr++; + } + } +} +#endif /* LV_HAVE_AVX */ + +#endif /* INCLUDED_volk_32f_tanh_32f_a_H */ diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt index 6cc4504cfa..37915e5552 100644 --- a/volk/lib/CMakeLists.txt +++ b/volk/lib/CMakeLists.txt @@ -406,10 +406,8 @@ if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") # if we find one that matches our current system architecture # set up the assembler flags and include the source files foreach(ARCH ${ASM_ARCHS_AVAILABLE}) - message(STATUS "--==>> -CFLAGS1: ${FULL_C_FLAGS}") string(REGEX MATCH "${ARCH}" ASM_ARCH "${FULL_C_FLAGS}") if( ASM_ARCH STREQUAL "armv7" ) - set(ASM-ATT $ENV{ASM}) message(STATUS "---- Adding ASM files") # we always use ATT syntax message(STATUS "-- Detected armv7 architecture; enabling ASM") # setup architecture specific assembler flags @@ -422,13 +420,20 @@ if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") message(STATUS "Adding source file: ${asm_file}") endforeach(asm_file) endif() - set(CMAKE_ASM-ATT_FLAGS_INIT ${ARCH_ASM_FLAGS}) - enable_language(ASM-ATT) # this must be after flags_init - message(STATUS "asm flags: ${CMAKE_ASM-ATT_FLAGS}") + enable_language(ASM) + set(CMAKE_ASM_FLAGS ${ARCH_ASM_FLAGS}) + message(STATUS "c flags: ${FULL_C_FLAGS}") + message(STATUS "asm flags: ${CMAKE_ASM_FLAGS}") endforeach(ARCH) else(${CMAKE_VERSION} VERSION_GREATER "2.8.9") message(STATUS "Not enabling ASM support. CMake >= 2.8.10 required.") + foreach(machine_name ${available_machines}) + string(REGEX MATCH "neon" NEON_MACHINE ${machine_name}) + if( NEON_MACHINE STREQUAL "neon") + message(FATAL_ERROR "CMake >= 2.8.10 is required for ARM NEON support") + endif() + endforeach() endif(${CMAKE_VERSION} VERSION_GREATER "2.8.9") ######################################################################## diff --git a/volk/lib/qa_utils.cc b/volk/lib/qa_utils.cc index f30f0097ae..3ab4a9970c 100644 --- a/volk/lib/qa_utils.cc +++ b/volk/lib/qa_utils.cc @@ -5,7 +5,9 @@ #include <boost/tokenizer.hpp> #include <boost/xpressive/xpressive.hpp> #include <iostream> +#include <fstream> #include <vector> +#include <map> #include <list> #include <ctime> #include <cmath> @@ -328,9 +330,9 @@ bool run_volk_tests(volk_func_desc_t desc, lv_32fc_t scalar, int vlen, int iter, - std::vector<std::string> *best_arch_vector = 0, - std::string puppet_master_name = "NULL", - bool benchmark_mode, + std::vector<volk_test_results_t> *results, + std::string puppet_master_name, + bool benchmark_mode, std::string kernel_regex ) { boost::xpressive::sregex kernel_expression = boost::xpressive::sregex::compile(kernel_regex); @@ -338,6 +340,12 @@ bool run_volk_tests(volk_func_desc_t desc, // in this case we have a regex and are only looking to test one kernel return false; } + if(results) { + results->push_back(volk_test_results_t()); + results->back().name = name; + results->back().vlen = vlen; + results->back().iter = iter; + } std::cout << "RUN_VOLK_TESTS: " << name << "(" << vlen << "," << iter << ")" << std::endl; // The multiply and lv_force_cast_hf are work arounds for GNU Radio bugs 582 and 583 @@ -453,6 +461,13 @@ bool run_volk_tests(volk_func_desc_t desc, end = clock(); double arch_time = 1000.0 * (double)(end-start)/(double)CLOCKS_PER_SEC; std::cout << arch_list[i] << " completed in " << arch_time << "ms" << std::endl; + if(results) { + volk_test_time_t result; + result.name = arch_list[i]; + result.time = arch_time; + result.units = "ms"; + results->back().results[result.name] = result; + } profile_times.push_back(arch_time); } @@ -553,13 +568,14 @@ bool run_volk_tests(volk_func_desc_t desc, std::cout << "Best aligned arch: " << best_arch_a << std::endl; std::cout << "Best unaligned arch: " << best_arch_u << std::endl; - if(best_arch_vector) { + if(results) { if(puppet_master_name == "NULL") { - best_arch_vector->push_back(name + " " + best_arch_a + " " + best_arch_u); - } - else { - best_arch_vector->push_back(puppet_master_name + " " + best_arch_a + " " + best_arch_u); + results->back().config_name = name; + } else { + results->back().config_name = puppet_master_name; } + results->back().best_arch_a = best_arch_a; + results->back().best_arch_u = best_arch_u; } return fail_global; diff --git a/volk/lib/qa_utils.h b/volk/lib/qa_utils.h index fc1a0239eb..7ca8b8d1e8 100644 --- a/volk/lib/qa_utils.h +++ b/volk/lib/qa_utils.h @@ -3,7 +3,10 @@ #include <cstdlib> #include <string> +#include <iostream> +#include <fstream> #include <vector> +#include <map> #include <volk/volk.h> #include <volk/volk_common.h> @@ -21,10 +24,46 @@ volk_type_t volk_type_from_string(std::string); float uniform(void); void random_floats(float *buf, unsigned n); -bool run_volk_tests(volk_func_desc_t, void(*)(), std::string, float, lv_32fc_t, int, int, std::vector<std::string> *, std::string, bool benchmark_mode=false, std::string kernel_regex=""); +class volk_test_time_t { + public: + std::string name; + double time; + std::string units; +}; + +class volk_test_results_t { + public: + std::string name; + std::string config_name; + int vlen; + int iter; + std::map<std::string, volk_test_time_t> results; + std::string best_arch_a; + std::string best_arch_u; +}; + +bool run_volk_tests( + volk_func_desc_t, + void(*)(), + std::string, + float, + lv_32fc_t, + int, + int, + std::vector<volk_test_results_t> *results = NULL, + std::string puppet_master_name = "NULL", + bool benchmark_mode=false, + std::string kernel_regex="" + ); -#define VOLK_RUN_TESTS(func, tol, scalar, len, iter) BOOST_AUTO_TEST_CASE(func##_test) { BOOST_CHECK_EQUAL(run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, 0, "NULL"), 0); } +#define VOLK_RUN_TESTS(func, tol, scalar, len, iter) \ + BOOST_AUTO_TEST_CASE(func##_test) { \ + BOOST_CHECK_EQUAL(run_volk_tests( \ + func##_get_func_desc(), (void (*)())func##_manual, \ + std::string(#func), tol, scalar, len, iter, 0, "NULL"), \ + 0); \ + } #define VOLK_PROFILE(func, tol, scalar, len, iter, results, bnmode, kernel_regex) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, "NULL", bnmode, kernel_regex) #define VOLK_PUPPET_PROFILE(func, puppet_master_func, tol, scalar, len, iter, results, bnmode, kernel_regex) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, std::string(#puppet_master_func), bnmode, kernel_regex) typedef void (*volk_fn_1arg)(void *, unsigned int, const char*); //one input, operate in place diff --git a/volk/lib/testqa.cc b/volk/lib/testqa.cc index bc97ad16e5..9d837517f1 100644 --- a/volk/lib/testqa.cc +++ b/volk/lib/testqa.cc @@ -114,3 +114,4 @@ VOLK_RUN_TESTS(volk_8u_conv_k7_r2puppet_8u, 0, 0, 2060, 1); VOLK_RUN_TESTS(volk_32f_invsqrt_32f, 1e-2, 0, 20462, 1); VOLK_RUN_TESTS(volk_32f_binary_slicer_32i, 0, 0, 20462, 1); VOLK_RUN_TESTS(volk_32f_binary_slicer_8i, 0, 0, 20462, 1); +VOLK_RUN_TESTS(volk_32f_tanh_32f, 1e-6, 0, 20462, 1); |