SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | List of all members
leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr > Struct Template Reference

#include <ldpc.h>

+ Collaboration diagram for leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >:

Classes

struct  node
 

Public Types

typedef int64_t score_t
 

Public Member Functions

 ldpc_engine ()
 
 ldpc_engine (const ldpc_table< Taddr > *table, int _k, int _n)
 
void print_node_stats ()
 
int count_edges (node *nodes, int nnodes)
 
void encode (const ldpc_table< Taddr > *table, const SOFTWORD *msg, int k, int n, SOFTWORD *parity, int integrate=true)
 
score_t compute_scores (SOFTWORD *m, SOFTWORD *p, SOFTWORD *q, int nc, score_t *score, int k)
 
int decode_bitflip (const ldpc_table< Taddr > *table, SOFTWORD *cw, int k, int n, int max_bitflips)
 

Static Public Member Functions

static void integrate_bits (const SOFTWORD *in, SOFTWORD *out, int nwords)
 
static void diff_bits (const SOFTWORD *in, SOFTWORD *out, int nwords)
 

Public Attributes

int k
 
int n
 
nodevnodes
 
nodecnodes
 

Static Public Attributes

static const int PPCM = 39
 

Detailed Description

template<typename SOFTBIT, typename SOFTWORD, int SWSIZE, typename Taddr>
struct leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >

Definition at line 52 of file ldpc.h.

Member Typedef Documentation

◆ score_t

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
typedef int64_t leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::score_t

Definition at line 258 of file ldpc.h.

Constructor & Destructor Documentation

◆ ldpc_engine() [1/2]

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::ldpc_engine ( )
inline

Definition at line 55 of file ldpc.h.

56  : vnodes(NULL), cnodes(NULL)
57  {
58  }
node * cnodes
Definition: ldpc.h:84
node * vnodes
Definition: ldpc.h:83

◆ ldpc_engine() [2/2]

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::ldpc_engine ( const ldpc_table< Taddr > *  table,
int  _k,
int  _n 
)
inline

Definition at line 88 of file ldpc.h.

References leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::node::append(), leansdr::fail(), leansdr::fatal(), leansdr::ldpc_table< Taddr >::nrows, leansdr::ldpc_table< Taddr >::q, and leansdr::ldpc_table< Taddr >::rows.

89  : k(_k), n(_n)
90  {
91  // Sanity checks
92  if (360 % SWSIZE)
93  fatal("Bad LDPC word size");
94  if (k % SWSIZE)
95  fatal("Bad LDPC k");
96  if (n % SWSIZE)
97  fatal("Bad LDPC n");
98  if (k != table->nrows * 360)
99  fatal("Bad table");
100  int n_k = n - k;
101  if (table->q * 360 != n_k)
102  fatal("Bad q");
103 
104  vnodes = new node[k];
105  memset(vnodes, 0, sizeof(node) * k);
106  cnodes = new node[n_k];
107  memset(cnodes, 0, sizeof(node) * n_k);
108 
109  // Expand the graph.
110 
111  int m = 0;
112  // Iterate over rows
113  for (const typename ldpc_table<Taddr>::row *prow = table->rows;
114  prow < table->rows + table->nrows;
115  ++prow)
116  {
117  // Process 360 bits per row.
118  int q = table->q;
119  int qoffs = 0;
120  for (int mw = 360; mw--; ++m, qoffs += q)
121  {
122  const Taddr *pa = prow->cols;
123  for (int nc = prow->ncols; nc--; ++pa)
124  {
125  int a = (int)*pa + qoffs;
126  if (a >= n_k)
127  a -= n_k; // Modulo n-k. Note qoffs<360*q.
128  if (a >= n_k)
129  fail("Invalid LDPC table");
130  vnodes[m].append(a);
131  cnodes[a].append(m);
132  }
133  }
134  }
135  }
node * cnodes
Definition: ldpc.h:84
void fail(const char *s)
Definition: framework.cpp:11
void append(Taddr a)
Definition: ldpc.h:71
void fatal(const char *s)
Definition: framework.cpp:6
node * vnodes
Definition: ldpc.h:83
+ Here is the call graph for this function:

