Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to set up a basic Reed-Solomon encoder/decoder by using the bootstrap example #20

Open
LiangJunqiang opened this issue Dec 20, 2023 · 0 comments

Comments

@LiangJunqiang
Copy link

I'm trying to work with the aff3ct Reed-Solomon codec, and here's the code I modified:

#include <iostream>
#include <memory>
#include <vector>
#include <string>

#include <aff3ct.hpp>
#include "cxxopts.hpp"

using namespace aff3ct;


struct params
{
	int   K         ; // number of information bits
	int   N         ; // codeword size
	int   fe        ; // number of frame errors
	int   seed      ; // PRNG seed for the AWGN channel
	float ebn0_min  ; // minimum SNR value
	float ebn0_max  ; // maximum SNR value
	float ebn0_step ; // SNR step
	float R         ; // code rate (R=K/N)
};

struct modules
{
	std::unique_ptr<module::Source_random<>>          source;
	std::unique_ptr<module::Encoder_RS<>> 		      encoder;
	std::unique_ptr<module::Modem_BPSK<>>             modem;
	std::unique_ptr<module::Channel_AWGN_LLR<>>       channel;
	std::unique_ptr<module::Decoder_RS_std<>>         decoder;
	std::unique_ptr<module::Monitor_BFER<>>           monitor;
};

struct buffers
{
	std::vector<int  > ref_bits;
	std::vector<bool > frozen_bits;
	std::vector<int  > enc_bits;
	std::vector<float> symbols;
	std::vector<float> sigma;
	std::vector<float> noisy_symbols;
	std::vector<float> LLRs;
	std::vector<int  > dec_bits;
};

struct utils
{
	std::unique_ptr<tools::Sigma<>>               noise;     // a sigma noise type
	std::vector<std::unique_ptr<tools::Reporter>> reporters; // list of reporters dispayed in the terminal
	std::unique_ptr<tools::Terminal_std>          terminal;  // manage the output text in the terminal
};

void init_params(params &p, cxxopts::ParseResult &opts)
{
	p.K         = opts["k"].as<int> ();
	p.N         = opts["n"].as<int> ();
	p.fe        = opts["fe"].as<int> ();
	p.seed      = opts["seed"].as<int> ();
	p.ebn0_min  = opts["ebn0min"].as<float> ();
	p.ebn0_max  = opts["ebn0max"].as<float> ();
	p.ebn0_step = opts["ebn0step"].as<float> ();
	if (opts.count("r"))
	{
		p.R = opts["r"].as<float> ();
		p.K = (int) (p.N * 1.0 * p.R);
	}
	else
	{
		p.R = (float)p.K / (float)p.N;
	}
	
	std::cout << "# * Simulation parameters: "              << std::endl;
	std::cout << "#    ** Frame errors   = " << p.fe        << std::endl;
	std::cout << "#    ** Noise seed     = " << p.seed      << std::endl;
	std::cout << "#    ** Info. bits (K) = " << p.K         << std::endl;
	std::cout << "#    ** Frame size (N) = " << p.N         << std::endl;
	std::cout << "#    ** Code rate  (R) = " << p.R         << std::endl;
	std::cout << "#    ** SNR min   (dB) = " << p.ebn0_min  << std::endl;
	std::cout << "#    ** SNR max   (dB) = " << p.ebn0_max  << std::endl;
	std::cout << "#    ** SNR step  (dB) = " << p.ebn0_step << std::endl;
	std::cout << "#"                                        << std::endl;
}

