From aa2bebdeeec29f93219faf00e4007aad05da3676 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Fri, 24 Jan 2025 12:58:47 +0000 Subject: [PATCH] fix(ldpctest): Confusion in sizes The variable block_length had an ambiguous role and was used as both K and Kprime. This was leading to arrays with wrong sizes and functions with wrong arguments. Now there is not anymore block_length but K and Kprime. Kprime can be set with the command line argument `-l`. There was also some problems with array allocation for segments with length not divisible by 8. A proper sizing with `((size_in_bits + 7) & ~7) / 8` was used. A proper masking of the last byte containing payload bits was also added to keep filler bits to 0 after random initialization. --- openair1/PHY/CODING/TESTBENCH/ldpctest.c | 106 +++++++++++++---------- 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 71c2f1af27..83553fd578 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -102,7 +102,7 @@ one_measurement_t test_ldpc(short max_iterations, int denom_rate, double SNR, unsigned char qbits, - short block_length, + short Kprime, unsigned int ntrials, int n_segments) { @@ -119,9 +119,8 @@ one_measurement_t test_ldpc(short max_iterations, double sigma; sigma = 1.0/sqrt(2*SNR); cpu_meas_enabled = 1; - //short test_input[block_length]; uint8_t *test_input[MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * NR_MAX_NB_LAYERS]; - uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][block_length]; + uint8_t estimated_output[MAX_NUM_DLSCH_SEGMENTS][Kprime]; memset(estimated_output, 0, sizeof(estimated_output)); uint8_t *channel_input[MAX_NUM_DLSCH_SEGMENTS]; uint8_t *channel_input_optim[MAX_NUM_DLSCH_SEGMENTS]; @@ -141,16 +140,6 @@ one_measurement_t test_ldpc(short max_iterations, int32_t n_iter = 0; - // generate input block - for(int j=0;j 3840) { + if (Kprime > 3840) { BG = 1; Kb = 22; nrows = 46; // parity check bits @@ -184,11 +168,11 @@ one_measurement_t test_ldpc(short max_iterations, BG = 2; nrows = 42; // parity check bits // ncols=10; // info bits - if (block_length > 640) + if (Kprime > 640) Kb = 10; - else if (block_length > 560) + else if (Kprime > 560) Kb = 9; - else if (block_length > 192) + else if (Kprime > 192) Kb = 8; else Kb = 6; @@ -240,18 +224,29 @@ one_measurement_t test_ldpc(short max_iterations, 22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 88, 96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384}; for (i1 = 0; i1 < 51; i1++) { - if (lift_size[i1] >= (double)block_length / Kb) { + if (lift_size[i1] >= (double)Kprime / Kb) { Zc = lift_size[i1]; break; } } - printf("ldpc_test: codeword_length %d, n_segments %d, block_length %d, BG %d, Zc %d, Kb %d\n",n_segments *block_length, n_segments, block_length, BG, Zc, Kb); + // K: Segment size = number of columns in the parity check matrix * lifting size (number of columns of the square parity check sub-matrix) + int K = 0; + if (BG == 1) { + K = 22 * Zc; + } else if (BG == 2) { + K = 10 * Zc; + } else { + printf("Not supported: BG: %d\n", BG); + exit(1); + } + + printf("ldpc_test: codeword_length %d, n_segments %d, Kprime %d, BG %d, Zc %d, Kb %d\n", n_segments * K, n_segments, Kprime, BG, Zc, Kb); const int no_punctured_columns = - (int)((nrows - 2) * Zc + block_length - block_length * (1 / ((float)nom_rate / (float)denom_rate))) / Zc; + (int)((nrows - 2) * Zc + K - K * (1 / ((float)nom_rate / (float)denom_rate))) / Zc; // printf("puncture:%d\n",no_punctured_columns); const int removed_bit = - (nrows - no_punctured_columns - 2) * Zc + block_length - (int)(block_length / ((float)nom_rate / (float)denom_rate)); + (nrows - no_punctured_columns - 2) * Zc + K - (int)(K / ((float)nom_rate / (float)denom_rate)); printf("nrows: %d\n", nrows); printf("no_punctured_columns: %d\n", no_punctured_columns); @@ -259,7 +254,29 @@ 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, .K = block_length}; + // generate input block + for(int j=0;j> (i & 7); unsigned char inputbit = (test_input[j][i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estoutputbit != inputbit) @@ -401,7 +420,7 @@ one_measurement_t test_ldpc(short max_iterations, configmodule_interface_t *uniqCfg = NULL; int main(int argc, char *argv[]) { - short block_length=8448; // decoder supports length: 1201 -> 1280, 2401 -> 2560 + short Kprime=8448; // default to check output inside ldpc, the NR version checks the outer CRC defined by 3GPP char *ldpc_version = "_optim8segmulti"; /* version of the ldpc decoder library to use (XXX suffix to use when loading libldpc_XXX.so */ @@ -452,7 +471,7 @@ int main(int argc, char *argv[]) break; case 'l': - block_length = atoi(optarg); + Kprime = atoi(optarg); break; case 'G': @@ -488,13 +507,13 @@ int main(int argc, char *argv[]) case 'h': default: printf("CURRENTLY SUPPORTED CODE RATES: \n"); - printf("BG1 (blocklength > 3840): 1/3, 2/3, 22/25 (8/9) \n"); - printf("BG2 (blocklength <= 3840): 1/5, 1/3, 2/3 \n\n"); + printf("BG1 (K' > 3840): 1/3, 2/3, 22/25 (8/9) \n"); + printf("BG2 (K' <= 3840): 1/5, 1/3, 2/3 \n\n"); printf("-h This message\n"); printf("-q Quantization bits, Default: 8\n"); printf("-r Nominator rate, (1, 2, 22), Default: 1\n"); printf("-d Denominator rate, (3, 5, 25), Default: 1\n"); - printf("-l Block length (l > 3840 -> BG1, rest BG2 ), Default: 8448\n"); + printf("-l Length of payload bits in a segment (K' in 38.212-5.2.2), [1, 8448], Default: 8448\n"); printf("-G give 1 to run cuda for LDPC, Default: 0\n"); printf("-n Number of simulation trials, Default: 1\n"); // printf("-M MCS2 for TB 2\n"); @@ -503,26 +522,23 @@ int main(int argc, char *argv[]) printf("-t SNR simulation step, Default: 0.1\n"); printf("-i Max decoder iterations, Default: 5\n"); printf("-u Set SNR per coded bit, Default: 0\n"); - printf("-v XXX Set ldpc shared library version. libldpc_XXX.so will be used \n"); + printf("-v _XXX Set ldpc shared library version. libldpc_XXX.so will be used \n"); exit(1); break; } } - //printf("the decoder supports BG2, Kb=10, Z=128 & 256\n"); - //printf(" range of blocklength: 1201 -> 1280, 2401 -> 2560\n"); - printf("block length %d: \n", block_length); + printf("block length %d: \n", Kprime); printf("n_trials %d: \n", n_trials); printf("SNR0 %f: \n", SNR0); load_LDPClib(ldpc_version, &ldpc_toCompare); load_LDPClib("_orig", &ldpc_orig); - //for (block_length=8;block_length<=MAX_BLOCK_LENGTH;block_length+=8) //find minimum value in all sets of lifting size Zc=0; char fname[200]; - sprintf(fname,"ldpctest_BG_%d_Zc_%d_rate_%d-%d_block_length_%d_maxit_%d.txt",BG,Zc,nom_rate,denom_rate,block_length, max_iterations); + sprintf(fname,"ldpctest_BG_%d_Zc_%d_rate_%d-%d_Kprime_%d_maxit_%d.txt", BG, Zc, nom_rate, denom_rate, Kprime, max_iterations); FILE *fd=fopen(fname,"w"); AssertFatal(fd!=NULL,"cannot open %s\n",fname); @@ -540,13 +556,13 @@ int main(int argc, char *argv[]) denom_rate, SNR_lin, // noise standard deviation qbits, - block_length, // block length bytes + Kprime, // block length bytes n_trials, n_segments); decoded_errors[i] = res.errors; dec_iter[i] = res.dec_iter; dec_iter[i].snr = SNR; - dec_iter[i].ber = (float)res.errors_bit / (float)n_trials / (float)block_length / (double)n_segments; + dec_iter[i].ber = (float)res.errors_bit / (float)n_trials / (float)Kprime / (double)n_segments; dec_iter[i].bler = (float)decoded_errors[i] / (float)n_trials; printf("SNR %f, BLER %f (%u/%d)\n", SNR, dec_iter[i].bler, decoded_errors[i], n_trials); printf("SNR %f, BER %f (%u/%d)\n", SNR, dec_iter[i].ber, decoded_errors[i], n_trials); @@ -571,7 +587,7 @@ int main(int argc, char *argv[]) "%f %f %f %f %f %f %f %f %f %f %f %f %d \n", SNR, (double)decoded_errors[i] / (double)n_trials, - (double)res.errors_bit / (double)n_trials / (double)block_length / (double)n_segments, + (double)res.errors_bit / (double)n_trials / (double)Kprime / (double)n_segments, res.errors_bit_uncoded / (double)n_trials / (double)n_segments, (double)res.time_optim.diff / res.time_optim.trials / 1000.0 / get_cpu_freq_GHz(), sqrt((double)res.time_optim.diff_square / res.time_optim.trials / pow(1000, 2) / pow(get_cpu_freq_GHz(), 2)