Member Function Documentation

◆ compute_scores()

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
score_t leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::compute_scores ( SOFTWORD *  m,
SOFTWORD *  p,
SOFTWORD *  q,
int  nc,
score_t score,
int  k 
)
inline

c, v, s, err, softwords_weight<SOFTBIT,SOFTWORD>(m,*pe));

Definition at line 260 of file ldpc.h.

References leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::node::edges, leansdr::softbit_harden(), and leansdr::softwords_xor().

262  {
263  int total = 0;
264  memset(score, 0, k * sizeof(*score));
265  for (int c = 0; c < nc; ++c)
266  {
267  SOFTBIT err = softwords_xor(p, q, c);
268  if (softbit_harden(err))
269  {
270  Taddr *pe = cnodes[c].edges;
271  for (int e = cnodes[c].nedges; e--; ++pe)
272  {
273  int v = *pe;
274  int s = err * softwords_weight<SOFTBIT, SOFTWORD>(m, v) * PPCM / vnodes[v].nedges;
275  //fprintf(stderr, "c[%d] bad => v[%d] += %d (%d*%d)\n",
277  score[v] += s;
278  total += s;
279  }
280  }
281  }
282  return total;
283  }
node * cnodes
Definition: ldpc.h:84
static const int PPCM
Definition: ldpc.h:256
bool softwords_xor(const hard_sb p1[], const hard_sb p2[], int b)
Definition: softword.h:42
bool softbit_harden(bool b)
Definition: softword.h:38
node * vnodes
Definition: ldpc.h:83
+ Here is the call graph for this function:

◆ count_edges()

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
int leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::count_edges ( node nodes,
int  nnodes 
)
inline

Definition at line 145 of file ldpc.h.

References leansdr::fatal(), i, leansdr::ldpc_table< Taddr >::nrows, leansdr::parity(), leansdr::ldpc_table< Taddr >::q, leansdr::ldpc_table< Taddr >::rows, leansdr::softword_get(), leansdr::softword_zero(), and leansdr::softwords_flip().

146  {
147  int c = 0;
148  for (int i = 0; i < nnodes; ++i)
149  c += nodes[i].nedges;
150  return c;
151  }
int32_t i
Definition: decimators.h:244
+ Here is the call graph for this function:

◆ decode_bitflip()

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
int leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::decode_bitflip ( const ldpc_table< Taddr > *  table,
SOFTWORD *  cw,
int  k,
int  n,
int  max_bitflips 
)
inline

Definition at line 285 of file ldpc.h.

References leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::node::edges, leansdr::fail(), lfprintf, leansdr::softbit_harden(), leansdr::softbit_set(), leansdr::softwords_flip(), and leansdr::softwords_xor().

Referenced by leansdr::s2_fecdec< SOFTBIT, SOFTBYTE >::run().

