1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-06-24 05:53:16 +00:00

The sample counter, the Acquisition and the Switch determine the uio device file that is assigned to them using the hardware accelerator device name in the FPGA

This commit is contained in:
Marc Majoral 2020-11-26 17:07:15 +01:00
parent 15c1f907bf
commit a53109c718
22 changed files with 294 additions and 32 deletions

View File

@ -129,6 +129,10 @@ if(ENABLE_FPGA)
Volk::volk
Volkgnsssdr::volkgnsssdr
)
target_include_directories(acquisition_adapters
PUBLIC
${CMAKE_SOURCE_DIR}/src/core/libs
)
endif()
target_include_directories(acquisition_adapters

View File

@ -24,6 +24,7 @@
#include "galileo_e1_signal_replica.h"
#include "gnss_sdr_flags.h"
#include "gnss_sdr_make_unique.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -77,11 +78,19 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
float nbits = ceilf(log2f(static_cast<float>(code_length) * 2.0F));
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration->property(role + ".select_queue_Fpga", 0);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
// UIO device file
std::string device_io_name;
std::string device_name = configuration->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
// find the uio device file corresponding to the GNSS reset module
if (find_uio_dev_file_name(device_io_name, device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GALILEO_E1_CODE_CHIP_RATE_CPS) * static_cast<float>(fs_in)));

View File

@ -183,6 +183,8 @@ public:
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
const std::string default_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -24,6 +24,7 @@
#include "galileo_e5_signal_replica.h"
#include "gnss_sdr_flags.h"
#include "gnss_sdr_make_unique.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -80,11 +81,19 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration->property(role + ".select_queue_Fpga", 1);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
std::string device_name = configuration->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
acq_parameters.samples_per_code = nsamples_total;
// UIO device file
std::string device_io_name;
std::string device_name = configuration->property(role + ".devicename", default_device_name);
// find the uio device file corresponding to the GNSS reset module
if (find_uio_dev_file_name(device_io_name, device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GALILEO_E5A_CODE_CHIP_RATE_CPS) * static_cast<float>(fs_in)));
// compute all the GALILEO E5 PRN Codes (this is done only once in the class constructor in order to avoid re-computing the PRN codes every time

View File

@ -191,6 +191,8 @@ public:
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
const std::string default_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -24,6 +24,7 @@
#include "configuration_interface.h"
#include "galileo_e5_signal_replica.h"
#include "gnss_sdr_flags.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -79,11 +80,19 @@ GalileoE5bPcpsAcquisitionFpga::GalileoE5bPcpsAcquisitionFpga(const Configuration
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration->property(role + ".select_queue_Fpga", 1);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
std::string device_name = configuration->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
acq_parameters.samples_per_code = nsamples_total;
// UIO device file
std::string device_io_name;
std::string device_name = configuration->property(role + ".devicename", default_device_name);
// find the uio device file corresponding to the GNSS reset module
if (find_uio_dev_file_name(device_io_name, device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GALILEO_E5B_CODE_CHIP_RATE_CPS) * static_cast<float>(fs_in)));
// compute all the GALILEO E5b PRN Codes (this is done only once in the class constructor in order to avoid re-computing the PRN codes every time

View File