void init_modules(const params &p, modules &m)
{
	/**
	 * N=2^m-1 and N <= 1048575, N+1 > K + 2t
	*/
    tools::RS_polynomial_generator pg{(1 << (int)std::ceil(std::log2(p.N))) - 1, (p.N - p.K) / 2};
	m.source  = std::unique_ptr<module::Source_random         <>>(new module::Source_random         <>(p.K         ));
	m.encoder = std::unique_ptr<module::Encoder_RS            <>>(new module::Encoder_RS            <>(p.K, p.N, pg));
	m.modem   = std::unique_ptr<module::Modem_BPSK            <>>(new module::Modem_BPSK            <>(p.N         ));
#if AFF3CT_VERSION==2
	m.channel = std::unique_ptr<module::Channel_AWGN_LLR      <>>(new module::Channel_AWGN_LLR      <>(p.N, p.seed ));
#elif AFF3CT_VERSION==3
	m.channel = std::unique_ptr<module::Channel_AWGN_LLR      <>>(new module::Channel_AWGN_LLR      <>(p.N         ));
#endif
	m.decoder = std::unique_ptr<module::Decoder_RS_std        <>>(new module::Decoder_RS_std        <>(p.K, p.N, pg));
	m.monitor = std::unique_ptr<module::Monitor_BFER          <>>(new module::Monitor_BFER          <>(p.K, p.fe   ));
};

void init_buffers(const params &p, buffers &b)
{
	b.ref_bits      = std::vector<int  >(p.K);
	b.enc_bits      = std::vector<int  >(p.N);
	b.symbols       = std::vector<float>(p.N);
#if AFF3CT_VERSION==3
	b.sigma         = std::vector<float>(  1);
#endif
	b.noisy_symbols = std::vector<float>(p.N);
	b.LLRs          = std::vector<float>(p.N);
	b.dec_bits      = std::vector<int  >(p.K);
}

void init_utils(const modules &m, utils &u)
{
	// create a sigma noise type
	u.noise = std::unique_ptr<tools::Sigma<>>(new tools::Sigma<>());
	// report the noise values (Es/N0 and Eb/N0)
	u.reporters.push_back(std::unique_ptr<tools::Reporter>(new tools::Reporter_noise<>(*u.noise)));
	// report the bit/frame error rates
	u.reporters.push_back(std::unique_ptr<tools::Reporter>(new tools::Reporter_BFER<>(*m.monitor)));
	// report the simulation throughputs
	u.reporters.push_back(std::unique_ptr<tools::Reporter>(new tools::Reporter_throughput<>(*m.monitor)));
	// create a terminal that will display the collected data from the reporters
	u.terminal = std::unique_ptr<tools::Terminal_std>(new tools::Terminal_std(u.reporters));
}

template <typename T> void print_vector(std::vector<T> vec) {
  std::for_each(vec.begin(), vec.end(),
                [&](const auto i) { std::cout << i << ' '; });
  std::cout << std::endl;
}