288  {
289  if (!vnodes)
290  fail("LDPC graph not initialized");
291  int n_k = n - k;
292 
293  // Compute the expected check bits (without the final mixing)
294  SOFTWORD *expected = new SOFTWORD[n_k / SWSIZE]; // Forbidden to statically allocate with non constant size
295  encode(table, cw, k, n, expected, false);
296  // Reverse the integrator mixing from the received check bits
297  SOFTWORD *received = new SOFTWORD[n_k / SWSIZE]; // Forbidden to statically allocate with non constant size
298  diff_bits(cw + k / SWSIZE, received, n_k / SWSIZE);
299 
300  // Compute initial scores
301  score_t *score = new score_t[k]; // Forbidden to statically allocate with non constant size
302  score_t tots = compute_scores(cw, expected, received, n_k, score, k);
303  lfprintf(stderr, "Initial score %d\n", (int)tots);
304 
305  int nflipped = 0;
306 
307  score_t score_threshold;
308  {
309  SOFTBIT one;
310  softbit_set(&one, true);
311  score_threshold = (int)one * 2;
312  }
313 
314  bool progress = true;
315  while (progress && nflipped < max_bitflips)
316  {
317  progress = false;
318  // Try to flip parity bits.
319  // Due to differential decoding, they appear as consecutive errors.
320  SOFTBIT prev_err = softwords_xor(expected, received, 0);
321  for (int b = 0; b < n - k - 1; ++b)
322  {
323  prev_err = softwords_xor(expected, received, b); //TBD
324  SOFTBIT err = softwords_xor(expected, received, b + 1);
325  if (softbit_harden(prev_err) && softbit_harden(err))
326  {
327  lfprintf(stderr, "flip parity %d\n", b);
328  softwords_flip(received, b);
329  softwords_flip(received, b + 1);
330  ++nflipped; // Counts as one flip before differential decoding.
331  progress = true;
332  int dtot = 0;
333  // Depenalize adjacent message bits.
334  {
335  Taddr *pe = cnodes[b].edges;
336  for (int e = cnodes[b].nedges; e--; ++pe)
337  {
338  int d = prev_err * softwords_weight<SOFTBIT, SOFTWORD>(cw, *pe) * PPCM / vnodes[*pe].nedges;
339  score[*pe] -= d;
340  dtot -= d;
341  }
342  }
343  {
344  Taddr *pe = cnodes[b + 1].edges;
345  for (int e = cnodes[b + 1].nedges; e--; ++pe)
346  {
347  int d = err * softwords_weight<SOFTBIT, SOFTWORD>(cw, *pe) * PPCM / vnodes[*pe].nedges;
348  score[*pe] -= d;
349  dtot -= d;
350  }
351  }
352  tots += dtot;
353 #if 1
354  // Also update the codeword in-place.
355  // TBD Useful for debugging only.
356  softwords_flip(cw, k + b);
357 #endif
358  // TBD version soft. err = ! err;
359  }
360  prev_err = err;
361  } // c nodes
362  score_t maxs = -(1 << 30);
363  for (int v = 0; v < k; ++v)
364  if (score[v] > maxs)
365  maxs = score[v];
366  if (!maxs)
367  break;
368  lfprintf(stderr, "maxs %d\n", (int)maxs);
369  // Try to flip each message bits with maximal score
370  for (int v = 0; v < k; ++v)
371  {
372  if (score[v] < score_threshold)
373  continue;
374  // if ( score[v] < maxs*9/10 ) continue;
375  if (score[v] < maxs - 4)
376  continue;
377  lfprintf(stderr, " flip %d score=%d\n", (int)v, (int)score[v]);
378  // Update expected parities and scores that depend on them.
379  score_t dtot = 0;
380  for (int commit = 0; commit <= 1; ++commit)
381  {
382  Taddr *pe = vnodes[v].edges;
383  for (int e = vnodes[v].nedges; e--; ++pe)
384  {
385  Taddr c = *pe;
386  SOFTBIT was_bad = softwords_xor(expected, received, c);
387  if (softbit_harden(was_bad))
388  {
389  Taddr *pe = cnodes[c].edges;
390  for (int e = cnodes[c].nedges; e--; ++pe)
391  {
392  int d = was_bad * softwords_weight<SOFTBIT, SOFTWORD>(cw, *pe) * PPCM / vnodes[*pe].nedges;
393  if (commit)
394  score[*pe] -= d;
395  else
396  dtot -= d;
397  }
398  }
399  softwords_flip(expected, c);
400  SOFTBIT is_bad = softwords_xor(expected, received, c);
401  if (softbit_harden(is_bad))
402  {
403  Taddr *pe = cnodes[c].edges;
404  for (int e = cnodes[c].nedges; e--; ++pe)
405  {
406  int d = is_bad * softwords_weight<SOFTBIT, SOFTWORD>(cw, *pe) * PPCM / vnodes[*pe].nedges;
407  if (commit)
408  score[*pe] += d;
409  else
410  dtot += d;
411  }
412  }
413  if (!commit)
414  softwords_flip(expected, c);
415  }
416  if (!commit)
417  {
418  if (dtot >= 0)
419  {
420  lfprintf(stderr, " abort %d\n", v);
421  break; // Next v
422  }
423  }
424  else
425  {
426  softwords_flip(cw, v);
427  ++nflipped;
428  tots += dtot;
429  progress = true;
430  v = k - 1; // Force exit to update maxs ?
431  }
432  } // commit
433  } // v
434  lfprintf(stderr, "progress %d\n", progress);
435 #if 0
436  fprintf(stderr, "CHECKING TOTS INCREMENT (slow) %d\n", tots);
437  score_t tots2 = compute_scores(cw, expected, received, n_k, score, k);
438  if ( tots2 != tots ) fail("bad tots update");
439 #endif
440  }
441 
442  delete[] score;
443  delete[] received;
444  delete[] expected;
445 
446  return nflipped;
447  }
int64_t score_t
Definition: ldpc.h:258
node * cnodes
Definition: ldpc.h:84
static const int PPCM
Definition: ldpc.h:256
bool softwords_xor(const hard_sb p1[], const hard_sb p2[], int b)
Definition: softword.h:42
score_t compute_scores(SOFTWORD *m, SOFTWORD *p, SOFTWORD *q, int nc, score_t *score, int k)
Definition: ldpc.h:260
bool softbit_harden(bool b)
Definition: softword.h:38
void softwords_flip(hard_sb p[], int b)
Definition: softword.h:63
#define lfprintf(...)
Definition: ldpc.h:20
void fail(const char *s)
Definition: framework.cpp:11
void encode(const ldpc_table< Taddr > *table, const SOFTWORD *msg, int k, int n, SOFTWORD *parity, int integrate=true)
Definition: ldpc.h:199
static void diff_bits(const SOFTWORD *in, SOFTWORD *out, int nwords)
Definition: ldpc.h:491
void softbit_set(bool *p, bool v)
Definition: softword.h:37
node * vnodes
Definition: ldpc.h:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ diff_bits()

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
static void leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::diff_bits ( const SOFTWORD *  in,
SOFTWORD *  out,
int  nwords 
)
inlinestatic

