Merge remote-tracking branch 'origin/nrLDPC_coding_improvements_2' into integration_2025_w02 (!3187)
nrLDPC_coding: Fix naming, comments, superfluous variables and documentation typos in coding library interfaces This MR is clarifying the interfaces to the LDPC coding libraries. It aims to improve the readability of the interfaces and compliance of naming with specification 38.212.
This commit is contained in:
@@ -114,9 +114,11 @@ Libraries implementing the slotwise LDPC coding must be named `libldpc<_version>
|
||||
The interface of the library is defined in [nrLDPC_defs.h](file://../nrLDPC_defs.h).
|
||||
The code loading the LDPC library is in [nrLDPC_load.c](file://../nrLDPC_load.c), in function `load_nrLDPClib`, which must be called at init time.
|
||||
|
||||
*Note: LDPC segment coding libraries are not loaded directly by OAI but by the intermediate library `libldpc.so` which is implementing the LDPC slot coding interface using a LDPC segment coding library.*
|
||||
|
||||
### Selecting the LDPC library at run time
|
||||
|
||||
By default the function `int load_nrLDPClib(void)` looks for `libldpc.so`, this default behavior can be changed using the oai loader configuration options in the configuration file or from the command line as shown below:
|
||||
By default the function `int load_nrLDPClib(void)` looks for `libldpc_optim8segmulti.so`, this default behavior can be changed using the oai loader configuration options in the configuration file or from the command line as shown below:
|
||||
|
||||
#### Examples of ldpc shared lib selection when running nr softmodem's:
|
||||
|
||||
@@ -133,7 +135,7 @@ loading `libldpc_optim8seg.so` instead of `libldpc_optim8segmulti.so`:
|
||||
........................
|
||||
```
|
||||
|
||||
loading `libldpc_cl.so` instead of `libldpc.so`:
|
||||
loading `libldpc_cl.so` instead of `libldpc_optim8segmulti.so`:
|
||||
|
||||
`make ldpc_cl`
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
printf("To: %d\n", (Kb + nrows - no_punctured_columns) * Zc - removed_bit);
|
||||
printf("number of undecoded bits: %d\n", (Kb + nrows - no_punctured_columns - 2) * Zc - removed_bit);
|
||||
|
||||
encoder_implemparams_t impp = {.Zc = Zc, .Kb = Kb, .BG = BG, .Kr = block_length, .K = block_length};
|
||||
encoder_implemparams_t impp = {.Zc = Zc, .Kb = Kb, .BG = BG, .K = block_length};
|
||||
impp.gen_code = 2;
|
||||
|
||||
if (ntrials==0)
|
||||
@@ -323,7 +323,7 @@ one_measurement_t test_ldpc(short max_iterations,
|
||||
decParams[j].R = code_rate_vec[R_ind]; // 13;
|
||||
decParams[j].numMaxIter = max_iterations;
|
||||
decParams[j].outMode = nrLDPC_outMode_BIT;
|
||||
decParams[j].E = block_length;
|
||||
decParams[j].Kprime = block_length;
|
||||
ldpc_toCompare.LDPCinit();
|
||||
}
|
||||
for (int j = 0; j < n_segments; j++) {
|
||||
|
||||
@@ -173,7 +173,7 @@ typedef struct nrLDPC_segment_encoding_parameters_s{
|
||||
* \var G Available radio resource bits
|
||||
* \var tbslbrm Transport block size LBRM
|
||||
* \var A Transport block size (This is A from 38.212 V15.4.0 section 5.1)
|
||||
* \var Kb Code block size divided by lifting size
|
||||
* \var Kb Number of time the lifting size needed to fit the payload of a code block
|
||||
* \var K Code block size at input of encoder
|
||||
* \var Z lifting size
|
||||
* \var F filler bits size
|
||||
|
||||
+30
-40
@@ -20,9 +20,8 @@
|
||||
*/
|
||||
|
||||
/*! \file PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c
|
||||
* \brief Top-level routines for decoding LDPC transport channels
|
||||
*/
|
||||
|
||||
* \brief Top-level routines for decoding LDPC transport channels
|
||||
*/
|
||||
|
||||
// [from gNB coding]
|
||||
#include "nr_rate_matching.h"
|
||||
@@ -46,10 +45,10 @@
|
||||
#include <stdint.h>
|
||||
#include <syscall.h>
|
||||
#include <time.h>
|
||||
//#define gNB_DEBUG_TRACE
|
||||
// #define gNB_DEBUG_TRACE
|
||||
|
||||
#define OAI_LDPC_DECODER_MAX_NUM_LLR 27000 //26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
|
||||
//#define DEBUG_CRC
|
||||
#define OAI_LDPC_DECODER_MAX_NUM_LLR 27000 // 26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
|
||||
// #define DEBUG_CRC
|
||||
#ifdef DEBUG_CRC
|
||||
#define PRINT_CRC_CHECK(a) a
|
||||
#else
|
||||
@@ -65,7 +64,8 @@
|
||||
* \brief decoding parameter of transport blocks
|
||||
* \var decoderParms decoder parameters
|
||||
* \var Qm modulation order
|
||||
* \var Kc size of base graph input
|
||||
* \var Kc ratio between the number of columns in the parity check matrix and the lifting size
|
||||
* it is fixed for a given base graph while the lifting size is chosen to have a sufficient number of columns
|
||||
* \var rv_index
|
||||
* \var max_number_iterations maximum number of LDPC iterations
|
||||
* \var abort_decode pointer to decode abort flag
|
||||
@@ -76,7 +76,7 @@
|
||||
* \var F filler bits size
|
||||
* \var r segment index in TB
|
||||
* \var E input llr segment size
|
||||
* \var C number of segments
|
||||
* \var C number of segments
|
||||
* \var llr input llr segment array
|
||||
* \var d Pointers to code blocks before LDPC decoding (38.212 V15.4.0 section 5.3.2)
|
||||
* \var d_to_be_cleared
|
||||
@@ -89,8 +89,7 @@
|
||||
* \var p_ts_rate_unmatch pointer to rate unmatching time stats
|
||||
* \var p_ts_ldpc_decode pointer to decoding time stats
|
||||
*/
|
||||
typedef struct nrLDPC_decoding_parameters_s{
|
||||
|
||||
typedef struct nrLDPC_decoding_parameters_s {
|
||||
t_nrLDPC_dec_params decoderParms;
|
||||
|
||||
uint8_t Qm;
|
||||
@@ -128,14 +127,13 @@ static void nr_process_decode_segment(void *arg)
|
||||
{
|
||||
nrLDPC_decoding_parameters_t *rdata = (nrLDPC_decoding_parameters_t *)arg;
|
||||
t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
|
||||
const int Kr = rdata->K;
|
||||
const int Kr_bytes = Kr >> 3;
|
||||
const int K_bits_F = Kr - rdata->F;
|
||||
const int K = rdata->K;
|
||||
const int Kprime = K - rdata->F;
|
||||
const int A = rdata->A;
|
||||
const int E = rdata->E;
|
||||
const int Qm = rdata->Qm;
|
||||
const int rv_index = rdata->rv_index;
|
||||
const uint8_t kc = rdata->Kc;
|
||||
const uint8_t Kc = rdata->Kc;
|
||||
short *ulsch_llr = rdata->llr;
|
||||
int8_t llrProcBuf[OAI_LDPC_DECODER_MAX_NUM_LLR] __attribute__((aligned(32)));
|
||||
|
||||
@@ -167,7 +165,6 @@ static void nr_process_decode_segment(void *arg)
|
||||
|
||||
///////////////////////// ulsch_harq->e =====> ulsch_harq->d /////////////////////////
|
||||
|
||||
|
||||
if (nr_rate_matching_ldpc_rx(rdata->tbslbrm,
|
||||
p_decoderParms->BG,
|
||||
p_decoderParms->Z,
|
||||
@@ -178,9 +175,8 @@ static void nr_process_decode_segment(void *arg)
|
||||
*rdata->d_to_be_cleared,
|
||||
E,
|
||||
rdata->F,
|
||||
Kr - rdata->F - 2 * (p_decoderParms->Z))
|
||||
K - rdata->F - 2 * (p_decoderParms->Z))
|
||||
== -1) {
|
||||
|
||||
stop_meas(rdata->p_ts_rate_unmatch);
|
||||
LOG_E(PHY, "nrLDPC_coding_segment_decoder.c: Problem in rate_matching\n");
|
||||
|
||||
@@ -192,9 +188,8 @@ static void nr_process_decode_segment(void *arg)
|
||||
|
||||
*rdata->d_to_be_cleared = false;
|
||||
|
||||
memset(rdata->c, 0, Kr_bytes);
|
||||
p_decoderParms->crc_type = crcType(rdata->C, A);
|
||||
p_decoderParms->E = lenWithCrc(rdata->C, A);
|
||||
p_decoderParms->Kprime = lenWithCrc(rdata->C, A);
|
||||
|
||||
// set first 2*Z_c bits to zeros
|
||||
|
||||
@@ -204,16 +199,16 @@ static void nr_process_decode_segment(void *arg)
|
||||
|
||||
memset(z, 0, 2 * rdata->Z * sizeof(*z));
|
||||
// set Filler bits
|
||||
memset(z + K_bits_F, 127, rdata->F * sizeof(*z));
|
||||
memset(z + Kprime, 127, rdata->F * sizeof(*z));
|
||||
// Move coded bits before filler bits
|
||||
memcpy(z + 2 * rdata->Z, rdata->d, (K_bits_F - 2 * rdata->Z) * sizeof(*z));
|
||||
memcpy(z + 2 * rdata->Z, rdata->d, (Kprime - 2 * rdata->Z) * sizeof(*z));
|
||||
// skip filler bits
|
||||
memcpy(z + Kr, rdata->d + (Kr - 2 * rdata->Z), (kc * rdata->Z - Kr) * sizeof(*z));
|
||||
memcpy(z + K, rdata->d + (K - 2 * rdata->Z), (Kc * rdata->Z - K) * sizeof(*z));
|
||||
// Saturate coded bits before decoding into 8 bits values
|
||||
simde__m128i *pv = (simde__m128i *)&z;
|
||||
int8_t l[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
simde__m128i *pl = (simde__m128i *)&l;
|
||||
for (int i = 0, j = 0; j < ((kc * rdata->Z) >> 4) + 1; i += 2, j++) {
|
||||
for (int i = 0, j = 0; j < ((Kc * rdata->Z) >> 4) + 1; i += 2, j++) {
|
||||
pl[j] = simde_mm_packs_epi16(pv[i], pv[i + 1]);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -227,9 +222,10 @@ static void nr_process_decode_segment(void *arg)
|
||||
ldpc_interface_segment.LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, rdata->abort_decode);
|
||||
|
||||
if (decodeIterations <= p_decoderParms->numMaxIter) {
|
||||
memcpy(rdata->c,llrProcBuf, Kr>>3);
|
||||
memcpy(rdata->c, llrProcBuf, K >> 3);
|
||||
*rdata->decodeSuccess = true;
|
||||
} else {
|
||||
memset(rdata->c, 0, K >> 3);
|
||||
*rdata->decodeSuccess = false;
|
||||
}
|
||||
stop_meas(rdata->p_ts_ldpc_decode);
|
||||
@@ -238,9 +234,10 @@ static void nr_process_decode_segment(void *arg)
|
||||
completed_task_ans(rdata->ans);
|
||||
}
|
||||
|
||||
int nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters, int pusch_id, thread_info_tm_t *t_info)
|
||||
int nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters,
|
||||
int pusch_id,
|
||||
thread_info_tm_t *t_info)
|
||||
{
|
||||
|
||||
nrLDPC_TB_decoding_parameters_t *nrLDPC_TB_decoding_parameters = &nrLDPC_slot_decoding_parameters->TBs[pusch_id];
|
||||
|
||||
*nrLDPC_TB_decoding_parameters->processedSegments = 0;
|
||||
@@ -251,14 +248,12 @@ int nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_de
|
||||
decParams.outMode = 0;
|
||||
|
||||
for (int r = 0; r < nrLDPC_TB_decoding_parameters->C; r++) {
|
||||
|
||||
nrLDPC_decoding_parameters_t *rdata = &((nrLDPC_decoding_parameters_t *)t_info->buf)[t_info->len];
|
||||
DevAssert(t_info->len < t_info->cap);
|
||||
rdata->ans = &t_info->ans[t_info->len];
|
||||
t_info->len += 1;
|
||||
|
||||
decParams.R = nrLDPC_TB_decoding_parameters->segments[r].R;
|
||||
decParams.setCombIn = !nrLDPC_TB_decoding_parameters->segments[r].d_to_be_cleared;
|
||||
rdata->decoderParms = decParams;
|
||||
rdata->llr = nrLDPC_TB_decoding_parameters->segments[r].llr;
|
||||
rdata->Kc = decParams.BG == 2 ? 52 : 68;
|
||||
@@ -288,29 +283,26 @@ int nrLDPC_prepare_TB_decoding(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_de
|
||||
return nrLDPC_TB_decoding_parameters->C;
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_init(void){
|
||||
|
||||
int32_t nrLDPC_coding_init(void)
|
||||
{
|
||||
char *segment_shlibversion = NULL;
|
||||
paramdef_t LoaderParams[] = {
|
||||
{"segment_shlibversion", NULL, 0, .strptr = &segment_shlibversion, .defstrval = "_optim8segmulti", TYPE_STRING, 0, NULL}
|
||||
};
|
||||
{"segment_shlibversion", NULL, 0, .strptr = &segment_shlibversion, .defstrval = "_optim8segmulti", TYPE_STRING, 0, NULL}};
|
||||
config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_segment");
|
||||
load_LDPClib(segment_shlibversion, &ldpc_interface_segment);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_shutdown(void){
|
||||
|
||||
int32_t nrLDPC_coding_shutdown(void)
|
||||
{
|
||||
free_LDPClib(&ldpc_interface_segment);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters){
|
||||
|
||||
int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_decoding_parameters)
|
||||
{
|
||||
int nbSegments = 0;
|
||||
for (int pusch_id = 0; pusch_id < nrLDPC_slot_decoding_parameters->nb_TBs; pusch_id++) {
|
||||
nrLDPC_TB_decoding_parameters_t *nrLDPC_TB_decoding_parameters = &nrLDPC_slot_decoding_parameters->TBs[pusch_id];
|
||||
@@ -340,6 +332,4 @@ int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *nrLDPC_slot_dec
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
+29
-39
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
/*! \file PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c
|
||||
* \brief Top-level routines for implementing LDPC encoding of transport channels
|
||||
*/
|
||||
* \brief Top-level routines for implementing LDPC encoding of transport channels
|
||||
*/
|
||||
|
||||
#include "nr_rate_matching.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
@@ -41,8 +41,8 @@
|
||||
|
||||
#include <syscall.h>
|
||||
|
||||
//#define DEBUG_LDPC_ENCODING
|
||||
//#define DEBUG_LDPC_ENCODING_FREE 1
|
||||
// #define DEBUG_LDPC_ENCODING
|
||||
// #define DEBUG_LDPC_ENCODING_FREE 1
|
||||
|
||||
extern ldpc_interface_t ldpc_interface_segment;
|
||||
|
||||
@@ -62,35 +62,34 @@ static void ldpc8blocks_coding_segment(void *p)
|
||||
uint32_t A = nrLDPC_TB_encoding_parameters->A;
|
||||
|
||||
unsigned int G = nrLDPC_TB_encoding_parameters->G;
|
||||
LOG_D(PHY,"dlsch coding A %d Kr %d G %d (nb_rb %d, mod_order %d)\n",
|
||||
A,impp->K,G, nb_rb,(int)mod_order);
|
||||
LOG_D(PHY, "dlsch coding A %d K %d G %d (nb_rb %d, mod_order %d)\n", A, impp->K, G, nb_rb, (int)mod_order);
|
||||
|
||||
// nrLDPC_encoder output is in "d"
|
||||
// let's make this interface happy!
|
||||
uint8_t tmp[8][68 * 384]__attribute__((aligned(32)));
|
||||
uint8_t tmp[8][68 * 384] __attribute__((aligned(32)));
|
||||
uint8_t *d[impp->n_segments];
|
||||
for (int rr=impp->macro_num*8, i=0; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++,i++ )
|
||||
for (int rr = impp->macro_num * 8, i = 0; rr < impp->n_segments && rr < (impp->macro_num + 1) * 8; rr++, i++)
|
||||
d[rr] = tmp[i];
|
||||
|
||||
uint8_t *c[nrLDPC_TB_encoding_parameters->C];
|
||||
for (int r = 0; r < nrLDPC_TB_encoding_parameters->C; r++)
|
||||
c[r]=nrLDPC_TB_encoding_parameters->segments[r].c;
|
||||
start_meas(&nrLDPC_TB_encoding_parameters->segments[impp->macro_num*8].ts_ldpc_encode);
|
||||
c[r] = nrLDPC_TB_encoding_parameters->segments[r].c;
|
||||
start_meas(&nrLDPC_TB_encoding_parameters->segments[impp->macro_num * 8].ts_ldpc_encode);
|
||||
ldpc_interface_segment.LDPCencoder(c, d, impp);
|
||||
stop_meas(&nrLDPC_TB_encoding_parameters->segments[impp->macro_num*8].ts_ldpc_encode);
|
||||
stop_meas(&nrLDPC_TB_encoding_parameters->segments[impp->macro_num * 8].ts_ldpc_encode);
|
||||
// Compute where to place in output buffer that is concatenation of all segments
|
||||
|
||||
uint32_t r_offset=0;
|
||||
for (int i=0; i < impp->macro_num*8; i++ )
|
||||
r_offset+=nrLDPC_TB_encoding_parameters->segments[i].E;
|
||||
for (int rr=impp->macro_num*8; rr < impp->n_segments && rr < (impp->macro_num+1)*8; rr++ ) {
|
||||
if (impp->F>0) {
|
||||
uint32_t r_offset = 0;
|
||||
for (int i = 0; i < impp->macro_num * 8; i++)
|
||||
r_offset += nrLDPC_TB_encoding_parameters->segments[i].E;
|
||||
for (int rr = impp->macro_num * 8; rr < impp->n_segments && rr < (impp->macro_num + 1) * 8; rr++) {
|
||||
if (impp->F > 0) {
|
||||
// writing into positions d[r][k-2Zc] as in clause 5.3.2 step 2) in 38.212
|
||||
memset(&d[rr][impp->K - impp->F - 2 * impp->Zc], NR_NULL, impp->F);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LDPC_ENCODING
|
||||
LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]);
|
||||
LOG_D(PHY, "rvidx in encoding = %d\n", rel15->rvIndex[0]);
|
||||
#endif
|
||||
uint32_t E = nrLDPC_TB_encoding_parameters->segments[rr].E;
|
||||
LOG_D(NR_PHY,
|
||||
@@ -109,7 +108,7 @@ static void ldpc8blocks_coding_segment(void *p)
|
||||
uint32_t Tbslbrm = nrLDPC_TB_encoding_parameters->tbslbrm;
|
||||
|
||||
uint8_t e[E];
|
||||
bzero (e, E);
|
||||
bzero(e, E);
|
||||
start_meas(&nrLDPC_TB_encoding_parameters->segments[rr].ts_rate_match);
|
||||
nr_rate_matching_ldpc(Tbslbrm,
|
||||
impp->BG,
|
||||
@@ -123,16 +122,10 @@ static void ldpc8blocks_coding_segment(void *p)
|
||||
E);
|
||||
stop_meas(&nrLDPC_TB_encoding_parameters->segments[rr].ts_rate_match);
|
||||
if (impp->K - impp->F - 2 * impp->Zc > E) {
|
||||
LOG_E(PHY,
|
||||
"dlsch coding A %d Kr %d G %d (nb_rb %d, mod_order %d)\n",
|
||||
A,
|
||||
impp->K,
|
||||
G,
|
||||
nb_rb,
|
||||
(int)mod_order);
|
||||
LOG_E(PHY, "dlsch coding A %d K %d G %d (nb_rb %d, mod_order %d)\n", A, impp->K, G, nb_rb, (int)mod_order);
|
||||
|
||||
LOG_E(NR_PHY,
|
||||
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Kr %d, Filler bits %d, Filler offset %d mod_order %d, "
|
||||
"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, K %d, Filler bits %d, Filler offset %d mod_order %d, "
|
||||
"nb_rb %d)...\n",
|
||||
rr,
|
||||
impp->n_segments,
|
||||
@@ -146,23 +139,20 @@ static void ldpc8blocks_coding_segment(void *p)
|
||||
}
|
||||
#ifdef DEBUG_LDPC_ENCODING
|
||||
|
||||
for (int i =0; i<16; i++)
|
||||
printf("output ratematching e[%d]= %d r_offset %u\n", i,e[i], r_offset);
|
||||
for (int i = 0; i < 16; i++)
|
||||
printf("output ratematching e[%d]= %d r_offset %u\n", i, e[i], r_offset);
|
||||
|
||||
#endif
|
||||
start_meas(&nrLDPC_TB_encoding_parameters->segments[rr].ts_interleave);
|
||||
nr_interleaving_ldpc(E,
|
||||
mod_order,
|
||||
e,
|
||||
impp->output+r_offset);
|
||||
nr_interleaving_ldpc(E, mod_order, e, impp->output + r_offset);
|
||||
stop_meas(&nrLDPC_TB_encoding_parameters->segments[rr].ts_interleave);
|
||||
#ifdef DEBUG_LDPC_ENCODING
|
||||
|
||||
for (int i =0; i<16; i++)
|
||||
printf("output interleaving f[%d]= %d r_offset %u\n", i,impp->output[i+r_offset], r_offset);
|
||||
for (int i = 0; i < 16; i++)
|
||||
printf("output interleaving f[%d]= %d r_offset %u\n", i, impp->output[i + r_offset], r_offset);
|
||||
|
||||
if (r==impp->n_segments-1)
|
||||
write_output("enc_output.m","enc",impp->output,G,1,4);
|
||||
if (r == impp->n_segments - 1)
|
||||
write_output("enc_output.m", "enc", impp->output, G, 1, 4);
|
||||
|
||||
#endif
|
||||
r_offset += E;
|
||||
@@ -172,7 +162,9 @@ static void ldpc8blocks_coding_segment(void *p)
|
||||
completed_task_ans(impp->ans);
|
||||
}
|
||||
|
||||
static int nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters, int dlsch_id, thread_info_tm_t *t_info)
|
||||
static int nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters,
|
||||
int dlsch_id,
|
||||
thread_info_tm_t *t_info)
|
||||
{
|
||||
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = &nrLDPC_slot_encoding_parameters->TBs[dlsch_id];
|
||||
|
||||
@@ -212,7 +204,6 @@ static int nrLDPC_prepare_TB_encoding(nrLDPC_slot_encoding_parameters_t *nrLDPC_
|
||||
|
||||
int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encoding_parameters)
|
||||
{
|
||||
|
||||
int nbTasks = 0;
|
||||
for (int dlsch_id = 0; dlsch_id < nrLDPC_slot_encoding_parameters->nb_TBs; dlsch_id++) {
|
||||
nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters = &nrLDPC_slot_encoding_parameters->TBs[dlsch_id];
|
||||
@@ -235,5 +226,4 @@ int nrLDPC_coding_encoder(nrLDPC_slot_encoding_parameters_t *nrLDPC_slot_encodin
|
||||
join_task_ans(ans, nbEncode);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ typedef struct args_fpga_decode_prepare_s {
|
||||
uint32_t r_span; /*!< number of blocks to be prepared within this function */
|
||||
int r_offset; /*!< r index expressed in bits */
|
||||
int input_CBoffset; /*!< */
|
||||
int kc; /*!< */
|
||||
int K_bits_F; /*!< */
|
||||
int Kc; /*!< ratio between the number of columns in the parity check graph and the lifting size */
|
||||
int Kprime; /*!< size of payload and CRC bits in a code block */
|
||||
task_ans_t *ans; /*!< pointer to the answer that is used by thread pool to detect job completion */
|
||||
} args_fpga_decode_prepare_t;
|
||||
|
||||
@@ -93,24 +93,20 @@ int32_t nrLDPC_coding_init(void);
|
||||
int32_t nrLDPC_coding_shutdown(void);
|
||||
int32_t nrLDPC_coding_decoder(nrLDPC_slot_decoding_parameters_t *slot_params, int frame_rx, int slot_rx);
|
||||
// int32_t nrLDPC_coding_encoder(void);
|
||||
int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
int frame_rx,
|
||||
int slot_rx,
|
||||
tpool_t *ldpc_threadPool);
|
||||
int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params, int frame_rx, int slot_rx, tpool_t *ldpc_threadPool);
|
||||
void nr_ulsch_FPGA_decoding_prepare_blocks(void *args);
|
||||
|
||||
int32_t nrLDPC_coding_init(void)
|
||||
{
|
||||
char *encoder_shlibversion = NULL;
|
||||
paramdef_t LoaderParams[] = {
|
||||
{"num_threads_prepare", NULL, 0, .iptr = &num_threads_prepare_max, .defintval = 0, TYPE_INT, 0, NULL},
|
||||
{"encoder_shlibversion", NULL, 0, .strptr = &encoder_shlibversion, .defstrval = "_optim8segmulti", TYPE_STRING, 0, NULL},
|
||||
{"user_device", NULL, 0, .strptr = &user_device, .defstrval = DEVICE_NAME_DEFAULT_USER, TYPE_STRING, 0, NULL},
|
||||
{"enc_read_device", NULL, 0, .strptr = &enc_read_device, .defstrval = DEVICE_NAME_DEFAULT_ENC_READ, TYPE_STRING, 0, NULL},
|
||||
{"enc_write_device", NULL, 0, .strptr = &enc_write_device, .defstrval = DEVICE_NAME_DEFAULT_ENC_WRITE, TYPE_STRING, 0, NULL},
|
||||
{"dec_read_device", NULL, 0, .strptr = &dec_read_device, .defstrval = DEVICE_NAME_DEFAULT_DEC_READ, TYPE_STRING, 0, NULL},
|
||||
{"dec_write_device", NULL, 0, .strptr = &dec_write_device, .defstrval = DEVICE_NAME_DEFAULT_DEC_WRITE, TYPE_STRING, 0, NULL}
|
||||
};
|
||||
{"num_threads_prepare", NULL, 0, .iptr = &num_threads_prepare_max, .defintval = 0, TYPE_INT, 0, NULL},
|
||||
{"encoder_shlibversion", NULL, 0, .strptr = &encoder_shlibversion, .defstrval = "_optim8segmulti", TYPE_STRING, 0, NULL},
|
||||
{"user_device", NULL, 0, .strptr = &user_device, .defstrval = DEVICE_NAME_DEFAULT_USER, TYPE_STRING, 0, NULL},
|
||||
{"enc_read_device", NULL, 0, .strptr = &enc_read_device, .defstrval = DEVICE_NAME_DEFAULT_ENC_READ, TYPE_STRING, 0, NULL},
|
||||
{"enc_write_device", NULL, 0, .strptr = &enc_write_device, .defstrval = DEVICE_NAME_DEFAULT_ENC_WRITE, TYPE_STRING, 0, NULL},
|
||||
{"dec_read_device", NULL, 0, .strptr = &dec_read_device, .defstrval = DEVICE_NAME_DEFAULT_DEC_READ, TYPE_STRING, 0, NULL},
|
||||
{"dec_write_device", NULL, 0, .strptr = &dec_write_device, .defstrval = DEVICE_NAME_DEFAULT_DEC_WRITE, TYPE_STRING, 0, NULL}};
|
||||
config_get(config_get_if(), LoaderParams, sizeofArray(LoaderParams), "nrLDPC_coding_xdma");
|
||||
AssertFatal(num_threads_prepare_max != 0, "nrLDPC_coding_xdma.num_threads_prepare was not provided");
|
||||
|
||||
@@ -139,16 +135,12 @@ int32_t nrLDPC_coding_encoder(void)
|
||||
}
|
||||
*/
|
||||
|
||||
int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
int frame_rx,
|
||||
int slot_rx,
|
||||
tpool_t *ldpc_threadPool)
|
||||
int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params, int frame_rx, int slot_rx, tpool_t *ldpc_threadPool)
|
||||
{
|
||||
const uint32_t Kr = TB_params->K;
|
||||
const uint32_t Kr_bytes = Kr >> 3;
|
||||
const int kc = TB_params->BG == 2 ? 52 : 68;
|
||||
const uint32_t K = TB_params->K;
|
||||
const int Kc = TB_params->BG == 2 ? 52 : 68;
|
||||
int r_offset = 0, offset = 0;
|
||||
int K_bits_F = Kr - TB_params->F;
|
||||
int Kprime = K - TB_params->F;
|
||||
|
||||
// FPGA parameter preprocessing
|
||||
static uint8_t multi_indata[27000 * 25]; // FPGA input data
|
||||
@@ -157,7 +149,7 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
int bg_len = TB_params->BG == 1 ? 22 : 10;
|
||||
|
||||
// Calc input CB offset
|
||||
int input_CBoffset = TB_params->Z * kc * 8;
|
||||
int input_CBoffset = TB_params->Z * Kc * 8;
|
||||
if ((input_CBoffset & 0x7F) == 0)
|
||||
input_CBoffset = input_CBoffset / 8;
|
||||
else
|
||||
@@ -169,7 +161,7 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
dec_conf.max_iter = TB_params->max_ldpc_iterations;
|
||||
dec_conf.numCB = TB_params->C;
|
||||
// input soft bits length, Zc x 66 - length of filler bits
|
||||
dec_conf.numChannelLls = (K_bits_F - 2 * TB_params->Z) + (kc * TB_params->Z - Kr);
|
||||
dec_conf.numChannelLls = (Kprime - 2 * TB_params->Z) + (Kc * TB_params->Z - K);
|
||||
// filler bits length
|
||||
dec_conf.numFillerBits = TB_params->F;
|
||||
dec_conf.max_schedule = 0;
|
||||
@@ -197,11 +189,11 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
printf("TB_params->F: %d\n", TB_params->F);
|
||||
printf("numChannelLls:\t %d = (%d - 2 * %d) + (%d * %d - %d)\n",
|
||||
dec_conf.numChannelLls,
|
||||
K_bits_F,
|
||||
Kprime,
|
||||
TB_params->Z,
|
||||
kc,
|
||||
Kc,
|
||||
TB_params->Z,
|
||||
Kr);
|
||||
K);
|
||||
printf("numFillerBits:\t %d\n", TB_params->F);
|
||||
printf("------------------------\n");
|
||||
// ===================================
|
||||
@@ -222,10 +214,9 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
// calculate required number of jobs
|
||||
uint32_t r_while = 0;
|
||||
while (r_while < TB_params->C) {
|
||||
|
||||
// calculate number of segments processed in the new job
|
||||
uint32_t modulus = (TB_params->C - r_while) % (num_threads_prepare_max - num_threads_prepare);
|
||||
uint32_t quotient = (TB_params->C - r_while) / (num_threads_prepare_max - num_threads_prepare);
|
||||
uint32_t quotient = (TB_params->C - r_while) / (num_threads_prepare_max - num_threads_prepare);
|
||||
uint32_t r_span_max = modulus == 0 ? quotient : quotient + 1;
|
||||
|
||||
// saturate to be sure to not go above C
|
||||
@@ -259,15 +250,15 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
args->r_first = r;
|
||||
|
||||
uint32_t modulus = (TB_params->C - r) % (num_threads_prepare_max - num_threads_prepare);
|
||||
uint32_t quotient = (TB_params->C - r) / (num_threads_prepare_max - num_threads_prepare);
|
||||
uint32_t quotient = (TB_params->C - r) / (num_threads_prepare_max - num_threads_prepare);
|
||||
uint32_t r_span_max = modulus == 0 ? quotient : quotient + 1;
|
||||
|
||||
uint32_t r_span = TB_params->C - r < r_span_max ? TB_params->C - r : r_span_max;
|
||||
args->r_span = r_span;
|
||||
args->r_offset = r_offset;
|
||||
args->input_CBoffset = input_CBoffset;
|
||||
args->kc = kc;
|
||||
args->K_bits_F = K_bits_F;
|
||||
args->Kc = Kc;
|
||||
args->Kprime = Kprime;
|
||||
|
||||
r_remaining = r_span;
|
||||
|
||||
@@ -277,7 +268,7 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params,
|
||||
LOG_D(PHY, "Added %d block(s) to prepare for decoding, in pipe: %d to %d\n", r_span, r, r + r_span - 1);
|
||||
}
|
||||
r_offset += segment_params->E;
|
||||
offset += (Kr_bytes - (TB_params->F >> 3) - ((TB_params->C > 1) ? 3 : 0));
|
||||
offset += ((K >> 3) - (TB_params->F >> 3) - ((TB_params->C > 1) ? 3 : 0));
|
||||
r_remaining -= 1;
|
||||
}
|
||||
|
||||
@@ -354,7 +345,7 @@ void nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
|
||||
uint8_t max_ldpc_iterations = TB_params->max_ldpc_iterations;
|
||||
|
||||
uint32_t tbslbrm = TB_params->tbslbrm;
|
||||
uint32_t Kr = TB_params->K;
|
||||
uint32_t K = TB_params->K;
|
||||
uint32_t Z = TB_params->Z;
|
||||
uint32_t F = TB_params->F;
|
||||
|
||||
@@ -370,8 +361,8 @@ void nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
|
||||
uint32_t r_span = arguments->r_span;
|
||||
int r_offset = arguments->r_offset;
|
||||
int input_CBoffset = arguments->input_CBoffset;
|
||||
int kc = arguments->kc;
|
||||
int K_bits_F = arguments->K_bits_F;
|
||||
int Kc = arguments->Kc;
|
||||
int Kprime = arguments->Kprime;
|
||||
|
||||
int16_t z[68 * 384 + 16] __attribute__((aligned(16)));
|
||||
simde__m128i *pv = (simde__m128i *)&z;
|
||||
@@ -406,7 +397,7 @@ void nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
|
||||
*segment_params->d_to_be_cleared,
|
||||
segment_params->E,
|
||||
F,
|
||||
Kr - F - 2 * Z)
|
||||
K - F - 2 * Z)
|
||||
== -1) {
|
||||
stop_meas(&segment_params->ts_rate_unmatch);
|
||||
LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n");
|
||||
@@ -419,33 +410,33 @@ void nr_ulsch_FPGA_decoding_prepare_blocks(void *args)
|
||||
|
||||
*segment_params->d_to_be_cleared = false;
|
||||
|
||||
memset(segment_params->c, 0, Kr >> 3);
|
||||
memset(segment_params->c, 0, K >> 3);
|
||||
|
||||
// set first 2*Z_c bits to zeros
|
||||
memset(&z[0], 0, 2 * Z * sizeof(int16_t));
|
||||
// set Filler bits
|
||||
memset((&z[0] + K_bits_F), 127, F * sizeof(int16_t));
|
||||
memset((&z[0] + Kprime), 127, F * sizeof(int16_t));
|
||||
// Move coded bits before filler bits
|
||||
memcpy((&z[0] + 2 * Z), segment_params->d, (K_bits_F - 2 * Z) * sizeof(int16_t));
|
||||
memcpy((&z[0] + 2 * Z), segment_params->d, (Kprime - 2 * Z) * sizeof(int16_t));
|
||||
// skip filler bits
|
||||
memcpy((&z[0] + Kr), segment_params->d + (Kr - 2 * Z), (kc * Z - Kr) * sizeof(int16_t));
|
||||
memcpy((&z[0] + K), segment_params->d + (K - 2 * Z), (Kc * Z - K) * sizeof(int16_t));
|
||||
|
||||
// Saturate coded bits before decoding into 8 bits values
|
||||
for (int i = 0, j = 0; j < ((kc * Z) >> 4); i += 2, j++) {
|
||||
for (int i = 0, j = 0; j < ((Kc * Z) >> 4); i += 2, j++) {
|
||||
temp_multi_indata[j] =
|
||||
simde_mm_xor_si128(simde_mm_packs_epi16(pv[i], pv[i + 1]),
|
||||
simde_mm_cmpeq_epi32(ones,
|
||||
ones)); // Perform NOT operation and write the result to temp_multi_indata[j]
|
||||
}
|
||||
|
||||
// the last bytes before reaching "kc * harq_process->Z" should not be written 128 bits at a time to avoid overwritting the
|
||||
// the last bytes before reaching "Kc * harq_process->Z" should not be written 128 bits at a time to avoid overwritting the
|
||||
// following block in multi_indata
|
||||
simde__m128i tmp =
|
||||
simde_mm_xor_si128(simde_mm_packs_epi16(pv[2 * ((kc * Z) >> 4)], pv[2 * ((kc * Z) >> 4) + 1]),
|
||||
simde_mm_xor_si128(simde_mm_packs_epi16(pv[2 * ((Kc * Z) >> 4)], pv[2 * ((Kc * Z) >> 4) + 1]),
|
||||
simde_mm_cmpeq_epi32(ones,
|
||||
ones)); // Perform NOT operation and write the result to temp_multi_indata[j]
|
||||
uint8_t *tmp_p = (uint8_t *)&tmp;
|
||||
for (int i = 0, j = ((kc * Z) & 0xfffffff0); j < kc * Z; i++, j++) {
|
||||
for (int i = 0, j = ((Kc * Z) & 0xfffffff0); j < Kc * Z; i++, j++) {
|
||||
multi_indata[r * input_CBoffset + j] = tmp_p[i];
|
||||
}
|
||||
|
||||
|
||||
@@ -855,7 +855,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr,
|
||||
nrLDPC_llr2bitPacked(p_out, p_llrOut, numLLR);
|
||||
else // if (outMode == nrLDPC_outMode_BITINT8)
|
||||
nrLDPC_llr2bit(p_out, p_llrOut, numLLR);
|
||||
if (p_decParams->check_crc((uint8_t*)p_out, p_decParams->E, p_decParams->crc_type)) {
|
||||
if (p_decParams->check_crc((uint8_t*)p_out, p_decParams->Kprime, p_decParams->crc_type)) {
|
||||
LOG_D(PHY, "Segment CRC OK, exiting LDPC decoder\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -86,11 +86,10 @@ typedef struct nrLDPC_dec_params {
|
||||
uint16_t Z; /**< Lifting size */
|
||||
uint8_t R; /**< Decoding rate: Format 15,13,... for code rates 1/5, 1/3,... */
|
||||
uint8_t numMaxIter; /**< Maximum number of iterations */
|
||||
int E;
|
||||
int Kprime; /**< Size of the payload bits and CRC bits in the code block */
|
||||
e_nrLDPC_outMode outMode; /**< Output format */
|
||||
int crc_type;
|
||||
int (*check_crc)(uint8_t* decoded_bytes, uint32_t n, uint8_t crc_type);
|
||||
uint8_t setCombIn;
|
||||
int crc_type; /**< Size and type of the parity check bits (16, 24A or 24B) */
|
||||
int (*check_crc)(uint8_t* decoded_bytes, uint32_t n, uint8_t crc_type); /**< Parity check function */
|
||||
} t_nrLDPC_dec_params;
|
||||
|
||||
/**
|
||||
|
||||
@@ -518,7 +518,7 @@ extern "C" int32_t LDPCdecoder(t_nrLDPC_dec_params *p_decParams,
|
||||
init_LLR_DMA(p_decParams, p_llr, p_out);
|
||||
uint16_t Zc = p_decParams->Z;
|
||||
uint8_t BG = p_decParams->BG;
|
||||
int block_length = p_decParams->E;
|
||||
int block_length = p_decParams->Kprime;
|
||||
uint8_t row, col;
|
||||
if (BG == 1) {
|
||||
row = 46;
|
||||
|
||||
@@ -26,37 +26,51 @@
|
||||
#include "openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
|
||||
|
||||
/**
|
||||
\brief LDPC encoder
|
||||
\param 1 input
|
||||
\param 2 channel_input
|
||||
\param 3 int Zc
|
||||
\param 4 int Kb
|
||||
\param 5 short block_length
|
||||
\param 6 short BG
|
||||
\param 7 int n_segment
|
||||
\param 8 unsigned int macro_num
|
||||
\param 9-12 time_stats_t *tinput,*tprep, *tparity,*toutput
|
||||
\brief LDPC encoder parameter structure
|
||||
\var n_segments number of segments in the transport block
|
||||
\var macro_num index of the subset of segments to encode
|
||||
within the transport block
|
||||
\var gen_code flag to generate parity check code
|
||||
0 -> encoding
|
||||
1 -> generate parity check code with AVX2
|
||||
2 -> generate parity check code without AVX2
|
||||
\var tinput time statistics for data input in the encoder
|
||||
\var tprep time statistics for data preparation in the encoder
|
||||
\var tparity time statistics for adding parity bits
|
||||
\var toutput time statistics for data output from the encoder
|
||||
\var K size of the complete code segment before encoding
|
||||
including payload, CRC bits and filler bit
|
||||
(also known as Kr, see 38.212-5.2.2)
|
||||
\var Kb number of lifting sizes to fit the payload (see 38.212-5.2.2)
|
||||
\var Zc lifting size (see 38.212-5.2.2)
|
||||
\var F number of filler bits (see 38.212-5.2.2)
|
||||
\var harq pointer to the HARQ process structure
|
||||
\var BG base graph index
|
||||
\var output output buffer after INTERLEAVING
|
||||
\var ans pointer to the task answer
|
||||
to notify thread pool about completion of the task
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int n_segments; // optim8seg
|
||||
unsigned int macro_num; // optim8segmulti
|
||||
unsigned char gen_code; //orig
|
||||
unsigned int n_segments; // optim8seg
|
||||
unsigned int macro_num; // optim8segmulti
|
||||
unsigned char gen_code; //orig
|
||||
time_stats_t *tinput;
|
||||
time_stats_t *tprep;
|
||||
time_stats_t *tparity;
|
||||
time_stats_t *toutput;
|
||||
int Kr;
|
||||
/// Size in bits of the code segments
|
||||
uint32_t K;
|
||||
/// Number of lifting sizes to fit the payload
|
||||
uint32_t Kb;
|
||||
/// Lifting size
|
||||
uint32_t Zc;
|
||||
/// Number of "Filler" bits
|
||||
uint32_t F;
|
||||
void *harq;
|
||||
/// Encoder BG
|
||||
uint8_t BG;
|
||||
/// Interleaver outputs
|
||||
unsigned char *output;
|
||||
/// Number of bits in "small" code segments
|
||||
uint32_t K;
|
||||
/// Number of "Filler" bits
|
||||
uint32_t F;
|
||||
task_ans_t *ans;
|
||||
} encoder_implemparams_t;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user