Skip to content

Commit

Permalink
Use DVB-S2-specific AFF3CT codec on benchmarking
Browse files Browse the repository at this point in the history
- Replace the standard AFF3CT BCH codec with the DVB-S2 specific
  versions from the aff3ct/dvbs2 repository.
- Organize the AFF3CT BCH encoder and decoder into a static library, to
  which the bench_bch executable links.
- Move the GR-based BCH encoders and decoders to another static library
  and link the bench_bch executable to it.
- Since the AFF3CT DVB-S2-specific BCH decoder only supports hiho
  decoding (hard-in/hard-out), now all decoders effectively rely on hard
  decisions on the input. Hence, use a common slicing function to
  convert the LLRs output by the BPSK demodulator into hard decisions.
  Remove the slicing function from the GR BCH decoding functions and
  apply it before calling decode().

With this change, the AFF3CT-based BCH decoder becomes DVB-S2-compliant
and, hence, interoperable with the other encoder and decoder
implementations.
  • Loading branch information
igorauad committed Oct 25, 2023
1 parent 4f75df1 commit 2b51b75
Show file tree
Hide file tree
Showing 16 changed files with 314 additions and 99 deletions.
19 changes: 12 additions & 7 deletions bench/fec/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ find_package(Threads REQUIRED)

add_subdirectory(src)

list(APPEND bench_apps bench_plsc bench_bch)
add_executable(bench_plsc ${CMAKE_CURRENT_SOURCE_DIR}/src/bench_plsc.cc)
target_link_libraries(bench_plsc PRIVATE aff3ct::aff3ct-static-lib
boost_program_options gnuradio-dvbs2rx)
target_include_directories(bench_plsc
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/)

foreach(app IN LISTS bench_apps)
add_executable(${app} ${CMAKE_CURRENT_SOURCE_DIR}/src/${app}.cc)
target_link_libraries(
${app} PRIVATE aff3ct::aff3ct-static-lib boost_program_options
gnuradio-dvbs2rx gnuradio-dvbs2rx-bench)
endforeach(app IN LISTS bench_apps)
add_executable(bench_bch ${CMAKE_CURRENT_SOURCE_DIR}/src/bench_bch.cc)
target_link_libraries(
bench_bch PRIVATE aff3ct::aff3ct-static-lib boost_program_options
gnuradio-dvbs2rx gnuradio-bch-bench aff3ct-bch)
target_include_directories(
bench_bch PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/aff3ct_bch
${CMAKE_CURRENT_SOURCE_DIR}/src/gr_bch)
9 changes: 2 additions & 7 deletions bench/fec/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
list(APPEND bench_lib_sources gr_bch.cc)

