From c6c590a3d9400b81fde85af2ee178d5033868f15 Mon Sep 17 00:00:00 2001 From: Christoph Mayer Date: Mon, 9 Sep 2019 16:04:06 +0200 Subject: [PATCH] custom allocator (VOLK) / filter update generalization --- lib/adaptive_dfe_impl.cc | 70 +++++++++++++++++++------------------- lib/adaptive_dfe_impl.h | 27 ++++++++------- lib/filter_update.hpp | 29 ++++++++++++++++ lib/lms.cc | 45 +++++++++++++++++++++++++ lib/lms.hpp | 35 +++++++++++++++++++ lib/rls.cc | 72 ++++++++++++++++++++++++++++++++++++++++ lib/rls.hpp | 37 +++++++++++++++++++++ lib/volk_allocator.hpp | 43 ++++++++++++++++++++++++ 8 files changed, 311 insertions(+), 47 deletions(-) create mode 100644 lib/filter_update.hpp create mode 100644 lib/lms.cc create mode 100644 lib/lms.hpp create mode 100644 lib/rls.cc create mode 100644 lib/rls.hpp create mode 100644 lib/volk_allocator.hpp diff --git a/lib/adaptive_dfe_impl.cc b/lib/adaptive_dfe_impl.cc index 1035e46..fdacacd 100644 --- a/lib/adaptive_dfe_impl.cc +++ b/lib/adaptive_dfe_impl.cc @@ -33,9 +33,8 @@ #include "adaptive_dfe_impl.h" -#define VOLK_SAFE_DELETE(x) \ - volk_free(x); \ - x = nullptr +#include "lms.hpp" +#include "rls.hpp" namespace gr { namespace digitalhf { @@ -71,9 +70,9 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol , _mu(mu) , _alpha(alpha) , _use_symbol_taps(true) - , _taps_samples(nullptr) - , _taps_symbols(nullptr) - , _hist_symbols(nullptr) + , _taps_samples() + , _taps_symbols() + , _hist_symbols() , _hist_symbol_index(0) , _constellations() , _npwr() @@ -89,11 +88,12 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol , _msg_ports{{"soft_dec", pmt::intern("soft_dec")}, {"frame_info", pmt::intern("frame_info")}} , _msg_metadata(pmt::make_dict()) - , _state(WAIT_FOR_PREAMBLE) , _num_samples_since_filter_update(0) , _rotated_samples() , _rotator() , _control_loop(2*M_PI/100, 5e-2, -5e-2) + , _state(WAIT_FOR_PREAMBLE) + , _filter_update() { GR_LOG_DECLARE_LOGPTR(d_logger); GR_LOG_ASSIGN_LOGPTR(d_logger, "adaptive_dfe"); @@ -115,9 +115,6 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol adaptive_dfe_impl::~adaptive_dfe_impl() { _msg_metadata = pmt::PMT_NIL; - VOLK_SAFE_DELETE(_taps_samples); - VOLK_SAFE_DELETE(_taps_symbols); - VOLK_SAFE_DELETE(_hist_symbols); } void @@ -162,6 +159,7 @@ adaptive_dfe_impl::general_work(int noutput_items, _state = WAIT_FOR_FRAME_INFO; GR_LOG_DEBUG(d_logger, "got preamble tag > wait for frame info"); } + _filter_update->reset(); break; } // WAIT_FOR_PREAMBLE case WAIT_FOR_FRAME_INFO: { @@ -208,7 +206,7 @@ adaptive_dfe_impl::general_work(int noutput_items, assert(i+_nF < nin && i-1-_nB >= 0); out_symb[nout] = filter(&_rotated_samples.front() + i - _nB, &_rotated_samples.front() + i + _nF+1); - std::memcpy(&out_taps[(_nB+_nF+1)*nout], _taps_samples, (_nB+_nF+1)*sizeof(gr_complex)); + std::memcpy(&out_taps[(_nB+_nF+1)*nout], &_taps_samples.front(), (_nB+_nF+1)*sizeof(gr_complex)); ++nout; } // next sample consume(0, ninput_processed); @@ -221,23 +219,23 @@ adaptive_dfe_impl::general_work(int noutput_items, bool adaptive_dfe_impl::start() { gr::thread::scoped_lock lock(d_setlock); - _taps_samples = (gr_complex*)(volk_malloc((_nB+_nF+1)*sizeof(gr_complex), volk_get_alignment())); - _last_taps_samples = (gr_complex*)(volk_malloc((_nB+_nF+1)*sizeof(gr_complex), volk_get_alignment())); - _taps_symbols = (gr_complex*)(volk_malloc( _nW*sizeof(gr_complex), volk_get_alignment())); - _hist_symbols = (gr_complex*)(volk_malloc( 2*_nW*sizeof(gr_complex), volk_get_alignment())); + _taps_samples.resize(_nB+_nF+1); + _last_taps_samples.resize(_nB+_nF+1); + _taps_symbols.resize(_nW); + _hist_symbols.resize(2*_nW); reset_filter(); GR_LOG_DEBUG(d_logger,str(boost::format("adaptive_dfe_impl::start() nB=%d nF=%d mu=%f alpha=%f") % _nB % _nF % _mu % _alpha)); + + //_filter_update = lms::make(_mu); + _filter_update = rls::make(0.001, 0.9999); return true; } bool adaptive_dfe_impl::stop() { gr::thread::scoped_lock lock(d_setlock); GR_LOG_DEBUG(d_logger, "adaptive_dfe_impl::stop()"); - VOLK_SAFE_DELETE(_taps_samples); - VOLK_SAFE_DELETE(_last_taps_samples); - VOLK_SAFE_DELETE(_taps_symbols); - VOLK_SAFE_DELETE(_hist_symbols); + _filter_update.reset(); return true; } @@ -249,7 +247,7 @@ gr_complex adaptive_dfe_impl::filter(gr_complex const* start, gr_complex const* // (1a) taps_samples volk_32fc_x2_dot_prod_32fc(&filter_output, start, - _taps_samples, + &_taps_samples.front(), _nB+_nF+1); // (1b) taps_symbols gr_complex dot_symbols(0); @@ -287,13 +285,15 @@ gr_complex adaptive_dfe_impl::filter(gr_complex const* start, gr_complex const* _num_samples_since_filter_update += _sps; // (3a) update of adaptive filter taps - gr_complex const err = filter_output - known_symbol; + gr_complex const err = known_symbol - filter_output; if (std::abs(err)>0.7) std::cout << "err= " << std::abs(err) << std::endl; // taps_samples + gr_complex const* gain = _filter_update->update(start, end); for (int j=0; j<_nB+_nF+1; ++j) { _last_taps_samples[j] = _taps_samples[j]; - _taps_samples[j] -= _mu*err*std::conj(start[j]); + _taps_samples[j] += _mu*std::conj(start[j]) * err; +// _taps_samples[j] += gain[j] * err; } // taps_symbols if (_use_symbol_taps) { @@ -335,8 +335,8 @@ gr_complex adaptive_dfe_impl::filter(gr_complex const* start, gr_complex const* int adaptive_dfe_impl::recenter_filter_taps() { #if 0 - ssize_t const _idx_max = std::distance(_taps_samples, - std::max_element(_taps_samples+_nB+1-3*_sps, _taps_samples+_nB+1+3*_sps, + ssize_t const _idx_max = std::distance(_taps_samples.begin(), + std::max_element(_taps_samples.begin()+_nB+1-3*_sps, _taps_samples.begin()+_nB+1+3*_sps, [](gr_complex a, gr_complex b) { return std::norm(a) < std::norm(b); })); @@ -354,17 +354,17 @@ adaptive_dfe_impl::recenter_filter_taps() { // maximum is right of the center tap // -> shift taps to the left left GR_LOG_DEBUG(d_logger, "shift left"); - std::copy(_taps_samples+4*_sps, _taps_samples+_nB+_nF+1, _taps_samples); - std::fill_n(_taps_samples+_nB+_nF+1-4*_sps, 4*_sps, gr_complex(0)); + std::copy(_taps_samples.begin()+4*_sps, _taps_samples.begin()+_nB+_nF+1, _taps_samples.begin()); + std::fill_n(_taps_samples.begin()+_nB+_nF+1-4*_sps, 4*_sps, gr_complex(0)); return +4*_sps; } if (idx_max-_nB-1 < -2*_sps) { // maximum is left of the center tap // -> shift taps to the right GR_LOG_DEBUG(d_logger, "shift right"); - std::copy_backward(_taps_samples, _taps_samples+_nB+_nF+1-4*_sps, - _taps_samples+_nB+_nF+1); - std::fill_n(_taps_samples, 4*_sps, gr_complex(0)); + std::copy_backward(_taps_samples.begin(), _taps_samples.begin()+_nB+_nF+1-4*_sps, + _taps_samples.begin()+_nB+_nF+1); + std::fill_n(_taps_samples.begin(), 4*_sps, gr_complex(0)); return -4*_sps; } return 0; @@ -372,10 +372,10 @@ adaptive_dfe_impl::recenter_filter_taps() { void adaptive_dfe_impl::reset_filter() { - std::fill_n(_taps_samples, _nB+_nF+1, gr_complex(0)); - std::fill_n(_last_taps_samples, _nB+_nF+1, gr_complex(0)); - std::fill_n(_taps_symbols, _nW, gr_complex(0)); - std::fill_n(_hist_symbols, 2*_nW, gr_complex(0)); + std::fill(_taps_samples.begin(), _taps_samples.end(), gr_complex(0)); + std::fill(_last_taps_samples.begin(), _last_taps_samples.end(), gr_complex(0)); + std::fill(_taps_symbols.begin(), _taps_symbols.end(), gr_complex(0)); + std::fill(_hist_symbols.begin(), _hist_symbols.end(), gr_complex(0)); _taps_symbols[0] = 1; _hist_symbol_index = 0; _num_samples_since_filter_update = 0; @@ -387,11 +387,11 @@ void adaptive_dfe_impl::publish_frame_info() GR_LOG_DEBUG(d_logger, str(boost::format("publish_frame_info %d == %d") % _descrambled_symbols.size() % _symbols.size())); data = pmt::dict_add(data, pmt::intern("symbols"), - pmt::init_c32vector(_descrambled_symbols.size(), &_descrambled_symbols.front())); + pmt::init_c32vector(_descrambled_symbols.size(), _descrambled_symbols)); // for (int i=0; i<_vec_soft_decisions.size(); ++i) // _vec_soft_decisions[i] = std::max(-1.0f, std::min(1.0f, _vec_soft_decisions[i])); data = pmt::dict_add(data, - pmt::intern("soft_dec"), pmt::init_f32vector(_vec_soft_decisions.size(), &_vec_soft_decisions.front())); + pmt::intern("soft_dec"), pmt::init_f32vector(_vec_soft_decisions.size(), _vec_soft_decisions)); message_port_pub(_msg_ports["frame_info"], data); _descrambled_symbols.clear(); } diff --git a/lib/adaptive_dfe_impl.h b/lib/adaptive_dfe_impl.h index bb9564f..d5f6a93 100644 --- a/lib/adaptive_dfe_impl.h +++ b/lib/adaptive_dfe_impl.h @@ -26,6 +26,9 @@ #include #include +#include "filter_update.hpp" +#include "volk_allocator.hpp" + namespace gr { namespace digitalhf { @@ -56,6 +59,9 @@ private: class adaptive_dfe_impl : public adaptive_dfe { private: + typedef std::vector > gr_complex_vec_type; +// typedef std::vector gr_complex_vec_type; + int _sps; int _nB, _nF, _nW; int _nGuard; @@ -65,25 +71,21 @@ private: bool _use_symbol_taps; - // module name w.r.t. digitalhf.physical_layer containing a PhysicalLayer class - // std::string _py_module_name; - // boost::python::object _physicalLayer; // class instance of physical layer description + gr_complex_vec_type _taps_samples; + gr_complex_vec_type _taps_symbols; + gr_complex_vec_type _last_taps_samples; - gr_complex* _taps_samples; - gr_complex* _taps_symbols; - gr_complex* _last_taps_samples; - - gr_complex* _hist_symbols; + gr_complex_vec_type _hist_symbols; int _hist_symbol_index; std::vector _constellations; std::vector _npwr; int _npwr_max_time_constant; int _constellation_index; - std::vector _symbols; - std::vector _scramble; // PSK-8 scramble symbols + std::vector _symbols; + std::vector _scramble; // PSK-8 scramble symbols std::vector > _scramble_xor; // signs for XOR scrambling - std::vector _descrambled_symbols; + std::vector _descrambled_symbols; int _symbol_counter; bool _save_soft_decisions; @@ -92,7 +94,7 @@ private: pmt::pmt_t _msg_metadata; int _num_samples_since_filter_update; - std::vector _rotated_samples; + gr_complex_vec_type _rotated_samples; blocks::rotator _rotator; gr::blocks::control_loop _control_loop; @@ -102,6 +104,7 @@ private: DO_FILTER } _state; + filter_update::sptr _filter_update; // void update_constellations(boost::python::object obj); void update_constellations(pmt::pmt_t ); void update_frame_info(pmt::pmt_t ); diff --git a/lib/filter_update.hpp b/lib/filter_update.hpp new file mode 100644 index 0000000..8471dc3 --- /dev/null +++ b/lib/filter_update.hpp @@ -0,0 +1,29 @@ +// -*- C++ -*- + +#ifndef _LIB_FILTER_UPDATE_HPP_ +#define _LIB_FILTER_UPDATE_HPP_ + +#include +#include + +#include +#include + +namespace gr { +namespace digitalhf { + +class filter_update : private boost::noncopyable { +public: + typedef std::unique_ptr sptr; + + virtual void reset() = 0; + virtual gr_complex const* update(gr_complex const*, gr_complex const*) = 0; + +protected: +private: +} ; + + +} // namespace digitalhf +} // namespace gr +#endif // _LIB_FILTER_UPDATE_HPP_ diff --git a/lib/lms.cc b/lib/lms.cc new file mode 100644 index 0000000..4111740 --- /dev/null +++ b/lib/lms.cc @@ -0,0 +1,45 @@ +// -*- C++ -*- + +#include +#include "lms.hpp" +#include + +namespace gr { +namespace digitalhf { + +filter_update::sptr lms::make(float mu) { + return filter_update::sptr(new lms(mu)); +} + +lms::lms(float mu) + : _mu(mu) + , _gain() { +} + +lms::~lms() { +} + +void lms::resize(size_t n) { + if (_gain.size() == n) + return; + _gain.resize(n); + std::fill_n(_gain.begin(), n, 0); +} + +void lms::reset() { + std::fill_n(_gain.begin(), _gain.size(), 0); +} + +gr_complex const* lms::update(gr_complex const* beg, + gr_complex const* end) { + assert(end-beg > 0); + size_t n = end - beg; + resize(n); + for (size_t i=0; i + +#include "filter_update.hpp" +#include "volk_allocator.hpp" + + +namespace gr { +namespace digitalhf { + +class lms : public filter_update { +public: + lms(float mu); + virtual ~lms(); + + static sptr make(float mu); + + virtual void reset(); + virtual gr_complex const* update(gr_complex const*, gr_complex const*); + +protected: + void resize(size_t); + +private: + float _mu; + std::vector > _gain; +} ; + +} // namespace digitalhf +} // namespace gr +#endif // _LIB_LMS_HPP_ diff --git a/lib/rls.cc b/lib/rls.cc new file mode 100644 index 0000000..9c6ebaf --- /dev/null +++ b/lib/rls.cc @@ -0,0 +1,72 @@ +// -*- C++ -*- + +#include +#include "rls.hpp" +#include + +namespace gr { +namespace digitalhf { + +filter_update::sptr rls::make(float delta, float lambda) { + return filter_update::sptr(new rls(delta, lambda)); +} + +rls::rls(float delta, float lambda) + : _delta(delta) + , _lambda(lambda) + , _gain() + , _inv_corr() { +} + +rls::~rls() { +} + +void rls::resize(size_t n) { + if (_gain.size() == n && _inv_corr.size() == n*n) + return; + _gain.resize(n); + _inv_corr.resize(n*n); + reset(); +} + +void rls::reset() { + size_t const n = _gain.size(); + std::fill_n(_gain.begin(), n, 0); + std::fill_n(_inv_corr.begin(), n*n, 0); + for (size_t i=0; i 0); + unsigned const n = end - beg; + resize(n); + + std::vector > pu(n), tmp(n); + //pu.resize(n); + + for (unsigned i=0; i + +#include "filter_update.hpp" +#include "volk_allocator.hpp" + + +namespace gr { +namespace digitalhf { + +class rls : public filter_update { +public: + rls(float delta, float lambda); + virtual ~rls(); + + static sptr make(float delta, float lambda); + + virtual void reset(); + virtual gr_complex const* update(gr_complex const*, gr_complex const*); + +protected: + void resize(size_t); + +private: + float _delta; + float _lambda; + std::vector > _gain; + std::vector > _inv_corr; +} ; + +} // namespace digitalhf +} // namespace gr +#endif // _LIB_RLS_HPP_ diff --git a/lib/volk_allocator.hpp b/lib/volk_allocator.hpp new file mode 100644 index 0000000..d4c926e --- /dev/null +++ b/lib/volk_allocator.hpp @@ -0,0 +1,43 @@ +// -*- c++ -*- + +#ifndef _LIB_VOLK_ALLOCATOR_HPP_ +#define _LIB_VOLK_ALLOCATOR_HPP_ + +#include +#include +#include + +namespace gr { +namespace digitalhf { + +// see https://en.cppreference.com/w/cpp/named_req/Allocator +template +struct volk_allocator { + typedef T value_type; + + volk_allocator() = default; + + template constexpr volk_allocator(const volk_allocator&) noexcept {} + + T* allocate(std::size_t n) { + if (n > std::numeric_limits::max() / sizeof(T)) throw std::bad_alloc(); + + if (auto p = static_cast(volk_malloc(n*sizeof(T), volk_get_alignment()))) + return p; + + throw std::bad_alloc(); + } + + void deallocate(T* p, std::size_t) noexcept { volk_free(p); } + +} ; + +template +bool operator==(const volk_allocator&, const volk_allocator&) { return true; } + +template +bool operator!=(const volk_allocator&, const volk_allocator&) { return false; } + +} // namespace digitalhf +} // namespace gr +#endif // _LIB_VOLK_ALLOCATOR_HPP_