diff options
author | Elof Wecksell <elof@wecksell.se> | 2021-01-12 10:35:31 +0100 |
---|---|---|
committer | Martin Braun <martin@gnuradio.org> | 2021-01-29 03:31:03 -0800 |
commit | b16924381c90e07d5d8cf5bc236c7dc48a0fd677 (patch) | |
tree | e5fe0c4005af6c6f0a6178139439a478de0abacf /gr-digital/include | |
parent | 761b327c761e0596f72cbe9f63e510f1b36c4b47 (diff) |
gr-digital: improved performance and capability of scramblers to 64-bit registers. Use __builtin_parity or volk popcnt. qa was also enhanced to detect errors.
Signed-off-by: Elof Wecksell <elof@wecksell.se>
Co-authored-by: Martin Braun <martin@gnuradio.org>
Diffstat (limited to 'gr-digital/include')
7 files changed, 66 insertions, 47 deletions
diff --git a/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h b/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h index 3e80606d6d..d7781bb2f4 100644 --- a/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h +++ b/gr-digital/include/gnuradio/digital/additive_scrambler_bb.h @@ -55,18 +55,18 @@ public: * \param reset_tag_key When a tag with this key is detected, the shift register is * reset (when this is set, count is ignored!) */ - static sptr make(int mask, - int seed, - int len, - int count = 0, - int bits_per_byte = 1, + static sptr make(uint64_t mask, + uint64_t seed, + uint8_t len, + int64_t count = 0, + uint8_t bits_per_byte = 1, const std::string& reset_tag_key = ""); - virtual int mask() const = 0; - virtual int seed() const = 0; - virtual int len() const = 0; - virtual int count() const = 0; - virtual int bits_per_byte() = 0; + virtual uint64_t mask() const = 0; + virtual uint64_t seed() const = 0; + virtual uint8_t len() const = 0; + virtual int64_t count() const = 0; + virtual uint8_t bits_per_byte() = 0; }; } /* namespace digital */ diff --git a/gr-digital/include/gnuradio/digital/descrambler_bb.h b/gr-digital/include/gnuradio/digital/descrambler_bb.h index 446754f58f..f361d92862 100644 --- a/gr-digital/include/gnuradio/digital/descrambler_bb.h +++ b/gr-digital/include/gnuradio/digital/descrambler_bb.h @@ -39,7 +39,7 @@ public: * \param seed Initial shift register contents * \param len Shift register length */ - static sptr make(int mask, int seed, int len); + static sptr make(uint64_t mask, uint64_t seed, uint8_t len); }; } /* namespace digital */ diff --git a/gr-digital/include/gnuradio/digital/glfsr.h b/gr-digital/include/gnuradio/digital/glfsr.h index 78646a59c3..53d6608647 100644 --- a/gr-digital/include/gnuradio/digital/glfsr.h +++ b/gr-digital/include/gnuradio/digital/glfsr.h @@ -23,26 +23,27 @@ namespace digital { * * \details * Generates a maximal length pseudo-random sequence of length 2^degree-1 + * if given a primitive polynomial. */ class DIGITAL_API glfsr { private: - uint32_t d_shift_register; - uint32_t d_mask; + uint64_t d_shift_register; + uint64_t d_mask; public: - glfsr(uint32_t mask, uint32_t seed) + glfsr(uint64_t mask, uint64_t seed) { d_shift_register = seed; d_mask = mask; } ~glfsr(); - static uint32_t glfsr_mask(unsigned int degree); + static uint64_t glfsr_mask(unsigned int degree); uint8_t next_bit(); - uint32_t mask() const { return d_mask; } + uint64_t mask() const { return d_mask; } }; } /* namespace digital */ diff --git a/gr-digital/include/gnuradio/digital/glfsr_source_b.h b/gr-digital/include/gnuradio/digital/glfsr_source_b.h index eb5b49e5db..c0059b7b24 100644 --- a/gr-digital/include/gnuradio/digital/glfsr_source_b.h +++ b/gr-digital/include/gnuradio/digital/glfsr_source_b.h @@ -40,11 +40,11 @@ public: */ static sptr make(unsigned int degree, bool repeat = true, - uint32_t mask = 0x0, - uint32_t seed = 0x1); + uint64_t mask = 0x0, + uint64_t seed = 0x1); - virtual uint32_t period() const = 0; - virtual uint32_t mask() const = 0; + virtual uint64_t period() const = 0; + virtual uint64_t mask() const = 0; }; } /* namespace digital */ diff --git a/gr-digital/include/gnuradio/digital/glfsr_source_f.h b/gr-digital/include/gnuradio/digital/glfsr_source_f.h index adc0a8d4f2..1a0dccc96b 100644 --- a/gr-digital/include/gnuradio/digital/glfsr_source_f.h +++ b/gr-digital/include/gnuradio/digital/glfsr_source_f.h @@ -30,7 +30,7 @@ public: /*! * Make a Galois LFSR pseudo-random source block. * - * \param degree Degree of shift register must be in [1, 32]. If mask + * \param degree Degree of shift register must be in [1, 64]. If mask * is 0, the degree determines a default mask (see * digital_impl_glfsr.cc for the mapping). * \param repeat Set to repeat sequence. @@ -39,10 +39,10 @@ public: * \param seed Initial setting for values in shift register. */ static sptr - make(unsigned int degree, bool repeat = true, uint32_t mask = 0, uint32_t seed = 1); + make(unsigned int degree, bool repeat = true, uint64_t mask = 0, uint64_t seed = 1); - virtual uint32_t period() const = 0; - virtual uint32_t mask() const = 0; + virtual uint64_t period() const = 0; + virtual uint64_t mask() const = 0; }; } /* namespace digital */ diff --git a/gr-digital/include/gnuradio/digital/lfsr.h b/gr-digital/include/gnuradio/digital/lfsr.h index b32eae8136..0d74195cb1 100644 --- a/gr-digital/include/gnuradio/digital/lfsr.h +++ b/gr-digital/include/gnuradio/digital/lfsr.h @@ -12,6 +12,10 @@ #define INCLUDED_DIGITAL_LFSR_H #include <gnuradio/digital/api.h> +#ifndef HAVE_BUILTIN_PARITYL +#include <volk/volk.h> +#endif +#include <stdint.h> #include <cstdint> #include <stdexcept> @@ -25,7 +29,7 @@ namespace digital { * * \details * Generates a maximal length pseudo-random sequence of length - * 2^degree-1 + * 2^degree-1, if supplied with a primitive polynomial. * * Constructor: digital::lfsr(int mask, int seed, int reg_len); * @@ -35,9 +39,9 @@ namespace digital { * order bit. * * Some common masks might be: - * x^4 + x^3 + x^0 = 0x19 - * x^5 + x^3 + x^0 = 0x29 - * x^6 + x^5 + x^0 = 0x61 + * x^4 + x^3 + x^0 = 0x19, K=3 + * x^5 + x^3 + x^0 = 0x29, K=4 + * x^6 + x^5 + x^0 = 0x61, K=5 * * \param seed - the initialization vector placed into the * register during initialization. Low order bit @@ -78,32 +82,33 @@ namespace digital { class lfsr { private: - uint32_t d_shift_register; - uint32_t d_mask; - uint32_t d_seed; - uint32_t d_shift_register_length; // less than 32 - - static uint32_t popCount(uint32_t x) - { - uint32_t r = x - ((x >> 1) & 033333333333) - ((x >> 2) & 011111111111); - return ((r + (r >> 3)) & 030707070707) % 63; - } + uint64_t d_shift_register; + uint64_t d_mask; + uint64_t d_seed; + uint8_t d_shift_register_length; // less than 64 public: - lfsr(uint32_t mask, uint32_t seed, uint32_t reg_len) + lfsr(uint64_t mask, uint64_t seed, uint8_t reg_len) : d_shift_register(seed), d_mask(mask), d_seed(seed), d_shift_register_length(reg_len) { - if (reg_len > 31) - throw std::invalid_argument("reg_len must be <= 31"); + if (reg_len > 63) + throw std::invalid_argument("reg_len must be <= 63"); } unsigned char next_bit() { unsigned char output = d_shift_register & 1; - unsigned char newbit = popCount(d_shift_register & d_mask) % 2; + uint64_t newbit; +#ifdef HAVE_BUILTIN_PARITYL + newbit = __builtin_parityl(d_shift_register & d_mask); +#else + volk_64u_popcnt(&newbit, d_shift_register & d_mask); + newbit %= 2; +#endif + d_shift_register = ((d_shift_register >> 1) | (newbit << d_shift_register_length)); return output; @@ -112,7 +117,13 @@ public: unsigned char next_bit_scramble(unsigned char input) { unsigned char output = d_shift_register & 1; - unsigned char newbit = (popCount(d_shift_register & d_mask) % 2) ^ (input & 1); + uint64_t newbit; +#ifdef HAVE_BUILTIN_PARITYL + newbit = __builtin_parityl(d_shift_register & d_mask) ^ (input & 1); +#else + volk_64u_popcnt(&newbit, d_shift_register & d_mask); + newbit = (newbit ^ input) & 1; +#endif d_shift_register = ((d_shift_register >> 1) | (newbit << d_shift_register_length)); return output; @@ -120,8 +131,15 @@ public: unsigned char next_bit_descramble(unsigned char input) { - unsigned char output = (popCount(d_shift_register & d_mask) % 2) ^ (input & 1); - unsigned char newbit = input & 1; + unsigned char output; +#ifdef HAVE_BUILTIN_PARITYL + output = __builtin_parityl(d_shift_register & d_mask) ^ (input & 1); +#else + uint64_t _tmp; + volk_64u_popcnt(&_tmp, d_shift_register & d_mask); + output = (_tmp ^ input) & 1; +#endif + uint64_t newbit = input & 1; d_shift_register = ((d_shift_register >> 1) | (newbit << d_shift_register_length)); return output; @@ -143,7 +161,7 @@ public: } } - int mask() const { return d_mask; } + uint64_t mask() const { return d_mask; } }; } /* namespace digital */ diff --git a/gr-digital/include/gnuradio/digital/scrambler_bb.h b/gr-digital/include/gnuradio/digital/scrambler_bb.h index 51f43b3bc8..8380856daa 100644 --- a/gr-digital/include/gnuradio/digital/scrambler_bb.h +++ b/gr-digital/include/gnuradio/digital/scrambler_bb.h @@ -39,7 +39,7 @@ public: * \param seed Initial shift register contents * \param len Shift register length */ - static sptr make(int mask, int seed, int len); + static sptr make(uint64_t mask, uint64_t seed, uint8_t len); }; } /* namespace digital */ |