mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-11-04 09:13:05 +00:00 
			
		
		
		
	real-time FPGA receiver buffer monitoring
This commit is contained in:
		@@ -98,22 +98,24 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
 | 
				
			|||||||
            throw std::exception();
 | 
					            throw std::exception();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch_position = configuration->property(role + ".switch_position", 0);
 | 
					    switch_position_ = configuration->property(role + ".switch_position", 0);
 | 
				
			||||||
    if (switch_position != 0 && switch_position != 2)
 | 
					    if (switch_position_ != 0 && switch_position_ != 2)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::cout << "SignalSource.switch_position configuration parameter must be either 0: read from file(s) via DMA, or 2: read from AD9361\n";
 | 
					            std::cout << "SignalSource.switch_position configuration parameter must be either 0: read from file(s) via DMA, or 2: read from AD9361\n";
 | 
				
			||||||
            std::cout << "SignalSource.switch_position configuration parameter set to its default value switch_position=0 - read from file(s)\n";
 | 
					            std::cout << "SignalSource.switch_position configuration parameter set to its default value switch_position=0 - read from file(s)\n";
 | 
				
			||||||
            switch_position = 0;
 | 
					            switch_position_ = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch_fpga = std::make_shared<Fpga_Switch>(device_io_name);
 | 
					    switch_fpga = std::make_shared<Fpga_Switch>(device_io_name);
 | 
				
			||||||
    switch_fpga->set_switch_position(switch_position);
 | 
					    switch_fpga->set_switch_position(switch_position_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    item_size_ = sizeof(gr_complex);
 | 
					    item_size_ = sizeof(gr_complex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::cout << "Sample rate: " << sample_rate_ << " Sps\n";
 | 
					    std::cout << "Sample rate: " << sample_rate_ << " Sps\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (switch_position == 0)  // Inject file(s) via DMA
 | 
					    enable_ovf_check_buffer_monitor_ = 0;  // check buffer overflow and buffer monitor disabled by default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (switch_position_ == 0)  // Inject file(s) via DMA
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            enable_DMA_ = true;
 | 
					            enable_DMA_ = true;
 | 
				
			||||||
            const std::string empty_string;
 | 
					            const std::string empty_string;
 | 
				
			||||||
@@ -154,7 +156,7 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
 | 
				
			|||||||
                    freq_band = "L1L2";
 | 
					                    freq_band = "L1L2";
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    if (switch_position == 2)  // Real-time via AD9361
 | 
					    if (switch_position_ == 2)  // Real-time via AD9361
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // some basic checks
 | 
					            // some basic checks
 | 
				
			||||||
            if ((rf_port_select_ != "A_BALANCED") and (rf_port_select_ != "B_BALANCED") and (rf_port_select_ != "A_N") and (rf_port_select_ != "B_N") and (rf_port_select_ != "B_P") and (rf_port_select_ != "C_N") and (rf_port_select_ != "C_P") and (rf_port_select_ != "TX_MONITOR1") and (rf_port_select_ != "TX_MONITOR2") and (rf_port_select_ != "TX_MONITOR1_2"))
 | 
					            if ((rf_port_select_ != "A_BALANCED") and (rf_port_select_ != "B_BALANCED") and (rf_port_select_ != "A_N") and (rf_port_select_ != "B_N") and (rf_port_select_ != "B_P") and (rf_port_select_ != "C_N") and (rf_port_select_ != "C_P") and (rf_port_select_ != "TX_MONITOR1") and (rf_port_select_ != "TX_MONITOR2") and (rf_port_select_ != "TX_MONITOR1_2"))
 | 
				
			||||||
@@ -292,6 +294,23 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
 | 
				
			|||||||
                            std::cout << "Exception cached when configuring the TX carrier: " << e.what() << '\n';
 | 
					                            std::cout << "Exception cached when configuring the TX carrier: " << e.what() << '\n';
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // when the receiver is working in real-time mode via AD9361 perform buffer overflow checking and buffer monitoring
 | 
				
			||||||
 | 
					            enable_ovf_check_buffer_monitor_ = 1;
 | 
				
			||||||
 | 
					            enable_buffer_monitor_ = configuration->property(role + ".enable_buffer_monitor", false);  // only buffer overflow checking by default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::string device_io_name_buffer_monitor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // find the uio device file corresponding to the buffer monitor
 | 
				
			||||||
 | 
					            if (find_uio_dev_file_name(device_io_name_buffer_monitor, buffer_monitor_device_name, 0) < 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    std::cout << "Cannot find the FPGA uio device file corresponding to device name " << buffer_monitor_device_name << std::endl;
 | 
				
			||||||
 | 
					                    throw std::exception();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            uint32_t num_freq_bands = (freq_band.compare("L1L2")) ? 1 : 2;
 | 
				
			||||||
 | 
					            buffer_monitor_fpga = std::make_shared<Fpga_buffer_monitor>(device_io_name_buffer_monitor, num_freq_bands);
 | 
				
			||||||
 | 
					            thread_buffer_monitor = std::thread([&] { run_buffer_monitor_process(); });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // dynamic bits selection
 | 
					    // dynamic bits selection
 | 
				
			||||||
@@ -331,7 +350,7 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
 | 
				
			|||||||
Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource()
 | 
					Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* cleanup and exit */
 | 
					    /* cleanup and exit */
 | 
				
			||||||
    if (switch_position == 0)  // read samples from a file via DMA
 | 
					    if (switch_position_ == 0)  // read samples from a file via DMA
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::unique_lock<std::mutex> lock(dma_mutex);
 | 
					            std::unique_lock<std::mutex> lock(dma_mutex);
 | 
				
			||||||
            enable_DMA_ = false;  // disable the DMA
 | 
					            enable_DMA_ = false;  // disable the DMA
 | 
				
			||||||
@@ -342,7 +361,7 @@ Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource()
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (switch_position == 2)  // Real-time via AD9361
 | 
					    if (switch_position_ == 2)  // Real-time via AD9361
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (rf_shutdown_)
 | 
					            if (rf_shutdown_)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@@ -363,6 +382,16 @@ Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource()
 | 
				
			|||||||
                                }
 | 
					                                }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // disable buffer overflow checking and buffer monitoring
 | 
				
			||||||
 | 
					            std::unique_lock<std::mutex> lock(buffer_monitor_mutex);
 | 
				
			||||||
 | 
					            enable_ovf_check_buffer_monitor_ = false;
 | 
				
			||||||
 | 
					            lock.unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (thread_buffer_monitor.joinable())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    thread_buffer_monitor.join();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::unique_lock<std::mutex> lock(dynamic_bit_selection_mutex);
 | 
					    std::unique_lock<std::mutex> lock(dynamic_bit_selection_mutex);
 | 
				
			||||||
@@ -646,6 +675,29 @@ void Ad9361FpgaSignalSource::run_dynamic_bit_selection_process()
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Ad9361FpgaSignalSource::run_buffer_monitor_process()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    bool enable_ovf_check_buffer_monitor_active = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitoring_initial_delay_ms));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while (enable_ovf_check_buffer_monitor_active)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            buffer_monitor_fpga->check_buffer_overflow();
 | 
				
			||||||
 | 
					            if (enable_buffer_monitor_)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    buffer_monitor_fpga->monitor_buffer_status();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            std::this_thread::sleep_for(std::chrono::milliseconds(buffer_monitor_period_ms));
 | 
				
			||||||
 | 
					            std::unique_lock<std::mutex> lock(buffer_monitor_mutex);
 | 
				
			||||||
 | 
					            if (enable_ovf_check_buffer_monitor_ == false)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    enable_ovf_check_buffer_monitor_active = false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            lock.unlock();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Ad9361FpgaSignalSource::connect(gr::top_block_sptr top_block)
 | 
					void Ad9361FpgaSignalSource::connect(gr::top_block_sptr top_block)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@
 | 
				
			|||||||
