Compare commits

...

8 Commits

Author SHA1 Message Date
Alexander V Joura 42ab9401d6
Merge 7333f0ce73 into 4910629a5d 2024-04-24 22:58:29 +03:00
Carles Fernandez 4910629a5d
CI: update actions/setup-python to v5 in volk-gnsssdr-windows job 2024-04-22 13:36:14 +02:00
Carles Fernandez 1ad631128f
cpu_features: Update AArch64 features to Linux 6.6 2024-04-22 13:03:31 +02:00
Carles Fernandez 78295866e6
Find dependencies in the loongarch64 architecture 2024-04-22 12:41:11 +02:00
Carles Fernandez 95e9c13cd5
Find dependencies in the loongarch64 architecture 2024-04-22 12:22:43 +02:00
Carles Fernandez c91c31bd35
Fix wrong order of arguments in calloc 2024-04-22 09:48:28 +02:00
Carles Fernandez c6010d943e
CMake fixes for old distros 2024-04-18 08:31:21 +02:00
Alexander V. Joura 7333f0ce73
- Added Hamming code correction method
- Added google tests for this method
2022-09-12 12:58:59 +03:00
20 changed files with 206 additions and 7 deletions

View File

@ -204,7 +204,7 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies

View File

@ -2542,7 +2542,11 @@ endif()
if(((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.0.0")) OR
((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0")) OR
((CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "11")))
find_package(Protobuf 21.12 EXACT)
if(CMAKE_VERSION VERSION_LESS 3.19)
find_package(Protobuf)
else()
find_package(Protobuf 3.0...21.12)
endif()
else()
find_package(Protobuf)
endif()
@ -2631,7 +2635,7 @@ if(Protobuf_FOUND AND CMAKE_CROSSCOMPILING)
endif()
endif()
if((NOT Protobuf_FOUND) OR (NOT Protobuf_PROTOC_EXECUTABLE) OR (${Protobuf_VERSION} VERSION_LESS ${GNSSSDR_PROTOBUF_MIN_VERSION}) OR ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.0.0")))
if((NOT Protobuf_FOUND) OR (NOT Protobuf_PROTOC_EXECUTABLE) OR (${Protobuf_VERSION} VERSION_LESS ${GNSSSDR_PROTOBUF_MIN_VERSION}))
unset(Protobuf_PROTOC_EXECUTABLE)
if(CMAKE_CROSSCOMPILING)
if(NOT Protobuf_FOUND)

View File

@ -108,6 +108,7 @@ find_library(MATIO_LIBRARY
/usr/lib/x86_64-linux-gnux32
/usr/lib/x86_64-kfreebsd-gnu
/usr/lib/i386-kfreebsd-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib

View File

@ -80,6 +80,8 @@ find_path(ORC_LIBRARY_DIR
/usr/lib/powerpc64le-linux-gnu
/usr/lib/hppa-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib
@ -106,6 +108,8 @@ find_library(ORC_LIB orc-0.4
/usr/lib/powerpc64le-linux-gnu
/usr/lib/hppa-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib
@ -134,6 +138,8 @@ find_library(ORC_LIBRARY_STATIC ${CMAKE_STATIC_LIBRARY_PREFIX}orc-0.4${CMAKE_STA
/usr/lib/powerpc64le-linux-gnu
/usr/lib/hppa-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib

View File

@ -105,6 +105,7 @@ else()
/usr/lib/powerpc64-linux-gnu
/usr/lib/powerpc64le-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/sh4-linux-gnu
/usr/lib/sparc64-linux-gnu

View File

@ -88,6 +88,7 @@ find_library(PUGIXML_LIBRARY
/usr/lib/sparc64-linux-gnu
/usr/lib/x86_64-linux-gnux32
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/lib/x86_64-kfreebsd-gnu
/usr/lib/i386-kfreebsd-gnu
/usr/local/lib

View File

@ -86,6 +86,7 @@ find_library(UHD_LIBRARIES
/usr/lib/x86_64-linux-gnux32
/usr/lib/alpha-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib

View File

@ -83,6 +83,7 @@ find_library(VOLK_LIBRARIES
/usr/lib/x86_64-linux-gnux32
/usr/lib/alpha-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib

View File

@ -46,6 +46,7 @@ find_library(ZEROMQ_LIBRARIES
/usr/lib/powerpc64-linux-gnu
/usr/lib/powerpc64le-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/sh4-linux-gnu
/usr/lib/sparc64-linux-gnu

View File

@ -1034,7 +1034,7 @@ double *zeros(int n, int m)
{
return nullptr;
}
if (!(p = static_cast<double *>(calloc(sizeof(double), n * m))))
if (!(p = static_cast<double *>(calloc(n * m, sizeof(double)))))
{
fatalerr("matrix memory allocation error: n=%d,m=%d\n", n, m);
}

View File

@ -34,6 +34,7 @@ find_library(CPUFEATURES_LIBRARIES
/usr/lib/x86_64-linux-gnux32
/usr/lib/alpha-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib

View File

@ -71,6 +71,8 @@ find_path(ORC_LIBRARY_DIR
/usr/lib/powerpc64le-linux-gnu
/usr/lib/hppa-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib
@ -97,6 +99,8 @@ find_library(ORC_LIB orc-0.4
/usr/lib/powerpc64le-linux-gnu
/usr/lib/hppa-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib
@ -125,6 +129,8 @@ find_library(ORC_LIBRARY_STATIC ${CMAKE_STATIC_LIBRARY_PREFIX}orc-0.4${CMAKE_STA
/usr/lib/powerpc64le-linux-gnu
/usr/lib/hppa-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/loongarch64-linux-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib

View File

@ -180,6 +180,8 @@ typedef struct
int smebi32i32 : 1; // 1-bit binary to 32-bit integer outer product.
int smeb16b16 : 1; // SME2.1 BFloat16 instructions.
int smef16f16 : 1; // FP16 to FP16 outer product.
int mops : 1; // Standardized memory operations.
int hbc : 1; // Hinted conditional branches.
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
} Aarch64Features;
@ -276,6 +278,8 @@ typedef enum
AARCH64_SME_BI32I32,
AARCH64_SME_B16B16,
AARCH64_SME_F16F16,
AARCH64_MOPS,
AARCH64_HBC,
AARCH64_LAST_,
} Aarch64FeaturesEnum;

View File

@ -92,6 +92,8 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define AARCH64_HWCAP2_SME_BI32I32 (1UL << 40)
#define AARCH64_HWCAP2_SME_B16B16 (1UL << 41)
#define AARCH64_HWCAP2_SME_F16F16 (1UL << 42)
#define AARCH64_HWCAP2_MOPS (1UL << 43)
#define AARCH64_HWCAP2_HBC (1UL << 44)
// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
#define ARM_HWCAP_SWP (1UL << 0)

View File

@ -100,7 +100,10 @@
AARCH64_HWCAP2_SME_BI32I32) \
LINE(AARCH64_SME_B16B16, smeb16b16, "smeb16b16", 0, \
AARCH64_HWCAP2_SME_B16B16) \
LINE(AARCH64_SME_F16F16, smef16f16, "smef16f16", 0, AARCH64_HWCAP2_SME_F16F16)
LINE(AARCH64_SME_F16F16, smef16f16, "smef16f16", 0, \
AARCH64_HWCAP2_SME_F16F16) \
LINE(AARCH64_MOPS, mops, "mops", 0, AARCH64_HWCAP2_MOPS) \
LINE(AARCH64_HBC, hbc, "hbc", 0, AARCH64_HWCAP2_HBC)
#define INTROSPECTION_PREFIX Aarch64
#define INTROSPECTION_ENUM_PREFIX AARCH64
#include "define_introspection_and_hwcaps.inl"

View File

@ -324,6 +324,8 @@ CPU revision : 3)");
EXPECT_FALSE(info.features.smebi32i32);
EXPECT_FALSE(info.features.smeb16b16);
EXPECT_FALSE(info.features.smef16f16);
EXPECT_FALSE(info.features.mops);
EXPECT_FALSE(info.features.hbc);
}
#elif defined(CPU_FEATURES_OS_MACOS)
TEST_F(CpuidAarch64Test, FromDarwinSysctlFromName)

View File

@ -240,6 +240,9 @@ const std::vector<int32_t> GLONASS_GNAV_CRC_P_INDEX{66, 67, 68, 69, 70, 71, 72,
const std::vector<int32_t> GLONASS_GNAV_CRC_Q_INDEX{9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85};
const std::vector<int32_t> GLONASS_GNAV_ECC_LOCATOR{0, 0, 1, 8, 2, 9, 10, 11, 3, 12, 13, 14, 15, 16, 17, 18, 4, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 5, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 6, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84};
const std::vector<std::vector<int32_t>> GLONASS_GNAV_HAMMING_INDEX{GLONASS_GNAV_CRC_I_INDEX, GLONASS_GNAV_CRC_J_INDEX, GLONASS_GNAV_CRC_K_INDEX, GLONASS_GNAV_CRC_L_INDEX,
GLONASS_GNAV_CRC_M_INDEX, GLONASS_GNAV_CRC_N_INDEX, GLONASS_GNAV_CRC_P_INDEX, GLONASS_GNAV_CRC_Q_INDEX};
// GLONASS GNAV NAVIGATION MESSAGE STRUCTURE
// NAVIGATION MESSAGE FIELDS POSITIONS

View File

@ -154,6 +154,95 @@ bool Glonass_Gnav_Navigation_Message::CRC_test(std::bitset<GLONASS_GNAV_STRING_B
}
bool Glonass_Gnav_Navigation_Message::hamming_correct(std::bitset<GLONASS_GNAV_STRING_BITS>& bits_io) const
{
std::vector<int> bits(GLONASS_GNAV_STRING_BITS);
// Populate data and Hamming code vectors
for (size_t i = 0; i < bits.size(); i++)
{
bits[i] = static_cast<int>(bits_io[i]);
}
std::vector<int> C(GLONASS_GNAV_HAMMING_CODE_BITS, 0);
int sum_bits;
for (size_t m = 0; m < GLONASS_GNAV_HAMMING_CODE_BITS; ++m)
{
sum_bits = 0;
for (int i : GLONASS_GNAV_HAMMING_INDEX[m])
sum_bits += bits[i - 1];
C[m] = bits[m] ^ (sum_bits % 2);
}
int sum_hamming = 0;
for (int i = 0; i < GLONASS_GNAV_HAMMING_CODE_BITS; ++i)
{
sum_hamming += bits[i];
}
C[GLONASS_GNAV_HAMMING_CODE_BITS - 1] = (sum_hamming % 2) ^ (sum_bits % 2);
int shortSumC = 0;
for (size_t m = 0; m < GLONASS_GNAV_HAMMING_CODE_BITS - 1; ++m)
{
shortSumC += C[m];
}
if (C[GLONASS_GNAV_HAMMING_CODE_BITS - 1] == 0)
{
if (shortSumC == 0)
{
// (A1) All checksums (C1, ..., C7 and C_Sigma) are equal to zero (all information
// bits and check bits are valid)
return true;
}
}
else
{
int highestNonZeroIdx = -1;
for (int i = 0; i < GLONASS_GNAV_HAMMING_CODE_BITS - 1; ++i) // C_Sigma should not be taken into account
{
if (C[i] != 0)
highestNonZeroIdx = i + 1; // 1-based indices
}
if (shortSumC == 1)
{
// (A2) Only one of the checksums (C1, ..., C7) is equal to 1 and C_Sigma = 1 (all
// information bits are valid and there is an error in one (!) of the check bits.
bits_io[highestNonZeroIdx - 1] = 1 - bits_io[highestNonZeroIdx - 1];
return true;
}
if (highestNonZeroIdx == -1)
{
// Error only in parity bit (C_Sigma = 1)
bits_io[GLONASS_GNAV_HAMMING_CODE_BITS - 1] = 1 - bits_io[GLONASS_GNAV_HAMMING_CODE_BITS - 1];
return true;
}
int idx = C[GLONASS_GNAV_HAMMING_CODE_BITS - 2];
for (int i = GLONASS_GNAV_HAMMING_CODE_BITS - 3; i >= 0; --i)
{
idx <<= 1;
idx += C[i];
}
int position = idx + GLONASS_GNAV_HAMMING_CODE_BITS - highestNonZeroIdx - 1;
if (position < GLONASS_GNAV_STRING_BITS)
{
// (B) Error only in a single information bit
bits_io[position] = 1 - bits_io[position];
return true;
}
}
// Irrecoverable error in information bits
return false;
}
bool Glonass_Gnav_Navigation_Message::read_navigation_bool(const std::bitset<GLONASS_GNAV_STRING_BITS>& bits, const std::vector<std::pair<int32_t, int32_t>>& parameter) const
{
bool value = bits[GLONASS_GNAV_STRING_BITS - parameter[0].first];
@ -235,8 +324,8 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame
// Unpack bytes to bits
std::bitset<GLONASS_GNAV_STRING_BITS> string_bits(frame_string);
// Perform data verification and exit code if error in bit sequence
flag_CRC_test = CRC_test(string_bits);
// Perform data correction and exit code if error in bit sequence is irrecoverable
flag_CRC_test = hamming_correct(string_bits);
if (flag_CRC_test == false)
{
return 0;

View File

@ -57,6 +57,12 @@ public:
*/
bool CRC_test(std::bitset<GLONASS_GNAV_STRING_BITS>& bits) const;
/*!
* \brief Check and (if needed and possible) correct information bits for GLONASS GNAV strings
* \param[in,out] bits_io Bits of the string message (information and Hamming codes)
*/
bool hamming_correct(std::bitset<GLONASS_GNAV_STRING_BITS>& bits_io) const;
/*!
* \brief Computes the frame number being decoded given the satellite slot number
* \param satellite_slot_number [in] Satellite slot number identifier

View File

@ -20,6 +20,9 @@
#include "glonass_gnav_navigation_message.h"
#include "gnss_signal_replica.h"
// A valid GLONASS GNAV message string
std::string valid_msg("0001110000000001001101001110100011111011010011001101001101110110010011110011100100011");
/*!
* \brief Testing CRC computation for GLONASS GNAV data bits of a string
* \test The provided string was generated with a version of MATLAB GNSS-SDR that
@ -60,6 +63,70 @@ TEST(GlonassGnavNavigationMessageTest, CRCTestFailure)
ASSERT_FALSE(test_result);
}
/*!
* \brief Testing Hamming code correction method for GLONASS GNAV data.
* \test A single-bit error is introduced into each bit of a valid string
* and the result of error correction is compared to the original string
*/
TEST(GlonassGnavNavigationMessageTest, hamming_correct_1bit)
{
bool test_result;
std::bitset<GLONASS_GNAV_STRING_BITS> bits(valid_msg);
const std::bitset<GLONASS_GNAV_STRING_BITS> bits_original = bits;
auto gnav_nav_message = Glonass_Gnav_Navigation_Message();
test_result = gnav_nav_message.hamming_correct(bits);
// check correct return value for a valid string
ASSERT_TRUE(test_result);
// check that a valid string is not being changed
ASSERT_EQ(bits, bits_original);
for (int i = 0; i < GLONASS_GNAV_STRING_BITS; ++i)
{
bits[i] = 1 - bits[i];
test_result = gnav_nav_message.hamming_correct(bits);
// check correct return value for a string with a single bit error
ASSERT_TRUE(test_result);
// check that a string is restored correctly
ASSERT_EQ(bits, bits_original);
}
}
/*!
* \brief Testing Hamming code correction method for GLONASS GNAV data.
* \test A two-bit error is introduced into each possible pair of bits of
* a valid string in order to check that the error correction method
* returns correction result as 'false'.
*/
TEST(GlonassGnavNavigationMessageTest, hamming_correct_2bits)
{
std::bitset<GLONASS_GNAV_STRING_BITS> bits(valid_msg);
auto gnav_nav_message = Glonass_Gnav_Navigation_Message();
for (int i = 0; i < GLONASS_GNAV_STRING_BITS - 1; ++i)
{
bits[i] = 1 - bits[i];
for (int j = i + 1; j < GLONASS_GNAV_STRING_BITS; ++j)
{
bits[j] = 1 - bits[j];
std::bitset<GLONASS_GNAV_STRING_BITS> bits_with_errors = bits;
bool test_result = gnav_nav_message.hamming_correct(bits);
// check correct return value for a string with 2 wrong bits
ASSERT_FALSE(test_result);
// check that a string with 2 wrong bits is not being changed
ASSERT_EQ(bits, bits_with_errors);
bits[j] = 1 - bits[j];
}
bits[i] = 1 - bits[i];
}
}
/*!
* \brief Testing string decoding for GLONASS GNAV messages