summaryrefslogtreecommitdiff
path: root/gr-digital/include
diff options
context:
space:
mode:
authorElof Wecksell <elof@wecksell.se>2021-01-12 10:35:31 +0100
committerMartin Braun <martin@gnuradio.org>2021-01-29 03:31:03 -0800
commitb16924381c90e07d5d8cf5bc236c7dc48a0fd677 (patch)
treee5fe0c4005af6c6f0a6178139439a478de0abacf /gr-digital/include
parent761b327c761e0596f72cbe9f63e510f1b36c4b47 (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')
-rw-r--r--gr-digital/include/gnuradio/digital/additive_scrambler_bb.h20
-rw-r--r--gr-digital/include/gnuradio/digital/descrambler_bb.h2
-rw-r--r--gr-digital/include/gnuradio/digital/glfsr.h11
-rw-r--r--gr-digital/include/gnuradio/digital/glfsr_source_b.h8
-rw-r--r--gr-digital/include/gnuradio/digital/glfsr_source_f.h8
-rw-r--r--gr-digital/include/gnuradio/digital/lfsr.h62
-rw-r--r--gr-digital/include/gnuradio/digital/scrambler_bb.h2
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 */