int main(int argc, char** argv)
{
	// parse the command line options
    cxxopts::Options options(argv[0], "A Reed-Solomon Code Codec Simlator");
    options.positional_help("[optional args]").show_positional_help();

    options.allow_unrecognised_options().add_options()
		("k,linfo", "The number of information bits", cxxopts::value<int>()->default_value("400"), "k")
		("n,lcode", "The codeword size", cxxopts::value<int>()->default_value("512"), "n")
		("r,coderate", "The code rate. If this presents, k is ignored.", cxxopts::value<float>()->default_value("0.8"), "r")
		("fe", "The number of frame error", cxxopts::value<int>()->default_value("100"), "fe")
		("seed", "Pseudorandom generator seed", cxxopts::value<int>()->default_value("0"), "seed")
		("ebn0min", "The minimum Eb/N0", cxxopts::value<float>()->default_value("0.0"), "ebn0min")
		("ebn0max", "The maximum Eb/N0", cxxopts::value<float>()->default_value("3.01"), "ebn0max")
		("ebn0step", "The step of Eb/N0", cxxopts::value<float>()->default_value("0.25"), "ebn0step")
		("help", "Print help");
	options.parse_positional({"input", "output", "positional"});

	auto opts = options.parse(argc, argv);
	if (opts.count("help"))
	{
		std::cout << options.help({"", "Group"}) << std::endl;
		exit(0);
	}

	// get the AFF3CT version
	const std::string v = "v" + std::to_string(tools::version_major()) + "." +
	                            std::to_string(tools::version_minor()) + "." +
	                            std::to_string(tools::version_release());

	std::cout << "#------------------------------------------------------------------------"      << std::endl;
	std::cout << "# This is a Reed-Solomon Code simulator using the AFF3CT library (" << v << ")" << std::endl;
	std::cout << "#------------------------------------------------------------------------"      << std::endl;
	std::cout << "#"                                                                              << std::endl;

	params p;  init_params (p, opts); // create and initialize the parameters defined by the user
	buffers b; init_buffers(p, b   ); // create and initialize the buffers required by the modules
	modules m; init_modules(p, m   ); // create and initialize the modules
	utils u;   init_utils  (m, u   ); // create and initialize the utils

	// display the legend in the terminal
	u.terminal->legend();

	// loop over the various SNRs
	for (auto ebn0 = p.ebn0_min; ebn0 < p.ebn0_max; ebn0 += p.ebn0_step)
	{
		// compute the current sigma for the channel noise
		const auto esn0  = tools::ebn0_to_esn0 (ebn0, p.R);
#if AFF3CT_VERSION == 2
		const auto sigma = tools::esn0_to_sigma(esn0     );
		u.noise->set_noise(sigma, ebn0, esn0);
		// update the sigma of the modem, the channel and the frozen bits
		m.modem  ->set_noise(*u.noise);
		m.channel->set_noise(*u.noise);
#elif AFF3CT_VERSION == 3
		std::fill(b.sigma.begin(), b.sigma.end(), tools::esn0_to_sigma(esn0));
		u.noise->set_values(b.sigma[0], ebn0, esn0);
#endif

		// display the performance (BER and FER) in real time (in a separate thread)
		u.terminal->start_temp_report();

		// run the simulation chain
		while (!m.monitor->fe_limit_achieved() && !u.terminal->is_interrupt())
		{
			m.source ->generate    (                 b.ref_bits     );
			m.encoder->encode      (b.ref_bits,      b.enc_bits     );
			m.modem  ->modulate    (b.enc_bits,      b.symbols      );
#if AFF3CT_VERSION == 2
			m.channel->add_noise   (b.symbols,       b.noisy_symbols);
			m.modem  ->demodulate  (b.noisy_symbols, b.LLRs         );
#elif AFF3CT_VERSION == 3
			m.channel->add_noise   (b.sigma, b.symbols,       b.noisy_symbols);
			m.modem  ->demodulate  (b.sigma, b.noisy_symbols, b.LLRs         );
#endif
			m.decoder->decode_siho (b.LLRs,          b.dec_bits     );
			m.monitor->check_errors(b.dec_bits,      b.ref_bits     );
		}

		// display the performance (BER and FER) in the terminal
		u.terminal->final_report();

		// reset the monitor for the next SNR
		m.monitor->reset();
		u.terminal->reset();

		// if user pressed Ctrl+c twice, exit the SNRs loop
		if (u.terminal->is_over()) break;
	}

	std::cout << "# End of the simulation" << std::endl;

	return 0;
}

Please tell me why it gives the following error, how I should fix it:
using the AFF3CT library (v2.3.5), output:

terminate called after throwing an instance of 'aff3ct::tools::length_error'
  what():  In the '/home/cm/Code/my_project_with_aff3ct/lib/aff3ct/src/Module/Encoder/Encoder.hxx' file at line 145 ('encode' function): "'U_K.size()' has to be equal to 'K' * 'n_frames' ('U_K.size()' = 400, 'K' = 3600, 'n_frames' = 1)."
Backtrace:
./bin/RS_codec_test: void aff3ct::module::Encoder<int>::encode<std::allocator<int> >(std::vector<int, std::allocator<int> > const&, std::vector<int, std::allocator<int> >&, int) +0x1dc [0x56192b38e28a]
./bin/RS_codec_test: main() +0x1b1d [0x56192b37e46b]
/lib/x86_64-linux-gnu/libc.so.6: () +0x29d90 [0x7f272de29d90]
/lib/x86_64-linux-gnu/libc.so.6: __libc_start_main() +0x80 [0x7f272de29e40]
./bin/RS_codec_test: _start() +0x25 [0x56192b37a915]
Aborted (core dumped)

using the AFF3CT library (v3.0.2), similar error occur in Socket.hxx:

'vector.size()' has to be equal to 'get_n_elmts()'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant