From 9c8dd1929d0a2e9ee49230923b5ebfa1d2ad9724 Mon Sep 17 00:00:00 2001 From: Jim Melton Date: Tue, 28 Feb 2023 14:13:31 -0700 Subject: [PATCH 1/7] REALLY suppress tags this time --- .../adapters/zmq_signal_source.cc | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/src/algorithms/signal_source/adapters/zmq_signal_source.cc b/src/algorithms/signal_source/adapters/zmq_signal_source.cc index 7a6370000..bc8616ccd 100644 --- a/src/algorithms/signal_source/adapters/zmq_signal_source.cc +++ b/src/algorithms/signal_source/adapters/zmq_signal_source.cc @@ -42,20 +42,24 @@ ZmqSignalSource::ZmqSignalSource(const ConfigurationInterface* configuration, if (!endpoint.empty()) { LOG(INFO) << "Connecting to ZMQ pub at " << endpoint; - // work around gnuradio interface deficiency + // work around gnuradio interface const-deficiency d_source_block = gr::zeromq::sub_source::make(d_item_size, vlen, const_cast(endpoint.data()), timeout_ms, pass_tags, hwm); - d_source_block->set_tag_propagation_policy(gr::block::TPP_DONT); // GNSS-SDR doesn't do well with tags/ + + // work around another bug. GNU Radio passes tags through the ZMQ block + // unconditionally if pass_tags is true, but that flag controls protocol more + // than the intent of the block. Since we have the vector-to-stream block, + // unconditionally create it, and have it squelch the tags. GNSS-SDR should + // not fail if unexpected tags are received + + // vector-to-stream should be coherent even if vlen == 1 + d_vec_block = gr::blocks::vector_to_stream::make(item_size(), vlen); + d_vec_block->set_tag_propagation_policy(gr::block::TPP_DONT); // GNSS-SDR doesn't do well with tags/ } else { std::cerr << "For ZMQ_Signal_Source " << property << " must be defined" << std::endl; throw std::invalid_argument(property + ": undefined"); } - - if (vlen > 1) - { - d_vec_block = gr::blocks::vector_to_stream::make(item_size(), vlen); - } } @@ -64,15 +68,13 @@ auto ZmqSignalSource::item_size() -> size_t { return d_item_size; } auto ZmqSignalSource::connect(gr::top_block_sptr top_block) -> void { - if (d_vec_block) - { - top_block->connect(d_source_block, 0, d_vec_block, 0); - } if (d_dump) { d_dump_sink = gr::blocks::file_sink::make(item_size(), d_dump_filename.data()); top_block->connect(get_right_block(), 0, d_dump_sink, 0); } + + top_block->connect(d_source_block, 0, d_vec_block, 0); } @@ -83,25 +85,13 @@ auto ZmqSignalSource::disconnect(gr::top_block_sptr top_block) -> void top_block->disconnect(d_dump_sink); } - if (d_vec_block) - { - top_block->disconnect(d_vec_block); - } + // this might be redundant + top_block->disconnect(d_vec_block); + top_block->disconnect(d_source_block); } auto ZmqSignalSource::get_right_block() -> gr::basic_block_sptr { - auto result = gr::basic_block_sptr(); - - if (d_vec_block) - { - result = d_vec_block; - } - else - { - result = d_source_block; - } - - return result; + return d_vec_block; } From 1b2087944ece1d3e0a0575105360825b7dcb81c7 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 17 Mar 2023 10:39:22 +0100 Subject: [PATCH 2/7] Add Geohash of PVT solution to internal logs --- docs/CHANGELOG.md | 2 + .../PVT/gnuradio_blocks/rtklib_pvt_gs.cc | 4 +- .../PVT/gnuradio_blocks/rtklib_pvt_gs.h | 2 + src/algorithms/PVT/libs/CMakeLists.txt | 2 + src/algorithms/PVT/libs/geohash.cc | 195 ++++++++++++++++++ src/algorithms/PVT/libs/geohash.h | 74 +++++++ src/tests/test_main.cc | 1 + .../pvt/geohash_test.cc | 38 ++++ .../pvt/nmea_printer_test.cc | 2 +- 9 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 src/algorithms/PVT/libs/geohash.cc create mode 100644 src/algorithms/PVT/libs/geohash.h create mode 100644 src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index fafe79b12..aff709642 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -111,6 +111,8 @@ All notable changes to GNSS-SDR will be documented in this file. - New configuration parameter `PVT.use_unhealthy_sats`, set by default to `false`, allows processing observables of satellites that report an unhealthy status in the navigation message if set to `true`. +- Added the [Geohash](https://en.wikipedia.org/wiki/Geohash) of the PVT solution + in the internal logs. - Allowed the CMake project to be a sub-project. See the definitions of concepts and metrics at diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc index 500db4d4c..9d2b843b3 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc @@ -28,6 +28,7 @@ #include "galileo_has_data.h" #include "galileo_iono.h" #include "galileo_utc_model.h" +#include "geohash.h" #include "geojson_printer.h" #include "glonass_gnav_almanac.h" #include "glonass_gnav_ephemeris.h" @@ -124,6 +125,7 @@ rtklib_pvt_gs::rtklib_pvt_gs(uint32_t nchannels, gr::io_signature::make(nchannels, nchannels, sizeof(Gnss_Synchro)), gr::io_signature::make(0, 0, 0)), d_dump_filename(conf_.dump_filename), + d_geohash(std::make_unique()), d_gps_ephemeris_sptr_type_hash_code(typeid(std::shared_ptr).hash_code()), d_gps_iono_sptr_type_hash_code(typeid(std::shared_ptr).hash_code()), d_gps_utc_model_sptr_type_hash_code(typeid(std::shared_ptr).hash_code()), @@ -2432,7 +2434,7 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item LOG(INFO) << "Position at " << boost::posix_time::to_simple_string(d_user_pvt_solver->get_position_UTC_time()) << " UTC using " << d_user_pvt_solver->get_num_valid_observations() << " observations is Lat = " << d_user_pvt_solver->get_latitude() << " [deg], Long = " << d_user_pvt_solver->get_longitude() << " [deg], Height = " << d_user_pvt_solver->get_height() << " [m]"; - + LOG(INFO) << "geohash: " << d_geohash->encode(d_user_pvt_solver->get_latitude(), d_user_pvt_solver->get_longitude()); /* std::cout << "Dilution of Precision at " << boost::posix_time::to_simple_string(d_user_pvt_solver->get_position_UTC_time()) << " UTC using "<< d_user_pvt_solver->get_num_valid_observations() <<" observations is HDOP = " << d_user_pvt_solver->get_hdop() << " VDOP = " << d_user_pvt_solver->get_vdop() diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.h b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.h index 94ffb458a..747c31c65 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.h +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.h @@ -50,6 +50,7 @@ class Beidou_Dnav_Ephemeris; class Galileo_Almanac; class Galileo_Ephemeris; class Galileo_HAS_data; +class Geohash; class GeoJSON_Printer; class Gps_Almanac; class Gps_Ephemeris; @@ -204,6 +205,7 @@ private: std::queue d_TimeChannelTagTimestamps; boost::posix_time::time_duration d_utc_diff_time; + std::unique_ptr d_geohash; size_t d_gps_ephemeris_sptr_type_hash_code; size_t d_gps_iono_sptr_type_hash_code; diff --git a/src/algorithms/PVT/libs/CMakeLists.txt b/src/algorithms/PVT/libs/CMakeLists.txt index 8e2785144..2460a3d4b 100644 --- a/src/algorithms/PVT/libs/CMakeLists.txt +++ b/src/algorithms/PVT/libs/CMakeLists.txt @@ -22,6 +22,7 @@ set(PVT_LIB_SOURCES monitor_pvt_udp_sink.cc monitor_ephemeris_udp_sink.cc has_simple_printer.cc + geohash.cc ) set(PVT_LIB_HEADERS @@ -43,6 +44,7 @@ set(PVT_LIB_HEADERS serdes_gps_eph.h monitor_ephemeris_udp_sink.h has_simple_printer.h + geohash.h ) list(SORT PVT_LIB_HEADERS) diff --git a/src/algorithms/PVT/libs/geohash.cc b/src/algorithms/PVT/libs/geohash.cc new file mode 100644 index 000000000..3682a7e0e --- /dev/null +++ b/src/algorithms/PVT/libs/geohash.cc @@ -0,0 +1,195 @@ +/*! + * \file geohash.cc + * \brief Implementation of a class for geohash encoding / decoding + * \author Carles Fernandez-Prades, 2023. cfernandez(at)cttc.es + * + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#include "geohash.h" +#include +#include +#include +#include +#include +#include + + +Geohash::Geohash() +{ + base32 = "0123456789bcdefghjkmnpqrstuvwxyz"; +} + +std::string Geohash::encode(double lat, double lon, int precision) const +{ + // infer precision? + if (precision == -1) + { + // refine geohash until it matches precision of supplied lat/lon + for (int p = 1; p <= 12; ++p) + { + const auto hash = Geohash::encode(lat, lon, p); + const auto posn = Geohash::decode(hash); + + if ((std::fabs(posn[0] - lat) < std::numeric_limits::epsilon()) && + (std::fabs(posn[1] - lon) < std::numeric_limits::epsilon())) + { + return hash; + } + } + precision = 12; // set to maximum + } + + if (std::isnan(lat) || std::isnan(lon) || precision < 1) + { + throw std::invalid_argument("Invalid geohash"); + } + + int idx = 0; // index into base32 map + int bit = 0; // each char holds 5 bits + bool evenBit = true; + std::string geohash = ""; + + double latMin = -90.0; + double latMax = 90.0; + double lonMin = -180.0; + double lonMax = 180.0; + + while (geohash.length() < static_cast(precision)) + { + if (evenBit) + { + // bisect E-W longitude + const double lonMid = (lonMin + lonMax) / 2.0; + if (lon >= lonMid) + { + idx = idx * 2 + 1; + lonMin = lonMid; + } + else + { + idx = idx * 2; + lonMax = lonMid; + } + } + else + { + // bisect N-S latitude + const double latMid = (latMin + latMax) / 2.0; + if (lat >= latMid) + { + idx = idx * 2 + 1; + latMin = latMid; + } + else + { + idx = idx * 2; + latMax = latMid; + } + } + evenBit = !evenBit; + + if (++bit == 5) + { + // 5 bits gives us a character: append it and start over + geohash += base32[idx]; + bit = 0; + idx = 0; + } + } + + return geohash; +} + + +std::array Geohash::decode(std::string geohash) const +{ + const auto bounds = Geohash::bounds(geohash); + + const double latMin = bounds[0]; + const double lonMin = bounds[1]; + const double latMax = bounds[2]; + const double lonMax = bounds[3]; + + // cell centre + double lat = (latMin + latMax) / 2.0; + double lon = (lonMin + lonMax) / 2.0; + + // round to close to centre without excessive precision: ⌊2-log10(Δ°)⌋ decimal places + std::array latlon{}; + latlon[0] = std::floor(lat * std::pow(10, std::floor(2 - std::log10(latMax - latMin)))); + latlon[1] = std::floor(lon * std::pow(10, std::floor(2 - std::log10(lonMax - lonMin)))); + + return latlon; +} + + +std::array Geohash::bounds(std::string geohash) const +{ + if (geohash.length() == 0) + { + throw std::runtime_error("Invalid geohash"); + } + + std::transform(geohash.begin(), geohash.end(), geohash.begin(), + [](unsigned char c) { return std::tolower(c); }); + + bool evenBit = true; + double latMin = -90.0; + double latMax = 90.0; + double lonMin = -180.0; + double lonMax = 180.0; + + for (size_t i = 0; i < geohash.length(); i++) + { + char chr = geohash[i]; + int idx = base32.find(chr); + if (idx == -1) + { + throw std::runtime_error("Invalid geohash"); + } + + for (int n = 4; n >= 0; n--) + { + int bitN = idx >> n & 1; + if (evenBit) + { + // longitude + double lonMid = (lonMin + lonMax) / 2; + if (bitN == 1) + { + lonMin = lonMid; + } + else + { + lonMax = lonMid; + } + } + else + { + // latitude + double latMid = (latMin + latMax) / 2; + if (bitN == 1) + { + latMin = latMid; + } + else + { + latMax = latMid; + } + } + evenBit = !evenBit; + } + } + + return {latMin, lonMin, latMax, lonMax}; +} \ No newline at end of file diff --git a/src/algorithms/PVT/libs/geohash.h b/src/algorithms/PVT/libs/geohash.h new file mode 100644 index 000000000..019dbaea5 --- /dev/null +++ b/src/algorithms/PVT/libs/geohash.h @@ -0,0 +1,74 @@ +/*! + * \file geohash.h + * \brief Interface of a class that encodes / decodes geohashes + * \author Carles Fernandez-Prades, 2023. cfernandez(at)cttc.es + * + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + + +#ifndef GNSS_SDR_GEOHASH_H +#define GNSS_SDR_GEOHASH_H + +#include +#include + +/** \addtogroup PVT + * \{ */ +/** \addtogroup PVT_libs + * \{ */ + +/*! + * \brief Class for geohash encoding / decoding + * See https://en.wikipedia.org/wiki/Geohash + */ +class Geohash +{ +public: + Geohash(); + + /** + * Encodes latitude/longitude to geohash, either to specified precision or + * to automatically evaluated precision. + * + * @param {double} lat - Latitude in degrees. + * @param {double} lon - Longitude in degrees. + * @param {int} [precision] - Number of characters in resulting geohash. + * @returns {string} Geohash of supplied latitude/longitude. + * @throws Invalid geohash. + * + */ + std::string encode(double lat, double lon, int precision = -1) const; + + /** + * Decode geohash to latitude/longitude (location is approximate centre of + * geohash cell, to reasonable precision). + * + * @param {string} geohash - Geohash string to be converted to + * latitude/longitude. + * @returns {lat, lon} (Center of) geohashed location. + * @throws Invalid geohash. + * + */ + std::array decode(std::string geohash) const; + +private: + /* + * Returns SW/NE latitude/longitude bounds of specified geohash. + */ + std::array bounds(std::string geohash) const; + std::string base32; +}; + +/** \} */ +/** \} */ +#endif // GNSS_SDR_GEOHASH_H diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index 15b5ffacc..3769756aa 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -72,6 +72,7 @@ DECLARE_string(log_dir); #include "unit-tests/signal-processing-blocks/adapter/adapter_test.cc" #include "unit-tests/signal-processing-blocks/adapter/pass_through_test.cc" #include "unit-tests/signal-processing-blocks/libs/item_type_helpers_test.cc" +#include "unit-tests/signal-processing-blocks/pvt/geohash_test.cc" #include "unit-tests/signal-processing-blocks/pvt/nmea_printer_test.cc" #include "unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc" #include "unit-tests/signal-processing-blocks/pvt/rtcm_printer_test.cc" diff --git a/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc b/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc new file mode 100644 index 000000000..bb1168a08 --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc @@ -0,0 +1,38 @@ +/*! + * \file geohash_test.cc + * \brief Implements Unit Tests for the Geohash class. + * \author Carles Fernandez-Prades, 2023. cfernandez(at)cttc.es + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#include "geohash.h" + +TEST(Geohash_Test, Encode) +{ + Geohash gh = Geohash(); + std::string hash; + EXPECT_NO_THROW(hash = gh.encode(52.205, 0.119, 7)); + + EXPECT_EQ(0, hash.compare("u120fxw")); + + EXPECT_THROW(gh.encode(52.205, 0.119, 0), std::invalid_argument); +} + +TEST(Geohash_Test, precision) +{ + Geohash gh = Geohash(); + std::string hash; + EXPECT_NO_THROW(hash = gh.encode(52.205, 0.119, 6)); + EXPECT_EQ(0, hash.compare("u120fx")); + EXPECT_NO_THROW(hash = gh.encode(52.205, 0.119, 5)); + EXPECT_EQ(0, hash.compare("u120f")); +} \ No newline at end of file diff --git a/src/tests/unit-tests/signal-processing-blocks/pvt/nmea_printer_test.cc b/src/tests/unit-tests/signal-processing-blocks/pvt/nmea_printer_test.cc index b4dfc483f..99c2bc0a3 100644 --- a/src/tests/unit-tests/signal-processing-blocks/pvt/nmea_printer_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/pvt/nmea_printer_test.cc @@ -1,5 +1,5 @@ /*! - * \file nma_printer_test.cc + * \file nmea_printer_test.cc * \brief Implements Unit Tests for the Nmea_Printer class. * \author Carles Fernandez-Prades, 2017. cfernandez(at)cttc.es * From 18e5345669a33ca60adce26ca784c66e3377173a Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 17 Mar 2023 13:51:01 +0100 Subject: [PATCH 3/7] clang-tidy fixes --- src/algorithms/PVT/libs/geohash.cc | 19 +++++++------------ src/algorithms/PVT/libs/geohash.h | 4 ++-- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/algorithms/PVT/libs/geohash.cc b/src/algorithms/PVT/libs/geohash.cc index 3682a7e0e..0021a752d 100644 --- a/src/algorithms/PVT/libs/geohash.cc +++ b/src/algorithms/PVT/libs/geohash.cc @@ -22,13 +22,9 @@ #include #include #include +#include -Geohash::Geohash() -{ - base32 = "0123456789bcdefghjkmnpqrstuvwxyz"; -} - std::string Geohash::encode(double lat, double lon, int precision) const { // infer precision? @@ -113,7 +109,7 @@ std::string Geohash::encode(double lat, double lon, int precision) const std::array Geohash::decode(std::string geohash) const { - const auto bounds = Geohash::bounds(geohash); + const auto bounds = Geohash::bounds(std::move(geohash)); const double latMin = bounds[0]; const double lonMin = bounds[1]; @@ -126,8 +122,8 @@ std::array Geohash::decode(std::string geohash) const // round to close to centre without excessive precision: ⌊2-log10(Δ°)⌋ decimal places std::array latlon{}; - latlon[0] = std::floor(lat * std::pow(10, std::floor(2 - std::log10(latMax - latMin)))); - latlon[1] = std::floor(lon * std::pow(10, std::floor(2 - std::log10(lonMax - lonMin)))); + latlon[0] = std::floor(lat * std::pow(10, std::floor(2.0 - std::log10(latMax - latMin)))); + latlon[1] = std::floor(lon * std::pow(10, std::floor(2.0 - std::log10(lonMax - lonMin)))); return latlon; } @@ -149,9 +145,8 @@ std::array Geohash::bounds(std::string geohash) const double lonMin = -180.0; double lonMax = 180.0; - for (size_t i = 0; i < geohash.length(); i++) + for (char chr : geohash) { - char chr = geohash[i]; int idx = base32.find(chr); if (idx == -1) { @@ -164,7 +159,7 @@ std::array Geohash::bounds(std::string geohash) const if (evenBit) { // longitude - double lonMid = (lonMin + lonMax) / 2; + double lonMid = (lonMin + lonMax) / 2.0; if (bitN == 1) { lonMin = lonMid; @@ -177,7 +172,7 @@ std::array Geohash::bounds(std::string geohash) const else { // latitude - double latMid = (latMin + latMax) / 2; + double latMid = (latMin + latMax) / 2.0; if (bitN == 1) { latMin = latMid; diff --git a/src/algorithms/PVT/libs/geohash.h b/src/algorithms/PVT/libs/geohash.h index 019dbaea5..a97015f44 100644 --- a/src/algorithms/PVT/libs/geohash.h +++ b/src/algorithms/PVT/libs/geohash.h @@ -34,7 +34,7 @@ class Geohash { public: - Geohash(); + Geohash() = default; /** * Encodes latitude/longitude to geohash, either to specified precision or @@ -66,7 +66,7 @@ private: * Returns SW/NE latitude/longitude bounds of specified geohash. */ std::array bounds(std::string geohash) const; - std::string base32; + std::string base32{"0123456789bcdefghjkmnpqrstuvwxyz"}; }; /** \} */ From da1a75ec39e3f6131fe8fcc462835a9886ef50c5 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sat, 18 Mar 2023 08:47:35 +0100 Subject: [PATCH 4/7] Fix geohash decoding --- src/algorithms/PVT/libs/geohash.cc | 8 ++++++-- .../pvt/geohash_test.cc | 19 +++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/algorithms/PVT/libs/geohash.cc b/src/algorithms/PVT/libs/geohash.cc index 0021a752d..33f14c705 100644 --- a/src/algorithms/PVT/libs/geohash.cc +++ b/src/algorithms/PVT/libs/geohash.cc @@ -122,8 +122,12 @@ std::array Geohash::decode(std::string geohash) const // round to close to centre without excessive precision: ⌊2-log10(Δ°)⌋ decimal places std::array latlon{}; - latlon[0] = std::floor(lat * std::pow(10, std::floor(2.0 - std::log10(latMax - latMin)))); - latlon[1] = std::floor(lon * std::pow(10, std::floor(2.0 - std::log10(lonMax - lonMin)))); + int decimalPlaces = std::floor(2.0 - std::log10(latMax - latMin)); + double factor = std::pow(10, decimalPlaces); + latlon[0] = std::round(lat * factor) / factor; + int decimalPlaces2 = std::floor(2.0 - std::log10(lonMax - lonMin)); + double factor2 = std::pow(10, decimalPlaces2); + latlon[1] = std::round(lon * factor2) / factor2; return latlon; } diff --git a/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc b/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc index bb1168a08..9eb0080ad 100644 --- a/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc @@ -19,15 +19,22 @@ TEST(Geohash_Test, Encode) { Geohash gh = Geohash(); - std::string hash; - EXPECT_NO_THROW(hash = gh.encode(52.205, 0.119, 7)); - - EXPECT_EQ(0, hash.compare("u120fxw")); - + std::string geohash; + EXPECT_NO_THROW(geohash = gh.encode(52.205, 0.119, 7)); + EXPECT_EQ(0, geohash.compare("u120fxw")); EXPECT_THROW(gh.encode(52.205, 0.119, 0), std::invalid_argument); } -TEST(Geohash_Test, precision) +TEST(Geohash_Test, Decode) +{ + Geohash gh = Geohash(); + auto latlon = gh.decode("sp36v1zk0e2g"); + EXPECT_NEAR(41.274966141209006, latlon[0], 1e-8); + EXPECT_NEAR(1.9875180535018444, latlon[1], 1e-8); + EXPECT_THROW(gh.decode(""), std::runtime_error); +} + +TEST(Geohash_Test, Precision) { Geohash gh = Geohash(); std::string hash; From 43eec445799548a9b23000a05e99002c9c3a3d04 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sat, 18 Mar 2023 11:39:44 +0100 Subject: [PATCH 5/7] Improve geohash test, make it easier to read the log --- .../PVT/gnuradio_blocks/rtklib_pvt_gs.cc | 2 +- .../signal-processing-blocks/pvt/geohash_test.cc | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc index 9d2b843b3..8f6f1648a 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_gs.cc @@ -2434,7 +2434,7 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item LOG(INFO) << "Position at " << boost::posix_time::to_simple_string(d_user_pvt_solver->get_position_UTC_time()) << " UTC using " << d_user_pvt_solver->get_num_valid_observations() << " observations is Lat = " << d_user_pvt_solver->get_latitude() << " [deg], Long = " << d_user_pvt_solver->get_longitude() << " [deg], Height = " << d_user_pvt_solver->get_height() << " [m]"; - LOG(INFO) << "geohash: " << d_geohash->encode(d_user_pvt_solver->get_latitude(), d_user_pvt_solver->get_longitude()); + LOG(INFO) << "geohash=" << d_geohash->encode(d_user_pvt_solver->get_latitude(), d_user_pvt_solver->get_longitude()); /* std::cout << "Dilution of Precision at " << boost::posix_time::to_simple_string(d_user_pvt_solver->get_position_UTC_time()) << " UTC using "<< d_user_pvt_solver->get_num_valid_observations() <<" observations is HDOP = " << d_user_pvt_solver->get_hdop() << " VDOP = " << d_user_pvt_solver->get_vdop() diff --git a/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc b/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc index 9eb0080ad..845c67937 100644 --- a/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/pvt/geohash_test.cc @@ -22,18 +22,28 @@ TEST(Geohash_Test, Encode) std::string geohash; EXPECT_NO_THROW(geohash = gh.encode(52.205, 0.119, 7)); EXPECT_EQ(0, geohash.compare("u120fxw")); + EXPECT_NO_THROW(geohash = gh.encode(41.274966141209, 1.987518053501)); + EXPECT_EQ(0, geohash.compare("sp36v1zk0e2g")); EXPECT_THROW(gh.encode(52.205, 0.119, 0), std::invalid_argument); } + TEST(Geohash_Test, Decode) { Geohash gh = Geohash(); auto latlon = gh.decode("sp36v1zk0e2g"); - EXPECT_NEAR(41.274966141209006, latlon[0], 1e-8); - EXPECT_NEAR(1.9875180535018444, latlon[1], 1e-8); + EXPECT_NEAR(41.274966141209, latlon[0], 1e-8); + EXPECT_NEAR(1.987518053501, latlon[1], 1e-8); EXPECT_THROW(gh.decode(""), std::runtime_error); + latlon = gh.decode("w21zd2mkt"); + EXPECT_NEAR(1.320527, latlon[0], 1e-8); + EXPECT_NEAR(103.81726, latlon[1], 1e-8); + latlon = gh.decode("W21ZD2MKT"); + EXPECT_NEAR(1.320527, latlon[0], 1e-8); + EXPECT_NEAR(103.81726, latlon[1], 1e-8); } + TEST(Geohash_Test, Precision) { Geohash gh = Geohash(); From 060c3af12406169b3bbd4b58afe13dd10ceea9fc Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sat, 18 Mar 2023 11:41:43 +0100 Subject: [PATCH 6/7] cpu_features: Add Windows Arm64 support, update C++ standard for tests from C++11 to C++14, add Raptor Lake-P and Raptor Lake-HX/S detection --- .../volk_gnsssdr/cpu_features/CMakeLists.txt | 5 +- .../include/cpu_features_macros.h | 2 +- .../cpu_features/include/cpuinfo_aarch64.h | 103 +++++++++- .../include/internal/windows_utils.h | 32 +++ .../cpu_features/src/impl_aarch64_windows.c | 130 ++++++++++++ .../cpu_features/test/CMakeLists.txt | 6 +- .../cpu_features/test/cpuinfo_aarch64_test.cc | 188 ++++++++---------- .../cpu_features/test/cpuinfo_x86_test.cc | 35 ++++ 8 files changed, 388 insertions(+), 113 deletions(-) create mode 100644 src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/impl_aarch64_windows.c diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt index 56c411c53..c213b6016 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt @@ -85,6 +85,7 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h) elseif(PROCESSOR_IS_AARCH64) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h) elseif(PROCESSOR_IS_X86) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h) list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h) @@ -185,9 +186,9 @@ if(BUILD_TESTING) # found. enable_language(CXX) - set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11 + set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std14 instead of -gnustd14 if(NOT TARGET gtest OR NOT TARGET gmock_main) # Download and unpack googletest at configure time. diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h index ace763248..2a8442db9 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h @@ -28,7 +28,7 @@ #define CPU_FEATURES_ARCH_ARM #endif -#if defined(__aarch64__) +#if (defined(__aarch64__) || defined(_M_ARM64)) #define CPU_FEATURES_ARCH_AARCH64 #endif diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h index b68869e3f..9fafccab8 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h @@ -1,6 +1,100 @@ // SPDX-FileCopyrightText: 2017 Google LLC // SPDX-License-Identifier: Apache-2.0 +//////////////////////////////////////////////////////////////////////////////// +// A note on Windows AArch64 implementation +//////////////////////////////////////////////////////////////////////////////// + +// Getting cpu info via EL1 system registers is not possible, so we delegate it +// to the Windows API (i.e., IsProcessorFeaturePresent and GetNativeSystemInfo). +// The `implementer`, `variant` and `part` fields of the `Aarch64Info` struct +// are not used, so they are set to 0. To get `revision` we use +// `wProcessorRevision` from `SYSTEM_INFO`. +// +// Cryptographic Extension: +// ----------------------------------------------------------------------------- +// According to documentation Arm Architecture Reference Manual for +// A-profile architecture. A2.3 The Armv8 Cryptographic Extension. The Armv8.0 +// Cryptographic Extension provides instructions for the acceleration of +// encryption and decryption, and includes the following features: FEAT_AES, +// FEAT_PMULL, FEAT_SHA1, FEAT_SHA256. +// see: https://developer.arm.com/documentation/ddi0487/latest +// +// We use `PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE` to detect all Armv8.0 crypto +// features. This value reports all features or nothing, so even if you only +// have support FEAT_AES and FEAT_PMULL, it will still return false. +// +// From Armv8.2, an implementation of the Armv8.0 Cryptographic Extension can +// include either or both of: +// +// • The AES functionality, including support for multiplication of 64-bit +// polynomials. The ID_AA64ISAR0_EL1.AES field indicates whether this +// functionality is supported. +// • The SHA1 and SHA2-256 functionality. The ID_AA64ISAR0_EL1.{SHA2, SHA1} +// fields indicate whether this functionality is supported. +// +// ID_AA64ISAR0_EL1.AES, bits [7:4]: +// Indicates support for AES instructions in AArch64 state. Defined values are: +// - 0b0000 No AES instructions implemented. +// - 0b0001 AESE, AESD, AESMC, and AESIMC instructions implemented. +// - 0b0010 As for 0b0001, plus PMULL/PMULL2 instructions operating on 64-bit +// data quantities. +// +// FEAT_AES implements the functionality identified by the value 0b0001. +// FEAT_PMULL implements the functionality identified by the value 0b0010. +// From Armv8, the permitted values are 0b0000 and 0b0010. +// +// ID_AA64ISAR0_EL1.SHA1, bits [11:8]: +// Indicates support for SHA1 instructions in AArch64 state. Defined values are: +// - 0b0000 No SHA1 instructions implemented. +// - 0b0001 SHA1C, SHA1P, SHA1M, SHA1H, SHA1SU0, and SHA1SU1 instructions +// implemented. +// +// FEAT_SHA1 implements the functionality identified by the value 0b0001. +// From Armv8, the permitted values are 0b0000 and 0b0001. +// If the value of ID_AA64ISAR0_EL1.SHA2 is 0b0000, this field must have the +// value 0b0000. +// +// ID_AA64ISAR0_EL1.SHA2, bits [15:12]: +// Indicates support for SHA2 instructions in AArch64 state. Defined values are: +// - 0b0000 No SHA2 instructions implemented. +// - 0b0001 Implements instructions: SHA256H, SHA256H2, SHA256SU0, and +// SHA256SU1. +// - 0b0010 Implements instructions: +// • SHA256H, SHA256H2, SHA256SU0, and SHA256SU1. +// • SHA512H, SHA512H2, SHA512SU0, and SHA512SU1. +// +// FEAT_SHA256 implements the functionality identified by the value 0b0001. +// FEAT_SHA512 implements the functionality identified by the value 0b0010. +// +// In Armv8, the permitted values are 0b0000 and 0b0001. +// From Armv8.2, the permitted values are 0b0000, 0b0001, and 0b0010. +// +// If the value of ID_AA64ISAR0_EL1.SHA1 is 0b0000, this field must have the +// value 0b0000. +// +// If the value of this field is 0b0010, ID_AA64ISAR0_EL1.SHA3 +// must have the value 0b0001. +// +// Other cryptographic features that we cannot detect such as sha512, sha3, sm3, +// sm4, sveaes, svepmull, svesha3, svesm4 we set to 0. +// +// FP/SIMD: +// ----------------------------------------------------------------------------- +// FP/SIMD must be implemented on all Armv8.0 implementations, but +// implementations targeting specialized markets may support the following +// combinations: +// +// • No NEON or floating-point. +// • Full floating-point and SIMD support with exception trapping. +// • Full floating-point and SIMD support without exception trapping. +// +// ref: +// https://developer.arm.com/documentation/den0024/a/AArch64-Floating-point-and-NEON +// +// So, we use `PF_ARM_VFP_32_REGISTERS_AVAILABLE`, +// `PF_ARM_NEON_INSTRUCTIONS_AVAILABLE` to detect `asimd` and `fp` + #ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ #define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ @@ -72,10 +166,11 @@ typedef struct typedef struct { Aarch64Features features; - int implementer; - int variant; - int part; - int revision; + int implementer; // We set 0 for Windows. + int variant; // We set 0 for Windows. + int part; // We set 0 for Windows. + int revision; // We use GetNativeSystemInfo to get processor revision for + // Windows. } Aarch64Info; Aarch64Info GetAarch64Info(void); diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/windows_utils.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/windows_utils.h index 1790adc9c..cc08d3c9f 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/windows_utils.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/windows_utils.h @@ -22,5 +22,37 @@ #define PF_SSE4_2_INSTRUCTIONS_AVAILABLE 38 #endif +#if !defined(PF_ARM_VFP_32_REGISTERS_AVAILABLE) +#define PF_ARM_VFP_32_REGISTERS_AVAILABLE 18 +#endif + +#if !defined(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) +#define PF_ARM_NEON_INSTRUCTIONS_AVAILABLE 19 +#endif + +#if !defined(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) +#define PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE 30 +#endif + +#if !defined(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) +#define PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE 31 +#endif + +#if !defined(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE) +#define PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE 34 +#endif + +#if !defined(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) +#define PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE 43 +#endif + +#if !defined(PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE) +#define PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE 44 +#endif + +#if !defined(PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE) +#define PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE 45 +#endif + #endif // CPU_FEATURES_OS_WINDOWS #endif // CPU_FEATURES_INCLUDE_INTERNAL_WINDOWS_UTILS_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/impl_aarch64_windows.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/impl_aarch64_windows.c new file mode 100644 index 000000000..dd830863b --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/impl_aarch64_windows.c @@ -0,0 +1,130 @@ +// SPDX-FileCopyrightText: 2023 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpu_features_macros.h" + +#ifdef CPU_FEATURES_ARCH_AARCH64 +#ifdef CPU_FEATURES_OS_WINDOWS + +#include "cpuinfo_aarch64.h" + +//////////////////////////////////////////////////////////////////////////////// +// Definitions for introspection. +//////////////////////////////////////////////////////////////////////////////// +#define INTROSPECTION_TABLE \ + LINE(AARCH64_FP, fp, , , ) \ + LINE(AARCH64_ASIMD, asimd, , , ) \ + LINE(AARCH64_EVTSTRM, evtstrm, , , ) \ + LINE(AARCH64_AES, aes, , , ) \ + LINE(AARCH64_PMULL, pmull, , , ) \ + LINE(AARCH64_SHA1, sha1, , , ) \ + LINE(AARCH64_SHA2, sha2, , , ) \ + LINE(AARCH64_CRC32, crc32, , , ) \ + LINE(AARCH64_ATOMICS, atomics, , , ) \ + LINE(AARCH64_FPHP, fphp, , , ) \ + LINE(AARCH64_ASIMDHP, asimdhp, , , ) \ + LINE(AARCH64_CPUID, cpuid, , , ) \ + LINE(AARCH64_ASIMDRDM, asimdrdm, , , ) \ + LINE(AARCH64_JSCVT, jscvt, , , ) \ + LINE(AARCH64_FCMA, fcma, , , ) \ + LINE(AARCH64_LRCPC, lrcpc, , , ) \ + LINE(AARCH64_DCPOP, dcpop, , , ) \ + LINE(AARCH64_SHA3, sha3, , , ) \ + LINE(AARCH64_SM3, sm3, , , ) \ + LINE(AARCH64_SM4, sm4, , , ) \ + LINE(AARCH64_ASIMDDP, asimddp, , , ) \ + LINE(AARCH64_SHA512, sha512, , , ) \ + LINE(AARCH64_SVE, sve, , , ) \ + LINE(AARCH64_ASIMDFHM, asimdfhm, , , ) \ + LINE(AARCH64_DIT, dit, , , ) \ + LINE(AARCH64_USCAT, uscat, , , ) \ + LINE(AARCH64_ILRCPC, ilrcpc, , , ) \ + LINE(AARCH64_FLAGM, flagm, , , ) \ + LINE(AARCH64_SSBS, ssbs, , , ) \ + LINE(AARCH64_SB, sb, , , ) \ + LINE(AARCH64_PACA, paca, , , ) \ + LINE(AARCH64_PACG, pacg, , , ) \ + LINE(AARCH64_DCPODP, dcpodp, , , ) \ + LINE(AARCH64_SVE2, sve2, , , ) \ + LINE(AARCH64_SVEAES, sveaes, , , ) \ + LINE(AARCH64_SVEPMULL, svepmull, , , ) \ + LINE(AARCH64_SVEBITPERM, svebitperm, , , ) \ + LINE(AARCH64_SVESHA3, svesha3, , , ) \ + LINE(AARCH64_SVESM4, svesm4, , , ) \ + LINE(AARCH64_FLAGM2, flagm2, , , ) \ + LINE(AARCH64_FRINT, frint, , , ) \ + LINE(AARCH64_SVEI8MM, svei8mm, , , ) \ + LINE(AARCH64_SVEF32MM, svef32mm, , , ) \ + LINE(AARCH64_SVEF64MM, svef64mm, , , ) \ + LINE(AARCH64_SVEBF16, svebf16, , , ) \ + LINE(AARCH64_I8MM, i8mm, , , ) \ + LINE(AARCH64_BF16, bf16, , , ) \ + LINE(AARCH64_DGH, dgh, , , ) \ + LINE(AARCH64_RNG, rng, , , ) \ + LINE(AARCH64_BTI, bti, , , ) \ + LINE(AARCH64_MTE, mte, , , ) \ + LINE(AARCH64_ECV, ecv, , , ) \ + LINE(AARCH64_AFP, afp, , , ) \ + LINE(AARCH64_RPRES, rpres, , , ) +#define INTROSPECTION_PREFIX Aarch64 +#define INTROSPECTION_ENUM_PREFIX AARCH64 +#include "define_introspection.inl" + +//////////////////////////////////////////////////////////////////////////////// +// Implementation. +//////////////////////////////////////////////////////////////////////////////// + +#include "internal/windows_utils.h" +#include + +#ifdef CPU_FEATURES_MOCK_CPUID_AARCH64 +extern bool GetWindowsIsProcessorFeaturePresent(DWORD); +extern WORD GetWindowsNativeSystemInfoProcessorRevision(); +#else // CPU_FEATURES_MOCK_CPUID_AARCH64 +static bool +GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) +{ + return IsProcessorFeaturePresent(dwProcessorFeature); +} + +static WORD GetWindowsNativeSystemInfoProcessorRevision() +{ + SYSTEM_INFO system_info; + GetNativeSystemInfo(&system_info); + return system_info.wProcessorRevision; +} +#endif + +static const Aarch64Info kEmptyAarch64Info; + +Aarch64Info GetAarch64Info(void) +{ + Aarch64Info info = kEmptyAarch64Info; + info.revision = GetWindowsNativeSystemInfoProcessorRevision(); + info.features.fp = + GetWindowsIsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE); + info.features.asimd = + GetWindowsIsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE); + info.features.crc32 = GetWindowsIsProcessorFeaturePresent( + PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); + info.features.asimddp = + GetWindowsIsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE); + info.features.jscvt = GetWindowsIsProcessorFeaturePresent( + PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE); + info.features.lrcpc = GetWindowsIsProcessorFeaturePresent( + PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE); + info.features.atomics = GetWindowsIsProcessorFeaturePresent( + PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE); + + + bool is_crypto_available = GetWindowsIsProcessorFeaturePresent( + PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE); + info.features.aes = is_crypto_available; + info.features.sha1 = is_crypto_available; + info.features.sha2 = is_crypto_available; + info.features.pmull = is_crypto_available; + return info; +} + +#endif // CPU_FEATURES_OS_WINDOWS +#endif // CPU_FEATURES_ARCH_AARCH64 \ No newline at end of file diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/CMakeLists.txt index 8df134964..5d41179e5 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/CMakeLists.txt @@ -74,7 +74,11 @@ endif() ##------------------------------------------------------------------------------ ## cpuinfo_aarch64_test if(PROCESSOR_IS_AARCH64) - add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/impl_aarch64_linux_or_android.c) + add_executable(cpuinfo_aarch64_test + cpuinfo_aarch64_test.cc + ../src/impl_aarch64_linux_or_android.c + ../src/impl_aarch64_windows.c) + target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_CPUID_AARCH64) target_link_libraries(cpuinfo_aarch64_test all_libraries) add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test) endif() diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc index 8d88e49d3..d2450752a 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc @@ -5,150 +5,103 @@ #include "filesystem_for_testing.h" #include "gtest/gtest.h" #include "hwcaps_for_testing.h" +#include + +#if defined(CPU_FEATURES_OS_WINDOWS) +#include "internal/windows_utils.h" +#endif // CPU_FEATURES_OS_WINDOWS namespace cpu_features { -namespace -{ -#if defined(CPU_FEATURES_OS_DARWIN) - -class FakeCpu +class FakeCpuAarch64 { public: - bool GetDarwinSysCtlByName(std::string name) const +#if defined(CPU_FEATURES_OS_WINDOWS) + bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) { - return darwin_sysctlbyname_.count(name); + return windows_isprocessorfeaturepresent_.count(dwProcessorFeature); } - int GetDarwinSysCtlByNameValue(std::string name) const + void SetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) { - std::map::const_iterator iter = - darwin_sysctlbynamevalue_.find(name); - if (iter != std::end(darwin_sysctlbynamevalue_)) - { - return iter->second; - } - - return 0; + windows_isprocessorfeaturepresent_.insert(dwProcessorFeature); } - void SetDarwinSysCtlByName(std::string name) + WORD GetWindowsNativeSystemInfoProcessorRevision() const { - darwin_sysctlbyname_.insert(name); + return processor_revision_; } - void SetDarwinSysCtlByNameValue(std::string name, int value) + void SetWindowsNativeSystemInfoProcessorRevision(WORD wProcessorRevision) { - darwin_sysctlbynamevalue_[name] = value; + processor_revision_ = wProcessorRevision; } private: - std::set darwin_sysctlbyname_; - std::map darwin_sysctlbynamevalue_; + std::set windows_isprocessorfeaturepresent_; + WORD processor_revision_{}; +#endif // CPU_FEATURES_OS_WINDOWS }; -FakeCpu* g_fake_cpu = nullptr; +static FakeCpuAarch64* g_fake_cpu_instance = nullptr; -extern "C" bool GetDarwinSysCtlByName(const char* name) +static FakeCpuAarch64& cpu() { - return g_fake_cpu->GetDarwinSysCtlByName(name); + assert(g_fake_cpu_instance != nullptr); + return *g_fake_cpu_instance; } -extern "C" int GetDarwinSysCtlByNameValue(const char* name) +#if defined(CPU_FEATURES_OS_WINDOWS) +extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) { - return g_fake_cpu->GetDarwinSysCtlByNameValue(name); + return cpu().GetWindowsIsProcessorFeaturePresent(dwProcessorFeature); } -class CpuinfoAarch64Test : public ::testing::Test +extern "C" WORD GetWindowsNativeSystemInfoProcessorRevision() +{ + return cpu().GetWindowsNativeSystemInfoProcessorRevision(); +} +#endif // CPU_FEATURES_OS_WINDOWS + +namespace +{ + +class CpuidAarch64Test : public ::testing::Test { protected: - void SetUp() override { g_fake_cpu = new FakeCpu(); } - void TearDown() override { delete g_fake_cpu; } + void SetUp() override + { + assert(g_fake_cpu_instance == nullptr); + g_fake_cpu_instance = new FakeCpuAarch64(); + } + void TearDown() override + { + delete g_fake_cpu_instance; + g_fake_cpu_instance = nullptr; + } }; -TEST_F(CpuinfoAarch64Test, FromDarwinSysctlFromName) -{ - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.floatingpoint"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.neon"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.neon_hpfp"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.neon_fp16"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.armv8_1_atomics"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.armv8_crc32"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.armv8_2_fhm"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.armv8_2_sha512"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.armv8_2_sha3"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.amx_version"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.ucnormal_mem"); - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.arm64"); - - g_fake_cpu->SetDarwinSysCtlByNameValue("hw.cputype", 16777228); - g_fake_cpu->SetDarwinSysCtlByNameValue("hw.cpusubtype", 2); - g_fake_cpu->SetDarwinSysCtlByNameValue("hw.cpu64bit", 1); - g_fake_cpu->SetDarwinSysCtlByNameValue("hw.cpufamily", 458787763); - g_fake_cpu->SetDarwinSysCtlByNameValue("hw.cpusubfamily", 2); - - const auto info = GetAarch64Info(); - - EXPECT_EQ(info.implementer, 0x100000C); - EXPECT_EQ(info.variant, 2); - EXPECT_EQ(info.part, 0x1B588BB3); - EXPECT_EQ(info.revision, 2); - - EXPECT_TRUE(info.features.fp); - EXPECT_FALSE(info.features.asimd); - EXPECT_FALSE(info.features.evtstrm); - EXPECT_FALSE(info.features.aes); - EXPECT_FALSE(info.features.pmull); - EXPECT_FALSE(info.features.sha1); - EXPECT_FALSE(info.features.sha2); - EXPECT_TRUE(info.features.crc32); - EXPECT_TRUE(info.features.atomics); - EXPECT_TRUE(info.features.fphp); - EXPECT_FALSE(info.features.asimdhp); - EXPECT_FALSE(info.features.cpuid); - EXPECT_FALSE(info.features.asimdrdm); - EXPECT_FALSE(info.features.jscvt); - EXPECT_FALSE(info.features.fcma); - EXPECT_FALSE(info.features.lrcpc); - EXPECT_FALSE(info.features.dcpop); - EXPECT_TRUE(info.features.sha3); - EXPECT_FALSE(info.features.sm3); - EXPECT_FALSE(info.features.sm4); - EXPECT_FALSE(info.features.asimddp); - EXPECT_TRUE(info.features.sha512); - EXPECT_FALSE(info.features.sve); - EXPECT_TRUE(info.features.asimdfhm); - EXPECT_FALSE(info.features.dit); - EXPECT_FALSE(info.features.uscat); - EXPECT_FALSE(info.features.ilrcpc); - EXPECT_FALSE(info.features.flagm); - EXPECT_FALSE(info.features.ssbs); - EXPECT_FALSE(info.features.sb); - EXPECT_FALSE(info.features.paca); - EXPECT_FALSE(info.features.pacg); -} - -#else - -void DisableHardwareCapabilities() -{ - SetHardwareCapabilities(0, 0); -} - TEST(CpuinfoAarch64Test, Aarch64FeaturesEnum) { - const char *last_name = GetAarch64FeaturesEnumName(AARCH64_LAST_); + const char* last_name = GetAarch64FeaturesEnumName(AARCH64_LAST_); EXPECT_STREQ(last_name, "unknown_feature"); - for (int i = static_cast(AARCH64_FP); i != static_cast(AARCH64_LAST_); ++i) + for (int i = static_cast(AARCH64_FP); + i != static_cast(AARCH64_LAST_); ++i) { const auto feature = static_cast(i); - const char *name = GetAarch64FeaturesEnumName(feature); + const char* name = GetAarch64FeaturesEnumName(feature); ASSERT_FALSE(name == nullptr); EXPECT_STRNE(name, ""); EXPECT_STRNE(name, last_name); } } +#if defined(CPU_FEATURES_OS_LINUX) +void DisableHardwareCapabilities() +{ + SetHardwareCapabilities(0, 0); +} + TEST(CpuinfoAarch64Test, FromHardwareCap) { ResetHwcaps(); @@ -222,7 +175,7 @@ TEST(CpuinfoAarch64Test, FromHardwareCap2) TEST(CpuinfoAarch64Test, ARMCortexA53) { ResetHwcaps(); - auto &fs = GetEmptyFilesystem(); + auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(Processor : AArch64 Processor rev 3 (aarch64) processor : 0 @@ -301,8 +254,33 @@ CPU revision : 3)"); EXPECT_FALSE(info.features.afp); EXPECT_FALSE(info.features.rpres); } +#endif // CPU_FEATURES_OS_LINUX -#endif +#if defined(CPU_FEATURES_OS_WINDOWS) +TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) +{ + cpu().SetWindowsNativeSystemInfoProcessorRevision(0x03); + cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent( + PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); + + const auto info = GetAarch64Info(); + + EXPECT_EQ(info.revision, 0x03); + EXPECT_TRUE(info.features.fp); + EXPECT_TRUE(info.features.asimd); + EXPECT_TRUE(info.features.crc32); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.atomics); + EXPECT_FALSE(info.features.asimddp); + EXPECT_FALSE(info.features.jscvt); + EXPECT_FALSE(info.features.lrcpc); +} +#endif // CPU_FEATURES_OS_WINDOWS } // namespace -} // namespace cpu_features +} // namespace cpu_features \ No newline at end of file diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc index f83df2efa..3948e1399 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc @@ -1708,6 +1708,41 @@ TEST_F(CpuidX86Test, INTEL_HASWELL_LZCNT) EXPECT_TRUE(info.features.lzcnt); } +// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00B06A2_RaptorLakeP_03_CPUID.txt +TEST_F(CpuidX86Test, INTEL_RAPTOR_LAKE_P) +{ + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000B06A3, 0x00400800, 0x7FFAFBFF, 0xBFEBFBFF}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0xBA); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_RPL); +} + +// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00B06F2_RaptorLakeS_02_CPUID.txt +TEST_F(CpuidX86Test, INTEL_RAPTOR_LAKE_S) +{ + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000B06F2, 0x00800800, 0x7FFAFBFF, 0xBFEBFBFF}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0xBF); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_RPL); +} + + // https://github.com/google/cpu_features/issues/200 // http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00206F2_Eagleton_CPUID.txt #if defined(CPU_FEATURES_OS_WINDOWS) From 6004b8f90119e4a114a4053ebe13a71b3c999a64 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 19 Mar 2023 13:53:58 +0100 Subject: [PATCH 7/7] Fix logic for downloading test files (Fixes: #707) --- src/tests/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index af8e96075..53cc054d9 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -471,8 +471,8 @@ if(ENABLE_UNIT_TESTING_EXTRA OR ENABLE_SYSTEM_TESTING_EXTRA OR ENABLE_FPGA) endif() endif() -if(NOT ENABLE_PACKAGING OR NOT ENABLE_UNIT_TESTING_MINIMAL) - message(STATUS "Downloading some data files for testing...") +if(NOT (ENABLE_PACKAGING OR ENABLE_UNIT_TESTING_MINIMAL)) + message(STATUS "Downloading some data files for testing ...") if(NOT EXISTS ${GNSSSDR_BINARY_DIR}/thirdparty/signal_samples/Galileo_E1_ID_1_Fs_4Msps_8ms.dat) message(STATUS "Downloading file: Galileo_E1_ID_1_Fs_4Msps_8ms.dat") file(DOWNLOAD https://sourceforge.net/projects/gnss-sdr/files/data/Galileo_E1_ID_1_Fs_4Msps_8ms.dat @@ -510,7 +510,7 @@ endif() if(ENABLE_UNIT_TESTING_EXTRA) add_definitions(-DEXTRA_TESTS) - message(STATUS "Downloading some extra data files for testing...") + message(STATUS "Downloading some extra data files for testing ...") if(NOT EXISTS ${GNSSSDR_BINARY_DIR}/thirdparty/signal_samples/gps_l2c_m_prn7_5msps.dat) message(STATUS "Downloading file: gps_l2c_m_prn7_5msps.dat") file(DOWNLOAD https://sourceforge.net/projects/gnss-sdr/files/data/gps_l2c_m_prn7_5msps.dat