@ -190,6 +190,9 @@ public:
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
const std::string default_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -27,6 +27,7 @@
#include "gnss_sdr_flags.h"
#include "gnss_sdr_make_unique.h"
#include "gps_sdr_signal_replica.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h>
#include <gnuradio/gr_complex.h> // for gr_complex
@ -72,9 +73,18 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration->property(role + ".select_queue_Fpga", 0);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
// UIO device file
std::string device_io_name;
std::string device_name = configuration->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
// find the uio device file corresponding to the GNSS reset module
if (find_uio_dev_file_name(device_io_name, device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil(GPS_L1_CA_CHIP_PERIOD_S * static_cast<float>(fs_in)));

View File

@ -187,6 +187,8 @@ public:
private:
static const uint32_t NUM_PRNs = 32;
const std::string default_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -27,6 +27,7 @@
#include "gnss_sdr_make_unique.h"
#include "gnss_synchro.h"
#include "gps_l2c_signal_replica.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -70,11 +71,19 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
unsigned int nsamples_total = pow(2, nbits);
unsigned int select_queue_Fpga = configuration->property(role + ".select_queue_Fpga", 0);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
std::string device_name = configuration->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
acq_parameters.samples_per_code = nsamples_total;
// UIO device file
std::string device_io_name;
std::string device_name = configuration->property(role + ".devicename", default_device_name);
// find the uio device file corresponding to the GNSS reset module
if (find_uio_dev_file_name(device_io_name, device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.downsampling_factor = configuration->property(role + ".downsampling_factor", 1.0);
acq_parameters.total_block_exp = configuration->property(role + ".total_block_exp", 14);
acq_parameters.excludelimit = static_cast<uint32_t>(std::round(static_cast<double>(fs_in_) / GPS_L2_M_CODE_RATE_CPS));

View File

@ -151,6 +151,8 @@ public:
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
const std::string default_device_name = "acquisition_S00_AXI"; // UIO device name
static const uint32_t NUM_PRNs = 32;
static const uint32_t QUANT_BITS_LOCAL_CODE = 16;
static const uint32_t SELECT_LSBits = 0x0000FFFF; // Select the 10 LSbits out of a 20-bit word

View File

@ -27,6 +27,7 @@
#include "gnss_sdr_flags.h"
#include "gnss_sdr_make_unique.h"
#include "gps_l5_signal_replica.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/fft/fft.h> // for fft_complex
#include <gnuradio/gr_complex.h> // for gr_complex
@ -76,11 +77,19 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration->property(role + ".select_queue_Fpga", 1);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
std::string device_name = configuration->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
acq_parameters.samples_per_code = nsamples_total;
// UIO device file
std::string device_io_name;
std::string device_name = configuration->property(role + ".devicename", default_device_name);
// find the uio device file corresponding to the GNSS reset module
if (find_uio_dev_file_name(device_io_name, device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
acq_parameters.device_name = device_io_name;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GPS_L5I_CODE_RATE_CPS) * static_cast<float>(fs_in)));
// compute all the GPS L5 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time

View File

@ -187,6 +187,8 @@ public:
private:
static const uint32_t NUM_PRNs = 32;
const std::string default_device_name = "acquisition_S00_AXI"; // UIO device name
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
static const uint32_t quant_bits_local_code = 16;

View File

@ -146,6 +146,13 @@ target_include_directories(signal_source_adapters
${CMAKE_SOURCE_DIR}/src/core/interfaces
)
if(ENABLE_FPGA)
target_include_directories(signal_source_adapters
PUBLIC
${CMAKE_SOURCE_DIR}/src/core/libs
)
endif()
target_link_libraries(signal_source_adapters
PUBLIC
Boost::headers

View File

@ -28,6 +28,7 @@
#include "ad9361_manager.h"
#include "configuration_interface.h"
#include "gnss_sdr_flags.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <iio.h>
#include <algorithm> // for max
@ -90,9 +91,17 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
rf_shutdown_ = configuration->property(role + ".rf_shutdown", FLAGS_rf_shutdown);
// turn switch to A/D position
const std::string default_device_name("/dev/uio1");
const std::string device_name = configuration->property(role + ".devicename", default_device_name);
// Switch UIO device file
std::string device_io_name;
std::string device_name = configuration->property(role + ".devicename", default_device_name);
// find the uio device file corresponding to the GNSS reset module
if (find_uio_dev_file_name(device_io_name, device_name, 0) < 0)
{
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
switch_position = configuration->property(role + ".switch_position", 0);
if (switch_position != 0 && switch_position != 2)
{
@ -101,7 +110,7 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
switch_position = 0;
}
switch_fpga = std::make_shared<Fpga_Switch>(device_name);
switch_fpga = std::make_shared<Fpga_Switch>(device_io_name);
switch_fpga->set_switch_position(switch_position);
item_size_ = sizeof(gr_complex);

View File

@ -76,6 +76,8 @@ public:
gr::basic_block_sptr get_right_block() override;
private:
const std::string default_device_name = "AXIS_Switch_v1_0_0"; // Switch UIO device name
// perform dynamic bit selection every 500 ms by default
static const uint32_t Gain_control_period_ms = 500;

View File

@ -109,6 +109,14 @@ target_include_directories(tracking_adapters
${CMAKE_SOURCE_DIR}/src/core/interfaces
)
if(ENABLE_FPGA)
target_include_directories(tracking_adapters
PUBLIC
${CMAKE_SOURCE_DIR}/src/core/libs
)
endif()
if(ENABLE_CUDA)
if(CMAKE_VERSION VERSION_GREATER 3.11)
target_include_directories(tracking_adapters

View File

@ -36,11 +36,13 @@ if(ENABLE_FPGA)
${CORE_LIBS_SOURCES}
gnss_sdr_fpga_sample_counter.cc
gnss_sdr_time_counter.cc
uio_fpga.cc
)
set(CORE_LIBS_HEADERS
${CORE_LIBS_HEADERS}
gnss_sdr_fpga_sample_counter.h
gnss_sdr_time_counter.h
uio_fpga.h
)
endif()

View File

@ -21,6 +21,7 @@
#include "gnss_sdr_fpga_sample_counter.h"
#include "gnss_synchro.h"
#include "uio_fpga.h"
#include <glog/logging.h>
#include <gnuradio/io_signature.h>
#include <pmt/pmt.h> // for from_double
@ -132,11 +133,20 @@ void gnss_sdr_fpga_sample_counter::configure_samples_per_output(uint32_t interva
void gnss_sdr_fpga_sample_counter::open_device()
{
// open communication with HW accelerator
if ((fd = open(device_name.c_str(), O_RDWR | O_SYNC)) == -1)
// UIO device file
std::string device_io_name;
// find the uio device file corresponding to the GNSS reset module
if (find_uio_dev_file_name(device_io_name, device_name, 0) < 0)
{
LOG(WARNING) << "Cannot open deviceio" << device_name;
std::cout << "Counter-Intr: cannot open deviceio" << device_name << '\n';
std::cout << "Cannot find the FPGA uio device file corresponding to device name " << device_name << std::endl;
throw std::exception();
}
// open communication with HW accelerator
if ((fd = open(device_io_name.c_str(), O_RDWR | O_SYNC)) == -1)
{
LOG(WARNING) << "Cannot open deviceio" << device_io_name;
std::cout << "Counter-Intr: cannot open deviceio" << device_io_name << '\n';
}
map_base = reinterpret_cast<volatile uint32_t *>(mmap(nullptr, page_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
@ -144,7 +154,7 @@ void gnss_sdr_fpga_sample_counter::open_device()
if (map_base == reinterpret_cast<void *>(-1))
{
LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory";
std::cout << "Counter-Intr: cannot map deviceio" << device_name << '\n';
std::cout << "Counter-Intr: cannot map deviceio" << device_io_name << '\n';
}
// sanity check : check test register

View File

@ -50,6 +50,8 @@ public:
gr_vector_void_star &output_items);
private:
const std::string device_name = "counter"; // UIO device name
static const uint32_t page_size = 0x10000; // default page size for the multicorrelator memory map
static const uint32_t test_reg_sanity_check = 0x55AA; // value to check the presence of the test register (to detect the hw)
@ -63,8 +65,7 @@ private:
bool stop();
void wait_for_interrupt(void);
volatile uint32_t *map_base; // driver memory map
std::string device_name = "/dev/uio2"; // HW device name
volatile uint32_t *map_base; // driver memory map
double fs;
uint64_t sample_counter;

115
src/core/libs/uio_fpga.cc Normal file
View File

@ -0,0 +1,115 @@
/*!
* \file uio_fpga.cc
* \brief This library contains functions to determine the uio device driver file that
* corresponds to a hardware accelerator device name in the FPGA
* \author Marc Majoral, 2020. mmajoral(at)cttc.es
*
* -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "uio_fpga.h"
#include <dirent.h> // scandir()
#include <fstream> // ifstream
#include <iostream> // cout
#include <sstream> // std::stringstream
int32_t get_uio_num(std::string uio_name)
{
size_t i = 0;
// search first digit
for (; i < uio_name.length(); i++)
{
if (isdigit(uio_name[i])) break;
}
// remove the first chars, which aren't digits
std::string uio_num = uio_name.substr(i, uio_name.length() - i);
// convert the remaining text to an integer
return atoi(uio_num.c_str());
}
void get_uio_name(uint32_t uio_num, std::string &uio_name)
{
std::stringstream filename;
filename << uio_dir << uio_filename << uio_num << uio_subdir_name;
std::ifstream infile;
infile.open(filename.str());
if (infile.is_open())
{
getline(infile, uio_name);
if (infile.bad())
{
std::cout << "Could not read the FPGA uio device information file" << std::endl;
throw std::exception();
}
infile.close();
}
else
{
std::cout << "Could not open the FPGA uio device information file" << std::endl;
throw std::exception();
}
}
int32_t find_uio_num(const std::string &device_name, uint32_t device_num)
{
struct dirent **files;
int32_t uio_num;
// get the number of directory entries in the uio driver description system directories
uint32_t num_dir_entries = scandir(uio_dir.c_str(), &files, 0, versionsort);
uint32_t device_count = 0, uio_count = 0;
// search for the requested device driver
while (device_count < num_dir_entries)
{
// get the uio number corresponding to directory entry n
uio_num = get_uio_num(files[device_count]->d_name);
if (uio_num >= 0) // valid uio number
{
std::string nametemp;
get_uio_name(uio_num, nametemp);
if (device_name.compare(nametemp) == 0)
{
if (uio_count == device_num)
{
return uio_num;
}
else
{
uio_count++;
}
}
}
device_count++;
}
return -1; // uio number not found
}
int32_t find_uio_dev_file_name(std::string &device_file_name, const std::string &device_name, uint32_t device_num)
{
int32_t uio_num = find_uio_num(device_name, device_num);
if (uio_num >= 0)
{
std::stringstream device_file_name_tmp;
device_file_name_tmp << "/dev/uio" << uio_num;
device_file_name = device_file_name_tmp.str();
return 0;
}
return -1;
}

36
src/core/libs/uio_fpga.h Normal file
View File

@ -0,0 +1,36 @@
/*!
* \file uio_fpga.h
* \brief This library contains functions to determine the uio device driver file that
* corresponds to a hardware accelerator device name in the FPGA
* \author Marc Majoral, 2020. mmajoral(at)cttc.es
*
* -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_SIM_GNSS_UIO_FPGA_H
#define GNSS_SDR_SIM_GNSS_UIO_FPGA_H
#include <string> // string, memset()
const std::string uio_dir = "/sys/class/uio/";
const std::string uio_filename = "uio";
const std::string uio_subdir_name = "/name";
/*!
* \brief This function finds the uio device driver device file name out of the device name and the device number
*/
int32_t find_uio_dev_file_name(std::string &device_file_name, const std::string &device_name, uint32_t device_num);
#endif // GNSS_SDR_GNSS_UIO_FPGA_H