mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-11-12 05:13:04 +00:00
real-time FPGA receiver buffer monitoring
This commit is contained in:
@@ -17,6 +17,8 @@ if(ENABLE_FPGA OR ENABLE_AD9361)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_switch.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_dynamic_bit_selection.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_dynamic_bit_selection.h)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_SOURCES ${OPT_SIGNAL_SOURCE_LIB_SOURCES} fpga_buffer_monitor.cc)
|
||||
set(OPT_SIGNAL_SOURCE_LIB_HEADERS ${OPT_SIGNAL_SOURCE_LIB_HEADERS} fpga_buffer_monitor.h)
|
||||
endif()
|
||||
|
||||
set(SIGNAL_SOURCE_LIB_SOURCES
|
||||
|
||||
147
src/algorithms/signal_source/libs/fpga_buffer_monitor.cc
Normal file
147
src/algorithms/signal_source/libs/fpga_buffer_monitor.cc
Normal file
@@ -0,0 +1,147 @@
|
||||
/*!
|
||||
* \file fpga_buffer_monitor.cc
|
||||
* \brief Check receiver buffer overflow and monitor the status of the receiver buffers.
|
||||
* \authors <ul>
|
||||
* <li> Marc Majoral, 2020. mmajoral(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* Class that checks the receiver buffer overflow flags and monitors the status of the receiver buffers.
|
||||
*
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "fpga_buffer_monitor.h"
|
||||
#include <glog/logging.h>
|
||||
#include <fcntl.h> // for open, O_RDWR, O_SYNC
|
||||
#include <iostream> // for cout
|
||||
#include <sys/mman.h> // for mmap
|
||||
|
||||
Fpga_buffer_monitor::Fpga_buffer_monitor(const std::string &device_name, uint32_t num_freq_bands)
|
||||
{
|
||||
d_num_freq_bands = num_freq_bands;
|
||||
|
||||
// open device descriptor
|
||||
if ((d_device_descriptor = open(device_name.c_str(), O_RDWR | O_SYNC)) == -1)
|
||||
{
|
||||
LOG(WARNING) << "Cannot open deviceio" << device_name;
|
||||
}
|
||||
|
||||
// device memory map
|
||||
d_map_base = reinterpret_cast<volatile unsigned *>(mmap(nullptr, FPGA_PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0));
|
||||
|
||||
if (d_map_base == reinterpret_cast<void *>(-1))
|
||||
{
|
||||
LOG(WARNING) << "Cannot map the FPGA buffer monitor module";
|
||||
std::cout << "Could not map the FPGA buffer monitor \n";
|
||||
}
|
||||
|
||||
// sanity check: check test register
|
||||
if (buffer_monitor_test_register() < 0)
|
||||
{
|
||||
LOG(WARNING) << "FPGA buffer monitor test register sanity check failed";
|
||||
std::cout << "FPGA buffer monitor test register sanity check failed\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(INFO) << "FPGA buffer monitor test register sanity check success !";
|
||||
}
|
||||
|
||||
DLOG(INFO) << "FPGA buffer monitor class created";
|
||||
|
||||
// initialize maximum buffer occupancy in case buffer monitoring is enabled
|
||||
max_buff_occ_freq_band_0 = 0;
|
||||
max_buff_occ_freq_band_1 = 0;
|
||||
}
|
||||
|
||||
|
||||
Fpga_buffer_monitor::~Fpga_buffer_monitor()
|
||||
{
|
||||
close_device();
|
||||
}
|
||||
|
||||
|
||||
void Fpga_buffer_monitor::check_buffer_overflow()
|
||||
{
|
||||
// check buffer overflow flags
|
||||
uint32_t buffer_overflow_status = d_map_base[overflow_flags_reg_addr];
|
||||
|
||||
if ((buffer_overflow_status & overflow_freq_band_0_bit_pos) != 0)
|
||||
{
|
||||
std::cout << "Buffer overflow in frequency band 0" << std::endl;
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
if (d_num_freq_bands > 1)
|
||||
{
|
||||
if ((buffer_overflow_status & overflow_freq_band_1_bit_pos) != 0)
|
||||
{
|
||||
std::cout << "Buffer overflow in frequency band 1" << std::endl;
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fpga_buffer_monitor::monitor_buffer_status(void)
|
||||
{
|
||||
uint32_t current_buff_occ_freq_band_0 = d_map_base[current_buff_occ_freq_band_0_reg_addr] * num_sapmples_per_buffer_element;
|
||||
uint32_t temp_max_buff_occ_freq_band_0 = d_map_base[max_buff_occ_freq_band_0_reg_addr] * num_sapmples_per_buffer_element;
|
||||
if (temp_max_buff_occ_freq_band_0 > max_buff_occ_freq_band_0)
|
||||
{
|
||||
max_buff_occ_freq_band_0 = temp_max_buff_occ_freq_band_0;
|
||||
}
|
||||
std::cout << "current buffer occupancy frequency band 0 = " << current_buff_occ_freq_band_0 << " samples " << std::endl;
|
||||
std::cout << "temporary maximum buffer occupancy frequency band 0 = " << temp_max_buff_occ_freq_band_0 << " samples " << std::endl;
|
||||
std::cout << "maximum buffer occupancy frequency band 0 = " << max_buff_occ_freq_band_0 << " samples " << std::endl;
|
||||
|
||||
if (d_num_freq_bands > 1)
|
||||
{
|
||||
uint32_t current_buff_occ_freq_band_1 = d_map_base[current_buff_occ_freq_band_1_reg_addr] * num_sapmples_per_buffer_element;
|
||||
uint32_t temp_max_buff_occ_freq_band_1 = d_map_base[max_buff_occ_freq_band_1_reg_addr] * num_sapmples_per_buffer_element;
|
||||
if (temp_max_buff_occ_freq_band_1 > max_buff_occ_freq_band_1)
|
||||
{
|
||||
max_buff_occ_freq_band_1 = temp_max_buff_occ_freq_band_1;
|
||||
}
|
||||
std::cout << "current buffer occupancy frequency band 1 = " << current_buff_occ_freq_band_1 << " samples " << std::endl;
|
||||
std::cout << "temporary maximum buffer occupancy frequency band 1 = " << temp_max_buff_occ_freq_band_1 << " samples " << std::endl;
|
||||
std::cout << "maximum buffer occupancy frequency band 1 = " << max_buff_occ_freq_band_1 << " samples " << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32_t Fpga_buffer_monitor::buffer_monitor_test_register(void)
|
||||
{
|
||||
// write value to test register
|
||||
d_map_base[test_reg_addr] = test_register_writeval;
|
||||
// read value from test register
|
||||
uint32_t readval = d_map_base[test_reg_addr];
|
||||
|
||||
if (test_register_writeval != readval)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Fpga_buffer_monitor::close_device()
|
||||
{
|
||||
auto *aux = const_cast<unsigned *>(d_map_base);
|
||||
if (munmap(static_cast<void *>(aux), FPGA_PAGE_SIZE) == -1)
|
||||
{
|
||||
std::cout << "Failed to unmap memory uio\n";
|
||||
}
|
||||
|
||||
close(d_device_descriptor);
|
||||
}
|
||||
94
src/algorithms/signal_source/libs/fpga_buffer_monitor.h
Normal file
94
src/algorithms/signal_source/libs/fpga_buffer_monitor.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*!
|
||||
* \file fpga_buffer_monitor.h
|
||||
* \brief Check receiver buffer overflow and monitor the status of the receiver buffers.
|
||||
* \authors <ul>
|
||||
* <li> Marc Majoral, 2021. mmajoral(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* Class that checks the receiver buffer overflow flags and monitors the status of the receiver buffers.
|
||||
*
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_FPGA_BUFFER_MONITOR_H
|
||||
#define GNSS_SDR_FPGA_BUFFER_MONITOR_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
/** \addtogroup Signal_Source
|
||||
* \{ */
|
||||
/** \addtogroup Signal_Source_libs
|
||||
* \{ */
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Class that checks the receiver buffer overflow flags and monitors the status of the receiver buffers.
|
||||
*/
|
||||
class Fpga_buffer_monitor
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* \brief Constructor
|
||||
*/
|
||||
explicit Fpga_buffer_monitor(const std::string& device_name, uint32_t num_freq_bands);
|
||||
|
||||
/*!
|
||||
* \brief Destructor
|
||||
*/
|
||||
~Fpga_buffer_monitor();
|
||||
|
||||
/*!
|
||||
* \brief This function checks the status of the buffer overflow flags in the FPGA
|
||||
*/
|
||||
void check_buffer_overflow(void);
|
||||
|
||||
/*!
|
||||
* \brief This function monitors the FPGA buffer status
|
||||
*/
|
||||
void monitor_buffer_status(void);
|
||||
|
||||
private:
|
||||
static const size_t FPGA_PAGE_SIZE = 0x10000;
|
||||
static const uint32_t test_register_writeval = 0x55AA;
|
||||
static const uint32_t num_sapmples_per_buffer_element = 2;
|
||||
// write addresses
|
||||
static const uint32_t reset_overflow_flags_and_max_buff_size_reg_addr = 0;
|
||||
// read-write addresses
|
||||
static const uint32_t test_reg_addr = 7;
|
||||
// read addresses
|
||||
static const uint32_t current_buff_occ_freq_band_0_reg_addr = 0;
|
||||
static const uint32_t current_buff_occ_freq_band_1_reg_addr = 1;
|
||||
static const uint32_t max_buff_occ_freq_band_0_reg_addr = 2;
|
||||
static const uint32_t max_buff_occ_freq_band_1_reg_addr = 3;
|
||||
static const uint32_t overflow_flags_reg_addr = 4;
|
||||
// FPGA-related constants
|
||||
static const uint32_t overflow_freq_band_0_bit_pos = 1;
|
||||
static const uint32_t overflow_freq_band_1_bit_pos = 2;
|
||||
|
||||
int32_t buffer_monitor_test_register(void);
|
||||
void close_device(void);
|
||||
|
||||
volatile unsigned* d_map_base; // driver memory map corresponding to the FPGA buffer monitor
|
||||
int d_device_descriptor; // driver descriptor corresponding to the FPGA buffer monitor
|
||||
|
||||
uint32_t d_num_freq_bands;
|
||||
|
||||
uint32_t max_buff_occ_freq_band_0;
|
||||
uint32_t max_buff_occ_freq_band_1;
|
||||
};
|
||||
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
#endif // GNSS_SDR_FPGA_BUFFER_MONITOR_H
|
||||
Reference in New Issue
Block a user