1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-23 00:18:37 -05:00

DATV: external LDPC tool implementation (5): dequeue outputs in run() method

This commit is contained in:
f4exb 2021-03-06 07:37:44 +01:00
parent 8c45107c8c
commit 6e8b573b5f
2 changed files with 79 additions and 82 deletions

View File

@ -28,6 +28,7 @@ static const int DEFAULT_TRIALS = 50;
#include "layered_decoder.h" #include "layered_decoder.h"
static const int DEFAULT_TRIALS = 25; static const int DEFAULT_TRIALS = 25;
#endif #endif
static const int DEFAULT_BATCH_SIZE = 32;
//ldpctool::LDPCInterface *create_ldpc(char *standard, char prefix, int number); //ldpctool::LDPCInterface *create_ldpc(char *standard, char prefix, int number);
@ -46,7 +47,7 @@ void fatal(const char *msg)
void usage(const char *name, FILE *f, int c, const char *info = NULL) void usage(const char *name, FILE *f, int c, const char *info = NULL)
{ {
fprintf(f, "Usage: %s [--standard DVB-S2] --modcod INT [--trials INT] [--shortframes] < FECFRAMES.int8 > FECFRAMES.int8\n", name); fprintf(f, "Usage: %s [--standard DVB-S2] --modcod INT [--trials 25] [--batch-size 32] [--shortframes] < FECFRAMES.int8 > FECFRAMES.int8\n", name);
if (info) if (info)
fprintf(f, "** Error while processing '%s'\n", info); fprintf(f, "** Error while processing '%s'\n", info);
exit(c); exit(c);
@ -57,6 +58,7 @@ int main(int argc, char **argv)
const char *standard = "DVB-S2"; const char *standard = "DVB-S2";
int modcod = -1; int modcod = -1;
int max_trials = DEFAULT_TRIALS; int max_trials = DEFAULT_TRIALS;
int batch_size = DEFAULT_BATCH_SIZE;
bool shortframes = false; bool shortframes = false;
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
@ -67,6 +69,8 @@ int main(int argc, char **argv)
modcod = atoi(argv[++i]); modcod = atoi(argv[++i]);
else if (!strcmp(argv[i], "--trials") && i + 1 < argc) else if (!strcmp(argv[i], "--trials") && i + 1 < argc)
max_trials = atoi(argv[++i]); max_trials = atoi(argv[++i]);
else if (!strcmp(argv[i], "--batch-size") && i + 1 < argc)
batch_size = atoi(argv[++i]);
else if (!strcmp(argv[i], "--shortframes")) else if (!strcmp(argv[i], "--shortframes"))
shortframes = true; shortframes = true;
else if (!strcmp(argv[i], "-h")) else if (!strcmp(argv[i], "-h"))
@ -123,7 +127,7 @@ int main(int argc, char **argv)
decode.init(ldpc); decode.init(ldpc);
int BLOCKS = 32; int BLOCKS = batch_size;
ldpctool::code_type *code = new ldpctool::code_type[BLOCKS * CODE_LEN]; ldpctool::code_type *code = new ldpctool::code_type[BLOCKS * CODE_LEN];
void *aligned_buffer = aligned_alloc(sizeof(ldpctool::simd_type), sizeof(ldpctool::simd_type) * CODE_LEN); void *aligned_buffer = aligned_alloc(sizeof(ldpctool::simd_type), sizeof(ldpctool::simd_type) * CODE_LEN);
ldpctool::simd_type *simd = reinterpret_cast<ldpctool::simd_type *>(aligned_buffer); ldpctool::simd_type *simd = reinterpret_cast<ldpctool::simd_type *>(aligned_buffer);
@ -172,6 +176,7 @@ int main(int argc, char **argv)
{ {
iterations += blocks * trials; iterations += blocks * trials;
std::cerr << "ldpc_tool: decoder failed at converging to a code word in " << trials << " trials" << std::endl; std::cerr << "ldpc_tool: decoder failed at converging to a code word in " << trials << " trials" << std::endl;
break;
} }
else else
{ {

View File

@ -393,7 +393,7 @@ struct s2_frame_transmitter : runnable
private: private:
pipereader<plslot<hard_ss>> in; pipereader<plslot<hard_ss>> in;
pipewriter<complex<T>> out; pipewriter<complex<T>> out;
cstln_lut<hard_ss, 256> *cstln; // NULL initially cstln_lut<hard_ss, 256> *cstln; // nullptr initially
complex<T> *csymbols; // Valid iff cstln is valid. RMS cstln_amp. complex<T> *csymbols; // Valid iff cstln is valid. RMS cstln_amp.
void update_cstln(const modcod_info *mcinfo) void update_cstln(const modcod_info *mcinfo)
{ {
@ -445,13 +445,13 @@ struct s2_frame_receiver : runnable
sampler_interface<T> *_sampler, sampler_interface<T> *_sampler,
pipebuf<complex<T>> &_in, pipebuf<complex<T>> &_in,
pipebuf<plslot<SOFTSYMB>> &_out, pipebuf<plslot<SOFTSYMB>> &_out,
pipebuf<float> *_freq_out = NULL, pipebuf<float> *_freq_out = nullptr,
pipebuf<float> *_ss_out = NULL, pipebuf<float> *_ss_out = nullptr,
pipebuf<float> *_mer_out = NULL, pipebuf<float> *_mer_out = nullptr,
pipebuf<complex<float>> *_cstln_out = NULL, pipebuf<complex<float>> *_cstln_out = nullptr,
pipebuf<complex<float>> *_cstln_pls_out = NULL, pipebuf<complex<float>> *_cstln_pls_out = nullptr,
pipebuf<complex<float>> *_symbols_out = NULL, pipebuf<complex<float>> *_symbols_out = nullptr,
pipebuf<int> *_state_out = NULL) pipebuf<int> *_state_out = nullptr)
: runnable(sch, "S2 frame receiver"), : runnable(sch, "S2 frame receiver"),
sampler(_sampler), sampler(_sampler),
meas_decimation(1048576), meas_decimation(1048576),
@ -459,7 +459,7 @@ struct s2_frame_receiver : runnable
strongpls(false), strongpls(false),
in_power(0), ev_power(0), agc_gain(1), agc_bw(1e-3), in_power(0), ev_power(0), agc_gain(1), agc_bw(1e-3),
nsyncs(0), nsyncs(0),
cstln(NULL), cstln(nullptr),
in(_in), out(_out, 1 + modcod_info::MAX_SLOTS_PER_FRAME), in(_in), out(_out, 1 + modcod_info::MAX_SLOTS_PER_FRAME),
meas_count(0), meas_count(0),
freq_out(opt_writer(_freq_out)), freq_out(opt_writer(_freq_out)),
@ -612,7 +612,7 @@ struct s2_frame_receiver : runnable
if (cstln_out && cstln_out->writable() >= 1024) if (cstln_out && cstln_out->writable() >= 1024)
psampled = cstln_out->wr(); psampled = cstln_out->wr();
else else
psampled = NULL; psampled = nullptr;
// Preserve float precision // Preserve float precision
phase16 -= 65536 * floor(phase16 / 65536); phase16 -= 65536 * floor(phase16 / 65536);
@ -714,15 +714,15 @@ struct s2_frame_receiver : runnable
if (cstln_out && cstln_out->writable() >= 1024) if (cstln_out && cstln_out->writable() >= 1024)
psampled = cstln_out->wr(); psampled = cstln_out->wr();
else else
psampled = NULL; psampled = nullptr;
complex<float> *psampled_pls; complex<float> *psampled_pls;
if (cstln_pls_out && cstln_pls_out->writable() >= 1024) if (cstln_pls_out && cstln_pls_out->writable() >= 1024)
psampled_pls = cstln_pls_out->wr(); psampled_pls = cstln_pls_out->wr();
else else
psampled_pls = NULL; psampled_pls = nullptr;
#if TEST_DIVERSITY #if TEST_DIVERSITY
complex<float> *psymbols = symbols_out ? symbols_out->wr() : NULL; complex<float> *psymbols = symbols_out ? symbols_out->wr() : nullptr;
float scale_symbols = 1.0 / cstln_amp; float scale_symbols = 1.0 / cstln_amp;
#endif #endif
@ -1941,7 +1941,7 @@ struct s2_ldpc_engines
const fec_info *fi = &fec_infos[sf][fec]; const fec_info *fi = &fec_infos[sf][fec];
if (!fi->ldpc) if (!fi->ldpc)
{ {
ldpcs[sf][fec] = NULL; ldpcs[sf][fec] = nullptr;
} }
else else
{ {
@ -2095,8 +2095,8 @@ struct s2_fecdec : runnable
int bitflips; int bitflips;
s2_fecdec(scheduler *sch, s2_fecdec(scheduler *sch,
pipebuf<fecframe<SOFTBYTE>> &_in, pipebuf<bbframe> &_out, pipebuf<fecframe<SOFTBYTE>> &_in, pipebuf<bbframe> &_out,
pipebuf<int> *_bitcount = NULL, pipebuf<int> *_bitcount = nullptr,
pipebuf<int> *_errcount = NULL) pipebuf<int> *_errcount = nullptr)
: runnable(sch, "S2 fecdec"), : runnable(sch, "S2 fecdec"),
bitflips(0), bitflips(0),
in(_in), out(_out), in(_in), out(_out),
@ -2309,7 +2309,7 @@ private:
uint8_t bch_buf[64800 / 8]; // Temp storage for hardening before BCH uint8_t bch_buf[64800 / 8]; // Temp storage for hardening before BCH
s2_bch_engines s2bch; s2_bch_engines s2bch;
s2_bbscrambling bbscrambling; s2_bbscrambling bbscrambling;
}; }; // s2_fecdec_soft
// External LDPC decoder // External LDPC decoder
// Spawns a user-specified command, FEC frames on stdin/stdout. // Spawns a user-specified command, FEC frames on stdin/stdout.
@ -2351,29 +2351,54 @@ struct s2_fecdec_helper : runnable
pipebuf<fecframe<SOFTBYTE>> &_in, pipebuf<fecframe<SOFTBYTE>> &_in,
pipebuf<bbframe> &_out, pipebuf<bbframe> &_out,
const char *_command, const char *_command,
pipebuf<int> *_bitcount = NULL, pipebuf<int> *_bitcount = nullptr,
pipebuf<int> *_errcount = NULL) pipebuf<int> *_errcount = nullptr)
: runnable(sch, "S2 fecdec io"), : runnable(sch, "S2 fecdec io"),
batch_size(32), batch_size(16),
nhelpers(1), nhelpers(1),
must_buffer(false), must_buffer(false),
in(_in), out(_out), in(_in), out(_out),
command(_command), command(_command),
writing_modulo(1),
zeros_count(0),
run_count(0),
bitcount(opt_writer(_bitcount, 1)), bitcount(opt_writer(_bitcount, 1)),
errcount(opt_writer(_errcount, 1)) errcount(opt_writer(_errcount, 1))
{ {
for (int mc = 0; mc < 32; ++mc) for (int mc = 0; mc < 32; ++mc)
for (int sf = 0; sf < 2; ++sf) for (int sf = 0; sf < 2; ++sf)
pools[mc][sf].procs = NULL; pools[mc][sf].procs = nullptr;
} }
void run() void run()
{ {
// Send work until all helpers block. // Send work until all helpers block.
while (in.readable() >= 1 && !jobs.full()) while (in.readable() >= 1 && !jobs.full())
{ {
if (out.writable() >= 1)
{
if (bbframe_q.size() != 0)
{
bbframe *pout = out.wr();
pout->pls = bbframe_q.front().pls;
std::copy(bbframe_q.front().bytes, bbframe_q.front().bytes + (58192 / 8), pout->bytes);
bbframe_q.pop_front();
out.written(1);
}
else
{
fprintf(stderr, "s2_fecdec_helper::run: WARNING: bbframe queue is empty\n");
}
}
if ((bitcount_q.size() != 0) && opt_writable(bitcount, 1))
{
opt_write(bitcount, bitcount_q.front());
bitcount_q.pop_front();
}
if ((errcount_q.size() != 0) && opt_writable(errcount, 1))
{
opt_write(errcount, errcount_q.front());
errcount_q.pop_front();
}
if (!send_frame(in.rd())) { if (!send_frame(in.rd())) {
break; break;
} }
@ -2381,54 +2406,12 @@ struct s2_fecdec_helper : runnable
in.read(1); in.read(1);
} }
// while (
// !jobs.empty() &&
// jobs.peek()->h->b_out &&
// out.writable() >= 1 &&
// opt_writable(bitcount, 1) &&
// opt_writable(errcount, 1)
// )
while ( while (
!jobs.empty() && !jobs.empty() &&
jobs.peek()->h->b_out) jobs.peek()->h->b_out)
{ {
receive_frame(jobs.get()); receive_frame(jobs.get());
} }
if ((run_count % writing_modulo == 0) && (bbframe_q.size() != 0) && out.writable() >= 1)
{
if (zeros_count != 0)
{
writing_modulo = (bbframe_q.size() + zeros_count) / bbframe_q.size();
fprintf(stderr, "s2_fecdec_helper::run: bbframe queue size: %lu zeros: %d writing_modulo: %d\n",
bbframe_q.size(), zeros_count, writing_modulo);
}
bbframe *pout = out.wr();
pout->pls = bbframe_q.front().pls;
std::copy(bbframe_q.front().bytes, bbframe_q.front().bytes + (58192 / 8), pout->bytes);
bbframe_q.pop_front();
out.written(1);
zeros_count = 0;
}
else
{
zeros_count++;
}
if ((bitcount_q.size() != 0) && opt_writable(bitcount, 1))
{
opt_write(bitcount, bitcount_q.front());
bitcount_q.pop_front();
}
if ((errcount_q.size() != 0) && opt_writable(errcount, 1))
{
opt_write(errcount, errcount_q.front());
errcount_q.pop_front();
}
run_count++;
} }
private: private:
@ -2442,7 +2425,7 @@ struct s2_fecdec_helper : runnable
}; };
struct pool struct pool
{ {
helper_instance *procs; // NULL or [nprocs] helper_instance *procs; // nullptr or [nprocs]
int nprocs; int nprocs;
} pools[32][2]; // [modcod][sf] } pools[32][2]; // [modcod][sf]
struct helper_job struct helper_job
@ -2533,7 +2516,10 @@ struct s2_fecdec_helper : runnable
fprintf(stderr, "*** Throughput will be suboptimal.\n"); fprintf(stderr, "*** Throughput will be suboptimal.\n");
} }
#endif #endif
int child = vfork(); // vfork() differs from fork(2) in that the calling thread is
// suspended until the child terminates
int child = fork();
if (!child) if (!child)
{ {
// Child process // Child process
@ -2543,16 +2529,19 @@ struct s2_fecdec_helper : runnable
dup2(rx[1], 1); dup2(rx[1], 1);
char mc_arg[16]; char mc_arg[16];
sprintf(mc_arg, "%d", pls->modcod); sprintf(mc_arg, "%d", pls->modcod);
const char *sf_arg = pls->sf ? "--shortframes" : NULL; char batch_size_arg[16];
const char *argv[] = {command, "--trials", "10", "--modcod", mc_arg, sf_arg, NULL}; sprintf(batch_size_arg, "%d", batch_size);
execve(command, (char *const *)argv, NULL); const char *sf_arg = pls->sf ? "--shortframes" : nullptr;
const char *argv[] = {command, "--trials", "5", "--batch-size", batch_size_arg, "--modcod", mc_arg, sf_arg, nullptr};
execve(command, (char *const *)argv, nullptr);
fatal(command); fatal(command);
} }
h->fd_tx = tx[1]; h->fd_tx = tx[1];
close(tx[0]); close(tx[0]);
h->fd_rx = rx[0]; h->fd_rx = rx[0];
close(rx[1]); close(rx[1]);
h->batch_size = 32; // TBD h->batch_size = batch_size; // TBD
h->b_in = h->b_out = 0; h->b_in = h->b_out = 0;
int flags = fcntl(h->fd_tx, F_GETFL); int flags = fcntl(h->fd_tx, F_GETFL);
if (fcntl(h->fd_tx, F_SETFL, flags | O_NONBLOCK)) if (fcntl(h->fd_tx, F_SETFL, flags | O_NONBLOCK))
@ -2618,9 +2607,6 @@ struct s2_fecdec_helper : runnable
std::deque<bbframe> bbframe_q; std::deque<bbframe> bbframe_q;
std::deque<int> bitcount_q; std::deque<int> bitcount_q;
std::deque<int> errcount_q; std::deque<int> errcount_q;
unsigned int writing_modulo;
unsigned int zeros_count;
unsigned int run_count;
pipewriter<int> *bitcount, *errcount; pipewriter<int> *bitcount, *errcount;
}; // s2_fecdec_helper }; // s2_fecdec_helper
@ -2714,8 +2700,8 @@ struct s2_framer : runnable
struct s2_deframer : runnable struct s2_deframer : runnable
{ {
s2_deframer(scheduler *sch, pipebuf<bbframe> &_in, pipebuf<tspacket> &_out, s2_deframer(scheduler *sch, pipebuf<bbframe> &_in, pipebuf<tspacket> &_out,
pipebuf<int> *_state_out = NULL, pipebuf<int> *_state_out = nullptr,
pipebuf<unsigned long> *_locktime_out = NULL) pipebuf<unsigned long> *_locktime_out = nullptr)
: runnable(sch, "S2 deframer"), : runnable(sch, "S2 deframer"),
missing(-1), missing(-1),
in(_in), out(_out, MAX_TS_PER_BBFRAME), in(_in), out(_out, MAX_TS_PER_BBFRAME),
@ -2767,7 +2753,9 @@ struct s2_deframer : runnable
syncd > dfl || (dfl & 7) || (syncd & 7)) syncd > dfl || (dfl & 7) || (syncd & 7))
{ {
// Note: Maybe accept syncd=65535 // Note: Maybe accept syncd=65535
fprintf(stderr, "Bad bbframe\n"); if (sch->debug) {
fprintf(stderr, "Bad bbframe\n");
}
missing = -1; missing = -1;
info_unlocked(); info_unlocked();
return; return;
@ -2778,7 +2766,9 @@ struct s2_deframer : runnable
{ {
// Skip unusable data at beginning of bbframe // Skip unusable data at beginning of bbframe
pos = syncd / 8; pos = syncd / 8;
fprintf(stderr, "Start TS at %d\n", pos); if (sch->debug) {
fprintf(stderr, "Start TS at %d\n", pos);
}
missing = 0; missing = 0;
} }
else else
@ -2786,7 +2776,9 @@ struct s2_deframer : runnable
// Sanity check // Sanity check
if (syncd / 8 != missing) if (syncd / 8 != missing)
{ {
fprintf(stderr, "Lost a bbframe ?\n"); if (sch->debug) {
fprintf(stderr, "Lost a bbframe ?\n");
}
missing = -1; missing = -1;
info_unlocked(); info_unlocked();
return; return;