Definition at line 491 of file ldpc.h.

References i, leansdr::softbit_clear(), leansdr::softbit_xor(), leansdr::softword_get(), and leansdr::softword_write().

492  {
493  SOFTBIT prev;
494  softbit_clear(&prev);
495  for (int i = 0; i < nwords; ++i, ++in, ++out)
496  {
497  SOFTWORD w = *in;
498  for (int b = 0; b < SWSIZE; ++b)
499  {
500  SOFTBIT n = softword_get(w, b);
501  softword_write(w, b, softbit_xor(prev, n));
502  prev = n;
503  }
504  *out = w;
505  }
506  }
void softword_write(hard_sb &p, int b, bool v)
Definition: softword.h:54
void softbit_clear(bool *p)
Definition: softword.h:41
int32_t i
Definition: decimators.h:244
bool softbit_xor(bool x, bool y)
Definition: softword.h:40
bool softword_get(const hard_sb &p, int b)
Definition: softword.h:23
+ Here is the call graph for this function:

◆ encode()

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
void leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::encode ( const ldpc_table< Taddr > *  table,
const SOFTWORD *  msg,
int  k,
int  n,
SOFTWORD *  parity,
int  integrate = true 
)
inline

Definition at line 199 of file ldpc.h.

References leansdr::fatal(), i, leansdr::ldpc_table< Taddr >::nrows, leansdr::ldpc_table< Taddr >::q, leansdr::ldpc_table< Taddr >::rows, leansdr::softbit_harden(), leansdr::softword_get(), leansdr::softword_zero(), and leansdr::softwords_flip().

Referenced by leansdr::s2_fecenc::run_frame().