#define GNSS_SDR_AD9361_FPGA_SIGNAL_SOURCE_H
 | 
					#define GNSS_SDR_AD9361_FPGA_SIGNAL_SOURCE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "concurrent_queue.h"
 | 
					#include "concurrent_queue.h"
 | 
				
			||||||
 | 
					#include "fpga_buffer_monitor.h"
 | 
				
			||||||
#include "fpga_dynamic_bit_selection.h"
 | 
					#include "fpga_dynamic_bit_selection.h"
 | 
				
			||||||
#include "fpga_switch.h"
 | 
					#include "fpga_switch.h"
 | 
				
			||||||
#include "gnss_block_interface.h"
 | 
					#include "gnss_block_interface.h"
 | 
				
			||||||
@@ -74,22 +75,30 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    const std::string switch_device_name = "AXIS_Switch_v1_0_0";          // Switch UIO device name
 | 
					    const std::string switch_device_name = "AXIS_Switch_v1_0_0";          // Switch UIO device name
 | 
				
			||||||
    const std::string dyn_bit_sel_device_name = "dynamic_bits_selector";  // Switch UIO device name
 | 
					    const std::string dyn_bit_sel_device_name = "dynamic_bits_selector";  // Switch dhnamic bit selector device name
 | 
				
			||||||
 | 
					    const std::string buffer_monitor_device_name = "buffer_monitor";      // buffer monitor device name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // perform dynamic bit selection every 500 ms by default
 | 
					    // perform dynamic bit selection every 500 ms by default
 | 
				
			||||||
    static const uint32_t Gain_control_period_ms = 500;
 | 
					    static const uint32_t Gain_control_period_ms = 500;
 | 
				
			||||||
 | 
					    // check buffer overflow and perform buffer monitoring every 1s by default
 | 
				
			||||||
 | 
					    static const uint32_t buffer_monitor_period_ms = 1000;
 | 
				
			||||||
 | 
					    // buffer overflow and buffer monitoring initial delay
 | 
				
			||||||
 | 
					    static const uint32_t buffer_monitoring_initial_delay_ms = 2000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void run_DMA_process(const std::string &FreqBand,
 | 
					    void run_DMA_process(const std::string &FreqBand,
 | 
				
			||||||
        const std::string &Filename1,
 | 
					        const std::string &Filename1,
 | 
				
			||||||
        const std::string &Filename2);
 | 
					        const std::string &Filename2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void run_dynamic_bit_selection_process();
 | 
					    void run_dynamic_bit_selection_process();
 | 
				
			||||||
 | 
					    void run_buffer_monitor_process();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::thread thread_file_to_dma;
 | 
					    std::thread thread_file_to_dma;
 | 
				
			||||||
    std::thread thread_dynamic_bit_selection;
 | 
					    std::thread thread_dynamic_bit_selection;
 | 
				
			||||||
 | 
					    std::thread thread_buffer_monitor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<Fpga_Switch> switch_fpga;
 | 
					    std::shared_ptr<Fpga_Switch> switch_fpga;
 | 
				
			||||||
    std::shared_ptr<Fpga_dynamic_bit_selection> dynamic_bit_selection_fpga;
 | 
					    std::shared_ptr<Fpga_dynamic_bit_selection> dynamic_bit_selection_fpga;
 | 
				
			||||||
 | 
					    std::shared_ptr<Fpga_buffer_monitor> buffer_monitor_fpga;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string role_;
 | 
					    std::string role_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -106,6 +115,7 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    std::mutex dma_mutex;
 | 
					    std::mutex dma_mutex;
 | 
				
			||||||
    std::mutex dynamic_bit_selection_mutex;
 | 
					    std::mutex dynamic_bit_selection_mutex;
 | 
				
			||||||
 | 
					    std::mutex buffer_monitor_mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double rf_gain_rx1_;
 | 
					    double rf_gain_rx1_;
 | 
				
			||||||
    double rf_gain_rx2_;
 | 
					    double rf_gain_rx2_;
 | 
				
			||||||
@@ -125,7 +135,7 @@ private:
 | 
				
			|||||||
    size_t item_size_;
 | 
					    size_t item_size_;
 | 
				
			||||||
    uint32_t in_stream_;
 | 
					    uint32_t in_stream_;
 | 
				
			||||||
    uint32_t out_stream_;
 | 
					    uint32_t out_stream_;
 | 
				
			||||||
    int32_t switch_position;
 | 
					    int32_t switch_position_;
 | 
				
			||||||
    bool enable_dds_lo_;
 | 
					    bool enable_dds_lo_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool filter_auto_;
 | 
					    bool filter_auto_;
 | 
				
			||||||
@@ -136,6 +146,8 @@ private:
 | 
				
			|||||||
    bool rx2_enable_;
 | 
					    bool rx2_enable_;
 | 
				
			||||||
    bool enable_DMA_;
 | 
					    bool enable_DMA_;
 | 
				
			||||||
    bool enable_dynamic_bit_selection_;
 | 
					    bool enable_dynamic_bit_selection_;
 | 
				
			||||||
 | 
					    bool enable_buffer_monitor_;
 | 
				
			||||||
 | 
					    bool enable_ovf_check_buffer_monitor_;
 | 
				
			||||||
    bool rf_shutdown_;
 | 
					    bool rf_shutdown_;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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_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_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_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()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(SIGNAL_SOURCE_LIB_SOURCES
 | 
					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