add_library(gnuradio-dvbs2rx-bench SHARED ${bench_lib_sources})
target_include_directories(
gnuradio-dvbs2rx-bench
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../../lib>)
target_link_libraries(gnuradio-dvbs2rx-bench PRIVATE gnuradio-dvbs2rx)
add_subdirectory(aff3ct_bch)
add_subdirectory(gr_bch)
4 changes: 4 additions & 0 deletions bench/fec/src/aff3ct_bch/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
file(GLOB_RECURSE SRC_FILES_CO ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/*.hpp)
add_library(aff3ct-bch STATIC ${SRC_FILES_CO})
target_link_libraries(aff3ct-bch PRIVATE aff3ct::aff3ct-static-lib)
84 changes: 84 additions & 0 deletions bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <cmath>
#include <iostream>
#include <vector>

#include "Decoder_BCH_DVBS2.hpp"

using namespace aff3ct;
using namespace aff3ct::module;

template <typename B, typename R>
Decoder_BCH_DVBS2<B, R>::Decoder_BCH_DVBS2(
const int& K, const int& N, const tools::BCH_polynomial_generator<B>& GF_poly)
: Decoder_BCH_std<B, R>(K, N, GF_poly)
{
const std::string name = "Decoder_BCH_DVBS2";
this->set_name(name);
}

template <typename B, typename R>
Decoder_BCH_DVBS2<B, R>* Decoder_BCH_DVBS2<B, R>::clone() const
{
auto m = new Decoder_BCH_DVBS2(*this);
m->deep_copy(*this);
return m;
}

template <typename B, typename R>
int Decoder_BCH_DVBS2<B, R>::_decode_hiho(const B* Y_N,
int8_t* CWD,
B* V_K,
const size_t frame_id)
{
std::reverse_copy(Y_N, Y_N + this->N, this->YH_N.begin());

auto status = this->_decode(this->YH_N.data(), frame_id);

std::reverse_copy(
this->YH_N.data() + this->N - this->K, this->YH_N.data() + this->N, V_K);

CWD[0] = !status;
return status;
}

template <typename B, typename R>
int Decoder_BCH_DVBS2<B, R>::_decode_hiho_cw(const B* Y_N,
int8_t* CWD,
B* V_N,
const size_t frame_id)
{
throw tools::unimplemented_error(__FILE__, __LINE__, __func__);
}

template <typename B, typename R>
int Decoder_BCH_DVBS2<B, R>::_decode_siho(const R* Y_N,
int8_t* CWD,
B* V_K,
const size_t frame_id)
{
throw tools::unimplemented_error(__FILE__, __LINE__, __func__);
}

template <typename B, typename R>
int Decoder_BCH_DVBS2<B, R>::_decode_siho_cw(const R* Y_N,
int8_t* CWD,
B* V_N,
const size_t frame_id)
{
throw tools::unimplemented_error(__FILE__, __LINE__, __func__);
}


// ====================================================================================
// explicit template instantiation
#include "Tools/types.h"
#ifdef AFF3CT_MULTI_PREC
template class aff3ct::module::Decoder_BCH_DVBS2<B_8, Q_8>;
template class aff3ct::module::Decoder_BCH_DVBS2<B_16, Q_16>;
template class aff3ct::module::Decoder_BCH_DVBS2<B_32, Q_32>;
template class aff3ct::module::Decoder_BCH_DVBS2<B_64, Q_64>;
#else
template class aff3ct::module::Decoder_BCH_DVBS2<B, Q>;
#endif
// ====================================================================================
// explicit template instantiation
29 changes: 29 additions & 0 deletions bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef DECODER_BCH_DVBS2_HPP_
#define DECODER_BCH_DVBS2_HPP_

#include <aff3ct.hpp>

namespace aff3ct {
namespace module {
template <typename B = int, typename R = float>
class Decoder_BCH_DVBS2 : public Decoder_BCH_std<B, R>
{
public:
Decoder_BCH_DVBS2(const int& K,
const int& N,
const tools::BCH_polynomial_generator<B>& GF);

virtual ~Decoder_BCH_DVBS2() = default;

virtual Decoder_BCH_DVBS2<B, R>* clone() const;

protected:
virtual int _decode_hiho(const B* Y_N, int8_t* CWD, B* V_K, const size_t frame_id);
virtual int _decode_hiho_cw(const B* Y_N, int8_t* CWD, B* V_N, const size_t frame_id);
virtual int _decode_siho(const R* Y_N, int8_t* CWD, B* V_K, const size_t frame_id);
virtual int _decode_siho_cw(const R* Y_N, int8_t* CWD, B* V_N, const size_t frame_id);
};
} // namespace module
} // namespace aff3ct

#endif // DECODER_BCH_DVBS2_HPP_
56 changes: 56 additions & 0 deletions bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <cmath>
#include <iostream>
#include <vector>

#include "Encoder_BCH_DVBS2.hpp"

using namespace aff3ct;
using namespace aff3ct::module;

template <typename B>
Encoder_BCH_DVBS2<B>::Encoder_BCH_DVBS2(const int& K,
const int& N,
const tools::BCH_polynomial_generator<B>& GF_poly)
: Encoder_BCH<B>(K, N, GF_poly), U_K_rev(K)
{
const std::string name = "Encoder_BCH_DVBS2";
this->set_name(name);
}

template <typename B>
Encoder_BCH_DVBS2<B>* Encoder_BCH_DVBS2<B>::clone() const
{
auto m = new Encoder_BCH_DVBS2(*this);
m->deep_copy(*this);
return m;
}

template <typename B>
void Encoder_BCH_DVBS2<B>::_encode(const B* U_K, B* X_N, const size_t frame_id)
{
// reverse bits for DVBS2 standard to aff3ct compliance
std::reverse_copy(U_K, U_K + this->K, U_K_rev.begin());

// generate the parity bits
this->__encode(U_K_rev.data(), X_N);

// copy sys bits
std::copy(U_K_rev.data(), U_K_rev.data() + this->K, X_N + this->n_rdncy);

// reverse bits for DVBS2 standard to aff3ct compliance
std::reverse(X_N, X_N + this->K + this->n_rdncy);
}

// ====================================================================================
// explicit template instantiation
#include "Tools/types.h"
#ifdef AFF3CT_MULTI_PREC
template class aff3ct::module::Encoder_BCH_DVBS2<B_8>;
template class aff3ct::module::Encoder_BCH_DVBS2<B_16>;
template class aff3ct::module::Encoder_BCH_DVBS2<B_32>;
template class aff3ct::module::Encoder_BCH_DVBS2<B_64>;
#else
template class aff3ct::module::Encoder_BCH_DVBS2<B>;
#endif
// ====================================================================================
// explicit template instantiation
29 changes: 29 additions & 0 deletions bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef ENCODER_BCH_DVBS2_HPP_
#define ENCODER_BCH_DVBS2_HPP_

#include <aff3ct.hpp>

namespace aff3ct {
namespace module {
template <typename B = int>
class Encoder_BCH_DVBS2 : public Encoder_BCH<B>
{
protected:
std::vector<B> U_K_rev;

public:
Encoder_BCH_DVBS2(const int& K,
const int& N,
const tools::BCH_polynomial_generator<B>& GF);

virtual ~Encoder_BCH_DVBS2() = default;

virtual Encoder_BCH_DVBS2<B>* clone() const;

protected:
virtual void _encode(const B* U_K, B* X_N, const size_t frame_id);
};
} // namespace module
} // namespace aff3ct

#endif // ENCODER_BCH_DVBS2_HPP_
25 changes: 17 additions & 8 deletions bench/fec/src/bench_bch.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "Decoder_BCH_DVBS2.hpp"
#include "Encoder_BCH_DVBS2.hpp"
#include "gr_bch.h"
#include <aff3ct.hpp>
#include <boost/program_options.hpp>
Expand Down Expand Up @@ -43,7 +45,7 @@ struct BchEncoder {
int m_impl; // Decoder implementation
std::unique_ptr<gr::dvbs2::NewBchCodec> m_new_encoder;
std::unique_ptr<gr::dvbs2::GrBchEncoder> m_gr_encoder;
std::unique_ptr<module::Encoder_BCH<>> m_aff3ct_encoder;
std::unique_ptr<module::Encoder_BCH_DVBS2<>> m_aff3ct_encoder;
std::unique_ptr<tools::BCH_polynomial_generator<>> m_aff3ct_gen_poly;

public:
Expand All @@ -62,7 +64,7 @@ struct BchEncoder {
if (m_impl == AFF3CT_IMPL) {
set_aff3ct_gen_poly(N, t, m_aff3ct_gen_poly);
m_aff3ct_encoder.reset(
new module::Encoder_BCH<>(K, N, *m_aff3ct_gen_poly.get()));
new module::Encoder_BCH_DVBS2<>(K, N, *m_aff3ct_gen_poly.get()));
} else if (m_impl == GR_DVBS2RX_IMPL) {
m_gr_encoder.reset(new gr::dvbs2::GrBchEncoder(K, N, t));
} else if (m_impl == NEW_IMPL) {
Expand All @@ -89,8 +91,9 @@ struct BchDecoder {
int m_impl; // Decoder implementation
std::unique_ptr<gr::dvbs2::NewBchCodec> m_new_encoder;
std::unique_ptr<gr::dvbs2::GrBchDecoder> m_gr_decoder;
std::unique_ptr<module::Decoder_BCH_std<>> m_aff3ct_std_decoder;
std::unique_ptr<module::Decoder_BCH_DVBS2<>> m_aff3ct_std_decoder;
std::unique_ptr<tools::BCH_polynomial_generator<>> m_aff3ct_gen_poly;
std::vector<int> m_hard_dec;

public:
/**
Expand All @@ -101,12 +104,13 @@ struct BchDecoder {
* @param N Codeword length in bits.
* @param t Error correction capability.
*/
BchDecoder(int impl, int K, int N, int t) : m_impl(impl), m_K(K), m_N(N)
BchDecoder(int impl, int K, int N, int t)
: m_impl(impl), m_K(K), m_N(N), m_hard_dec(N)
{
if (m_impl == AFF3CT_IMPL) {
set_aff3ct_gen_poly(N, t, m_aff3ct_gen_poly);
m_aff3ct_std_decoder.reset(
new module::Decoder_BCH_std<>(K, N, *m_aff3ct_gen_poly.get()));
new module::Decoder_BCH_DVBS2<>(K, N, *m_aff3ct_gen_poly.get()));
} else if (m_impl == GR_DVBS2RX_IMPL) {
m_gr_decoder.reset(new gr::dvbs2::GrBchDecoder(K, N, t));
} else if (m_impl == NEW_IMPL) {
Expand All @@ -116,12 +120,17 @@ struct BchDecoder {

void decode(const std::vector<float>& llr_vec, std::vector<int>& dec_bits)
{
// Convert the LLR vector into hard decisions. Assume the BCH decoder would take
// hard decisions output by the LDPC decoder even though there is no LDPC block in
// this setup. Importantly, make the same assumption for all implementations.
tools::hard_decide(llr_vec.data(), m_hard_dec.data(), m_N);

if (m_impl == AFF3CT_IMPL) {
m_aff3ct_std_decoder->decode_siho(llr_vec, dec_bits);
m_aff3ct_std_decoder->decode_hiho(m_hard_dec, dec_bits);
} else if (m_impl == GR_DVBS2RX_IMPL) {
m_gr_decoder->decode(llr_vec, dec_bits);
m_gr_decoder->decode(m_hard_dec, dec_bits);
} else if (m_impl == NEW_IMPL) {
m_new_encoder->decode(llr_vec, dec_bits);
m_new_encoder->decode(m_hard_dec, dec_bits);
}
}
};
Expand Down
36 changes: 0 additions & 36 deletions bench/fec/src/bitman.hh

This file was deleted.

5 changes: 5 additions & 0 deletions bench/fec/src/gr_bch/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
list(APPEND gr_bch_sources gr_bch.cc)
add_library(gnuradio-bch-bench STATIC ${gr_bch_sources})
target_include_directories(gnuradio-bch-bench
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib)
target_link_libraries(gnuradio-bch-bench PRIVATE gnuradio-dvbs2rx)
6 changes: 6 additions & 0 deletions bench/fec/src/gr_bch/api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef INCLUDED_DVBS2_GR_BCH_BENCH_API_H
#define INCLUDED_DVBS2_GR_BCH_BENCH_API_H

#define DVBS2_GR_BCH_BENCH_API __attribute__((visibility("default")))

#endif /* INCLUDED_DVBS2_GR_BCH_BENCH_API_H */
Loading

0 comments on commit 2b51b75

Please sign in to comment.