201  {
202  // Sanity checks
203  if (360 % SWSIZE)
204  fatal("Bad LDPC word size");
205  if (k % SWSIZE)
206  fatal("Bad LDPC k");
207  if (n % SWSIZE)
208  fatal("Bad LDPC n");
209  if (k != table->nrows * 360)
210  fatal("Bad table");
211  int n_k = n - k;
212  if (table->q * 360 != n_k)
213  fatal("Bad q");
214 
215  for (int i = 0; i < n_k / SWSIZE; ++i)
217 
218  // Iterate over rows
219  for (const typename ldpc_table<Taddr>::row *prow = table->rows; // quirk
220  prow < table->rows + table->nrows;
221  ++prow)
222  {
223  // Process 360 bits per row, in words of SWSIZE bits
224  int q = table->q;
225  int qoffs = 0;
226  for (int mw = 360 / SWSIZE; mw--; ++msg)
227  {
228  SOFTWORD msgword = *msg;
229  for (int wbit = 0; wbit < SWSIZE; ++wbit, qoffs += q)
230  {
231  SOFTBIT msgbit = softword_get(msgword, wbit);
232  if (!softbit_harden(msgbit))
233  continue;
234  const Taddr *pa = prow->cols;
235  for (int nc = prow->ncols; nc--; ++pa)
236  {
237  int a = (int)*pa + qoffs;
238  // Note: qoffs < 360*q=n-k
239  if (a >= n_k)
240  a -= n_k; // TBD not predictable
242  }
243  }
244  }
245  }
246 
247  if (integrate)
248  integrate_bits(parity, parity, n_k / SWSIZE);
249  }
bool softbit_harden(bool b)
Definition: softword.h:38
static void integrate_bits(const SOFTWORD *in, SOFTWORD *out, int nwords)
Definition: ldpc.h:453
void softwords_flip(hard_sb p[], int b)
Definition: softword.h:63
int32_t i
Definition: decimators.h:244
void fatal(const char *s)
Definition: framework.cpp:6
void softword_zero(hard_sb *p)
Definition: softword.h:46
unsigned char parity(uint8_t x)
Definition: math.cpp:27
bool softword_get(const hard_sb &p, int b)
Definition: softword.h:23
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ integrate_bits()

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
static void leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::integrate_bits ( const SOFTWORD *  in,
SOFTWORD *  out,
int  nwords 
)
inlinestatic

Definition at line 453 of file ldpc.h.

References i, leansdr::softbit_clear(), leansdr::softbit_xor(), leansdr::softword_get(), and leansdr::softword_write().

454  {
455  SOFTBIT sum;
456  softbit_clear(&sum);
457  for (int i = 0; i < nwords; ++i)
458  {
459  SOFTWORD w = in[i];
460  for (int b = 0; b < SWSIZE; ++b)
461  {
462  sum = softbit_xor(sum, softword_get(w, b));
463  softword_write(w, b, sum);
464  }
465  out[i] = w;
466  }
467  }
void softword_write(hard_sb &p, int b, bool v)
Definition: softword.h:54
void softbit_clear(bool *p)
Definition: softword.h:41
int32_t i
Definition: decimators.h:244
bool softbit_xor(bool x, bool y)
Definition: softword.h:40
bool softword_get(const hard_sb &p, int b)
Definition: softword.h:23
+ Here is the call graph for this function:

◆ print_node_stats()

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
void leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::print_node_stats ( )
inline

Definition at line 137 of file ldpc.h.

Referenced by leansdr::s2_ldpc_engines< bool, hard_sb >::print_node_stats().

138  {
139  int nedges = count_edges(vnodes, k);
140  fprintf(stderr, "LDPC(%5d,%5d)(%.2f)"
141  " %5.2f edges/vnode, %5.2f edges/cnode\n",
142  k, n - k, (float)k / n, (float)nedges / k, (float)nedges / (n - k));
143  }
int count_edges(node *nodes, int nnodes)
Definition: ldpc.h:145
node * vnodes
Definition: ldpc.h:83
+ Here is the caller graph for this function:

Member Data Documentation

◆ cnodes

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
node* leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::cnodes

Definition at line 84 of file ldpc.h.

◆ k

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
int leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::k

Definition at line 63 of file ldpc.h.

◆ n

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
int leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::n

Definition at line 64 of file ldpc.h.

◆ PPCM

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
const int leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::PPCM = 39
static

Definition at line 256 of file ldpc.h.

◆ vnodes

template<typename SOFTBIT , typename SOFTWORD , int SWSIZE, typename Taddr >
node* leansdr::ldpc_engine< SOFTBIT, SOFTWORD, SWSIZE, Taddr >::vnodes

Definition at line 83 of file ldpc.h.


The documentation for this struct was generated from the following file: