diff options
35 files changed, 1520 insertions, 317 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/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/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..981ee6cf9d --- /dev/null +++ b/gr-blocks/examples/vector_source_with_tags.grc @@ -0,0 +1,614 @@ +<?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>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>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>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_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]</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>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>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>(440, 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> +</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/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-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 20f6fd6237..3301ca1815 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/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..386237bf65 100644 --- a/volk/lib/CMakeLists.txt +++ b/volk/lib/CMakeLists.txt @@ -409,7 +409,6 @@ if(${CMAKE_VERSION} VERSION_GREATER "2.8.9") 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 +421,19 @@ 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}") + set(CMAKE_ASM_FLAGS ${ARCH_ASM_FLAGS}) + enable_language(ASM) # this must be after flags_init + 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); |