From aa9cd6394ab16e07471463773872e061d8f8c0b7 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 19 Dec 2023 16:01:38 +0100 Subject: [PATCH 1/4] T2: Enable LDPC encoding offload for all MCS - Rate matching performed by card - Due to rate matching on card, small TBs are encoded correctly, so the limitation of encoding small TBs in CPU can be lifted (all TBs encoded on T2), see a later commits --- .../nrLDPC_decoder/nrLDPC_decoder_offload.c | 14 ++++++------- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 21 ++++--------------- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c index 1f2163ca5e..eac85186f7 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c @@ -568,14 +568,14 @@ static void set_ldpc_enc_op(struct rte_bbdev_enc_op **ops, { // struct rte_bbdev_op_ldpc_enc *ldpc_enc = &ref_op->ldpc_enc; for (int i = 0; i < n; ++i) { - ops[i]->ldpc_enc.cb_params.e = 3 * p_offloadParams->E; // Fix mee: what is the correct size for "e" ??? + ops[i]->ldpc_enc.cb_params.e = p_offloadParams->E; ops[i]->ldpc_enc.basegraph = p_offloadParams->BG; ops[i]->ldpc_enc.z_c = p_offloadParams->Z; ops[i]->ldpc_enc.q_m = p_offloadParams->Qm; ops[i]->ldpc_enc.n_filler = p_offloadParams->F; ops[i]->ldpc_enc.n_cb = p_offloadParams->n_cb; ops[i]->ldpc_enc.rv_index = p_offloadParams->rv; - ops[i]->ldpc_enc.op_flags = RTE_BBDEV_LDPC_INTERLEAVER_BYPASS; // RTE_BBDEV_LDPC_RATE_MATCH; + ops[i]->ldpc_enc.op_flags = RTE_BBDEV_LDPC_INTERLEAVER_BYPASS | RTE_BBDEV_LDPC_RATE_MATCH; ops[i]->ldpc_enc.code_block_mode = 1; ops[i]->ldpc_enc.output = outputs[start_idx + i]; ops[i]->ldpc_enc.input = inputs[start_idx + i]; @@ -613,7 +613,7 @@ static int retrieve_ldpc_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n, for (i = 0; i < n; ++i) { output = &ops[i]->ldpc_enc.output; m = output->data; - uint16_t data_len = min((384 * 68) / 8, rte_pktmbuf_data_len(m)); // fix me + uint16_t data_len = min((LDPC_MAX_CB_SIZE) / 8, rte_pktmbuf_data_len(m)); // fix me data = m->buf_addr; for (int byte = 0; byte < data_len; byte++) for (int bit = 0; bit < 8; bit++) @@ -1103,10 +1103,10 @@ int32_t LDPCencoder(unsigned char **input, unsigned char **output, encoder_imple .n_cb = (BG == 1) ? (66 * Zc) : (50 * Zc), .BG = BG, .Z = Zc, - .rv = 0, //impp->rv, - .F = 0, //impp->F, + .rv = impp->rv, + .F = impp->F, .Qm = impp->Qm, - .Kr = impp->Kr}; + .Kr = (impp->K - impp->F + 7)/8}; struct rte_bbdev_info info; rte_bbdev_info_get(ad->dev_id, &info); int socket_id = GET_SOCKET(info.socket_id); @@ -1126,7 +1126,7 @@ int32_t LDPCencoder(unsigned char **input, unsigned char **output, encoder_imple for (enum op_data_type type = DATA_INPUT; type < 3; type += 2) { int ret = init_op_data_objs(*queue_ops[type], *input, - (offloadParams.Kr + 7) / 8, + offloadParams.Kr, m_head[type], mbuf_pools[type], 1, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 04a320be24..730aee9377 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -363,7 +363,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, impp.tparity = tparity; impp.toutput = toutput; impp.harq = harq; - if (gNB->ldpc_offload_flag && *rel15->mcsIndex > 2) { + if (gNB->ldpc_offload_flag) { impp.Qm = rel15->qamModOrder[0]; impp.rv = rel15->rvIndex[0]; int nb_re_dmrs = @@ -375,25 +375,12 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, harq->unav_res, rel15->qamModOrder[0], rel15->nrOfLayers); - uint8_t tmp[68 * 384] __attribute__((aligned(32))); - uint8_t *d = tmp; + uint8_t tmp[BBDEV_LDPC_MAX_E] __attribute__((aligned(32))); + uint8_t *e = tmp; int r_offset = 0; for (int r = 0; r < impp.n_segments; r++) { impp.E = nr_get_E(impp.G, impp.n_segments, impp.Qm, rel15->nrOfLayers, r); - impp.Kr = impp.K; - ldpc_interface_offload.LDPCencoder(&harq->c[r], &d, &impp); - uint8_t e[impp.E]; - bzero(e, impp.E); - nr_rate_matching_ldpc(rel15->maintenance_parms_v3.tbSizeLbrmBytes, - impp.BG, - impp.Zc, - tmp, - e, - impp.n_segments, - impp.F, - impp.K - impp.F - 2 * impp.Zc, - impp.rv, - impp.E); + ldpc_interface_offload.LDPCencoder(&harq->c[r], &e, &impp); nr_interleaving_ldpc(impp.E, impp.Qm, e, impp.output + r_offset); r_offset += impp.E; } From ce659915ec7891a184ce7df380485ae0cd2214e5 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 19 Dec 2023 19:46:55 +0100 Subject: [PATCH 2/4] Enable T2 encoding offload with rate matching on the UE side - cleanup of the UE encoder code - support rate matching on the T2 card - remove unused code --- .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 272 +++++++----------- 1 file changed, 97 insertions(+), 175 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index fadd7d6ac6..ff84a42f47 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -51,41 +51,38 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, start_meas(&ue->ulsch_encoding_stats); /////////////////////////parameters and variables initialization///////////////////////// -/////////// unsigned int crc = 1; NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; uint16_t nb_rb = ulsch->pusch_pdu.rb_size; uint32_t A = tb_size << 3; - uint8_t mod_order = ulsch->pusch_pdu.qam_mod_order; - uint16_t Kr = 0; uint32_t r_offset = 0; - uint32_t F = 0; // target_code_rate is in 0.1 units float Coderate = (float) ulsch->pusch_pdu.target_code_rate / 10240.0f; - -/////////// + encoder_implemparams_t impp = {.n_segments = harq_process->C, + .macro_num = 0, + .K = harq_process->K, + .Kr = harq_process->K, + .Zc = harq_process->Z, + .BG = harq_process->BG, + .F = harq_process->F, + .rv = ulsch->pusch_pdu.pusch_data.rv_index, + .Qm = ulsch->pusch_pdu.qam_mod_order, + .tinput = NULL, + .tprep = NULL, + .tparity = NULL, + .toutput = NULL}; ///////////////////////////////////////////////////////////////////////////////////////// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN); - LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, ulsch->pusch_pdu.nrOfLayers); - LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G, mod_order, Coderate); + LOG_D(NR_PHY, "ulsch coding A %d G %d mod_order %d Coderate %f\n", A, G, impp.Qm, Coderate); LOG_D(NR_PHY, "harq_pid %d, pusch_data.new_data_indicator %d\n", harq_pid, ulsch->pusch_pdu.pusch_data.new_data_indicator); if (ulsch->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet #ifdef DEBUG_ULSCH_CODING - printf("encoding thinks this is a new packet \n"); + printf("encoding thinks this is a new packet \n"); #endif ///////////////////////// a---->| add CRC |---->b ///////////////////////// -/////////// - /* - int i; - printf("ulsch (tx): \n"); - for (i=0;i<(A>>3);i++) - printf("%02x.",harq_process->a[i]); - printf("\n"); - */ - int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers*1056; int B; if (A > NR_MAX_PDSCH_TBS) { @@ -94,221 +91,146 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, harq_process->a[A>>3] = ((uint8_t*)&crc)[2]; harq_process->a[1+(A>>3)] = ((uint8_t*)&crc)[1]; harq_process->a[2+(A>>3)] = ((uint8_t*)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); - B = A + 24; - AssertFatal((A/8)+4 <= max_payload_bytes,"A %d is too big (A/8+4 = %d > %d)\n",A,(A/8)+4,max_payload_bytes); - memcpy(harq_process->b,harq_process->a,(A/8)+4); } else { // Add 16-bit crc (polynomial A) to payload crc = crc16(harq_process->a,A)>>16; harq_process->a[A>>3] = ((uint8_t*)&crc)[1]; harq_process->a[1+(A>>3)] = ((uint8_t*)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); - B = A + 16; - AssertFatal((A/8)+3 <= max_payload_bytes,"A %d is too big (A/8+3 = %d > %d)\n",A,(A/8)+3,max_payload_bytes); - memcpy(harq_process->b,harq_process->a,(A/8)+3); // using 3 bytes to mimic the case of 24 bit crc } -/////////// -/////////////////////////////////////////////////////////////////////////// ///////////////////////// b---->| block segmentation |---->c ///////////////////////// -/////////// harq_process->BG = ulsch->pusch_pdu.ldpcBaseGraph; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN); start_meas(&ue->ulsch_segmentation_stats); - uint32_t Kb = nr_segmentation(harq_process->b, - harq_process->c, - B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F, - harq_process->BG); - - if (harq_process->C>MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers) { - LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", harq_process->C, B); + impp.Kb = nr_segmentation(harq_process->b, + harq_process->c, + B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F, + harq_process->BG); + impp.n_segments = harq_process->C; + impp.K = harq_process->K; + impp.Kr = impp.K; + impp.Zc = harq_process->Z; + impp.F = harq_process->F; + impp.BG = harq_process->BG; + if (impp.n_segments > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers) { + LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B); return(-1); } stop_meas(&ue->ulsch_segmentation_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT); - F = harq_process->F; - Kr = harq_process->K; #ifdef DEBUG_ULSCH_CODING uint16_t Kr_bytes; - Kr_bytes = Kr>>3; + Kr_bytes = impp.Kr>>3; #endif -///////////////////////// c---->| LDCP coding |---->d ///////////////////////// -/////////// - - // printf("segment Z %d k %d Kr %d BG %d\n", harq_process->Z,harq_process->K,Kr,BG); - - //start_meas(te_stats); - for (int r=0; rC; r++) { - //channel_input[r] = &harq_process->d[r][0]; +///////////////////////// c---->| LDCP coding |---->d //////////////////////////////////// + for (int r = 0; r < impp.n_segments; r++) { #ifdef DEBUG_ULSCH_CODING - printf("Encoder: B %d F %d \n", B, harq_process->F); - printf("start ldpc encoder segment %d/%d\n",r,harq_process->C); + printf("Encoder: B %d F %d \n", B, impp.F); + printf("start ldpc encoder segment %d/%d\n", r, impp.n_segments); printf("input %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]); - for (int cnt = 0; cnt < 22 * harq_process->Z / 8; cnt++) { + for (int cnt = 0; cnt < 22 * impp.Zc / 8; cnt++) { printf("%d ", harq_process->c[r][cnt]); } printf("\n"); - #endif - //ldpc_encoder_orig((unsigned char*)harq_process->c[r],harq_process->d[r],Kr,BG,0); - //ldpc_encoder_optim((unsigned char*)harq_process->c[r],(unsigned char*)&harq_process->d[r][0],Kr,BG,NULL,NULL,NULL,NULL); } - - //for (int i=0;i<68*384;i++) - // printf("channel_input[%d]=%d\n",i,channel_input[i]); - - /*printf("output %d %d %d %d %d \n", harq_process->d[0][0], harq_process->d[0][1], harq_process->d[r][2],harq_process->d[0][3], - harq_process->d[0][4]); for (int cnt =0 ; cnt < 66*harq_process->Z; cnt ++){ printf("%d \n", harq_process->d[0][cnt]); - } - printf("\n");*/ - encoder_implemparams_t impp = {.n_segments = harq_process->C, - .macro_num = 0, - .K = harq_process->K, - .Kb = Kb, - .Zc = harq_process->Z, - .BG = harq_process->BG, - .tinput = NULL, - .tprep = NULL, - .tparity = NULL, - .toutput = NULL}; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN); - - start_meas(&ue->ulsch_ldpc_encoding_stats); - if (ldpc_interface_offload.LDPCencoder) - for (int j = 0; j < harq_process->C; j++) { + } + start_meas(&ue->ulsch_ldpc_encoding_stats); + if (ldpc_interface_offload.LDPCencoder) { + uint8_t tmp[BBDEV_LDPC_MAX_E] __attribute__((aligned(32))); + uint8_t *e = tmp; + for (int j = 0; j < impp.n_segments; j++) { + impp.E = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, j); + ldpc_interface_offload.LDPCencoder(&harq_process->c[j], &e, &impp); + nr_interleaving_ldpc(impp.E, impp.Qm, e, harq_process->f + r_offset); + r_offset += impp.E; + } + } else { + if (ulsch->pusch_pdu.pusch_data.new_data_indicator) { + for (int j = 0; j < (impp.n_segments / 8 + 1); j++) { impp.macro_num = j; - impp.E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, j); - impp.Kr = Kr; - ldpc_interface_offload.LDPCencoder(&harq_process->c[j], &harq_process->d[j], &impp); - } - else - for (int j = 0; j < (harq_process->C / 8 + 1); j++) { - impp.macro_num = j; - impp.E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, j); - impp.Kr = Kr; + impp.E = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, j); + impp.Kr = impp.K; ldpc_interface.LDPCencoder(harq_process->c, harq_process->d, &impp); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT); - //stop_meas(te_stats); - //printf("end ldpc encoder -- output\n"); #ifdef DEBUG_ULSCH_CODING - write_output("ulsch_enc_input0.m","enc_in0",&harq_process->c[0][0],Kr_bytes,1,4); - write_output("ulsch_enc_output0.m","enc0",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,4); + write_output("ulsch_enc_input0.m","enc_in0",&harq_process->c[0][0],Kr_bytes,1,4); + write_output("ulsch_enc_output0.m","enc0",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,4); #endif - -/////////// -/////////////////////////////////////////////////////////////////////////////// - } - F = harq_process->F; - Kr = harq_process->K; - - for (int r=0; rC; r++) { // looping over C segments - if (harq_process->F>0) { - for (int k = Kr - F - 2 * harq_process->Z; k < Kr - 2 * harq_process->Z; k++) { - harq_process->d[r][k] = NR_NULL; - //if (k<(Kr-F+8)) - //printf("r %d filler bits [%d] = %d \n", r,k, harq_process->d[r][k]); - } } +/////////////////////////////////////////////////////////////////////////////// + for (int r = 0; r < impp.n_segments; r++) { // looping over C segments + if (impp.F > 0) { + for (int k = impp.Kr - impp.F - 2 * impp.Zc; k < impp.Kr - 2 * impp.Zc; k++) { + harq_process->d[r][k] = NR_NULL; + } + } + LOG_D(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n", r, G, impp.Kr*3, impp.Qm, nb_rb, ulsch->pusch_pdu.pusch_data.rv_index); - LOG_D(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n", - r, - G, - Kr*3, - mod_order,nb_rb, - ulsch->pusch_pdu.pusch_data.rv_index); - - //start_meas(rm_stats); ///////////////////////// d---->| Rate matching bit selection |---->e ///////////////////////// -/////////// - - uint32_t E = nr_get_E(G, harq_process->C, mod_order, ulsch->pusch_pdu.nrOfLayers, r); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN); - start_meas(&ue->ulsch_rate_matching_stats); - if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm, - harq_process->BG, - harq_process->Z, - harq_process->d[r], - harq_process->e + r_offset, - harq_process->C, - F, - Kr - F - 2 * harq_process->Z, - ulsch->pusch_pdu.pusch_data.rv_index, - E) - == -1) - return -1; - - stop_meas(&ue->ulsch_rate_matching_stats); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_OUT); + impp.E = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, r); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN); + start_meas(&ue->ulsch_rate_matching_stats); + if (nr_rate_matching_ldpc(ulsch->pusch_pdu.tbslbrm, + impp.BG, + impp.Zc, + harq_process->d[r], + harq_process->e + r_offset, + impp.n_segments, + impp.F, + impp.Kr - impp.F - 2 * impp.Zc, + impp.rv, + impp.E) == -1) + return -1; + stop_meas(&ue->ulsch_rate_matching_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_OUT); #ifdef DEBUG_ULSCH_CODING - for (int i =0; i<16; i++) - printf("output ratematching e[%d]= %d r_offset %u\n", i,harq_process->e[i+r_offset], r_offset); + for (int i =0; i<16; i++) + printf("output ratematching e[%d]= %d r_offset %u\n", i,harq_process->e[i + r_offset], r_offset); #endif -/////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - - ///////////////////////// e---->| Rate matching bit interleaving |---->f ///////////////////////// -/////////// - - //stop_meas(rm_stats); - - //start_meas(i_stats); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_IN); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_IN); + start_meas(&ue->ulsch_interleaving_stats); + nr_interleaving_ldpc(impp.E, + impp.Qm, + harq_process->e + r_offset, + harq_process->f + r_offset); + stop_meas(&ue->ulsch_interleaving_stats); - start_meas(&ue->ulsch_interleaving_stats); - nr_interleaving_ldpc(E, - mod_order, - harq_process->e+r_offset, - harq_process->f+r_offset); - stop_meas(&ue->ulsch_interleaving_stats); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_OUT); - //stop_meas(i_stats); - - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_OUT); #ifdef DEBUG_ULSCH_CODING - for (int i =0; i<16; i++) - printf("output interleaving f[%d]= %d r_offset %u\n", i,harq_process->f[i+r_offset], r_offset); - - if (r==harq_process->C-1) - write_output("enc_output.m","enc",harq_process->f,G,1,4); + for (int i = 0; i < 16; i++) + printf("output interleaving f[%d]= %d r_offset %u\n", i, harq_process->f[i+r_offset], r_offset); + if (r == impp.n_segments - 1) + write_output("enc_output.m","enc", harq_process->f, G, 1, 4); #endif - - r_offset += E; - -/////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - + r_offset += impp.E; + } } - +/////////////////////////////////////////////////////////////////////////////////////////////// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_OUT); - stop_meas(&ue->ulsch_encoding_stats); return(0); } From bec8ebc311ec89a185ef8cfb6955decdd32a4ef4 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 20 Dec 2023 15:33:58 +0100 Subject: [PATCH 3/4] Perform interleaving on the T2 card - UE and gNB encoder modification - update T2 related doc --- doc/LDPC_T2_OFFLOAD_SETUP.md | 3 +-- .../nrLDPC_decoder/nrLDPC_decoder_offload.c | 2 +- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 15 ++++----------- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 6 ++---- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/doc/LDPC_T2_OFFLOAD_SETUP.md b/doc/LDPC_T2_OFFLOAD_SETUP.md index 485ad4c4a4..d6335ecbaf 100644 --- a/doc/LDPC_T2_OFFLOAD_SETUP.md +++ b/doc/LDPC_T2_OFFLOAD_SETUP.md @@ -62,7 +62,7 @@ sudo python3 ~/dpdk-stable/usertools/dpdk-devbind.py --bind=vfio-pci 41:00.0 Replace PCI address of the card *41:00.0* by address detected by *lspci | grep "Xilinx"* command - hugepages setup (10 x 1GB hugepages) ``` -sudo python3 ~/dpdk-stable/usertools/dpdk-hugepages.py -p 1G --setup 10G` +sudo python3 ~/dpdk-stable/usertools/dpdk-hugepages.py -p 1G --setup 10G ``` *Note: device binding and hugepages setup has to be done after every reboot of @@ -144,7 +144,6 @@ sudo ./nr-softmodem --sa -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa # Limitations ## AMD Xilinx T2 card - - offload of the LDPC encoding implemented for MCS > 2, OAI CPU encoder is used for MCS =< 2 - functionality of the LDPC encoding and decoding offload verified in OTA SISO setup with USRP N310 and Quectel RM500Q, blocking of the card reported for MIMO setup (2 layers) *Note: AMD Xilinx T1 Telco card is not supported anymore.* diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c index eac85186f7..79e6d04fb5 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c @@ -575,7 +575,7 @@ static void set_ldpc_enc_op(struct rte_bbdev_enc_op **ops, ops[i]->ldpc_enc.n_filler = p_offloadParams->F; ops[i]->ldpc_enc.n_cb = p_offloadParams->n_cb; ops[i]->ldpc_enc.rv_index = p_offloadParams->rv; - ops[i]->ldpc_enc.op_flags = RTE_BBDEV_LDPC_INTERLEAVER_BYPASS | RTE_BBDEV_LDPC_RATE_MATCH; + ops[i]->ldpc_enc.op_flags = RTE_BBDEV_LDPC_RATE_MATCH; ops[i]->ldpc_enc.code_block_mode = 1; ops[i]->ldpc_enc.output = outputs[start_idx + i]; ops[i]->ldpc_enc.input = inputs[start_idx + i]; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 730aee9377..d790072390 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -368,20 +368,13 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, impp.rv = rel15->rvIndex[0]; int nb_re_dmrs = (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData); - impp.G = nr_get_G(rel15->rbSize, - rel15->NrOfSymbols, - nb_re_dmrs, - get_num_dmrs(rel15->dlDmrsSymbPos), - harq->unav_res, - rel15->qamModOrder[0], - rel15->nrOfLayers); - uint8_t tmp[BBDEV_LDPC_MAX_E] __attribute__((aligned(32))); - uint8_t *e = tmp; + impp.G = nr_get_G(rel15->rbSize, rel15->NrOfSymbols, nb_re_dmrs, get_num_dmrs(rel15->dlDmrsSymbPos), harq->unav_res, + rel15->qamModOrder[0], rel15->nrOfLayers); int r_offset = 0; for (int r = 0; r < impp.n_segments; r++) { impp.E = nr_get_E(impp.G, impp.n_segments, impp.Qm, rel15->nrOfLayers, r); - ldpc_interface_offload.LDPCencoder(&harq->c[r], &e, &impp); - nr_interleaving_ldpc(impp.E, impp.Qm, e, impp.output + r_offset); + uint8_t *f = impp.output + r_offset; + ldpc_interface_offload.LDPCencoder(&harq->c[r], &f, &impp); r_offset += impp.E; } } else { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index ff84a42f47..927c1fa12e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -152,12 +152,10 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, } start_meas(&ue->ulsch_ldpc_encoding_stats); if (ldpc_interface_offload.LDPCencoder) { - uint8_t tmp[BBDEV_LDPC_MAX_E] __attribute__((aligned(32))); - uint8_t *e = tmp; for (int j = 0; j < impp.n_segments; j++) { impp.E = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, j); - ldpc_interface_offload.LDPCencoder(&harq_process->c[j], &e, &impp); - nr_interleaving_ldpc(impp.E, impp.Qm, e, harq_process->f + r_offset); + uint8_t *f = harq_process->f + r_offset; + ldpc_interface_offload.LDPCencoder(&harq_process->c[j], &f, &impp); r_offset += impp.E; } } else { From b166286a7834b2cfe7db6ee18ad99bda8a017f2c Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 25 Jan 2024 09:52:22 +0100 Subject: [PATCH 4/4] Use clang format --- .../nrLDPC_decoder/nrLDPC_decoder_offload.c | 2 +- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 9 ++- .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 59 +++++++++++-------- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c index 79e6d04fb5..dafdf28644 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder_offload.c @@ -1106,7 +1106,7 @@ int32_t LDPCencoder(unsigned char **input, unsigned char **output, encoder_imple .rv = impp->rv, .F = impp->F, .Qm = impp->Qm, - .Kr = (impp->K - impp->F + 7)/8}; + .Kr = (impp->K - impp->F + 7) / 8}; struct rte_bbdev_info info; rte_bbdev_info_get(ad->dev_id, &info); int socket_id = GET_SOCKET(info.socket_id); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index d790072390..07dabe07e1 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -368,8 +368,13 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, impp.rv = rel15->rvIndex[0]; int nb_re_dmrs = (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) ? (6 * rel15->numDmrsCdmGrpsNoData) : (4 * rel15->numDmrsCdmGrpsNoData); - impp.G = nr_get_G(rel15->rbSize, rel15->NrOfSymbols, nb_re_dmrs, get_num_dmrs(rel15->dlDmrsSymbPos), harq->unav_res, - rel15->qamModOrder[0], rel15->nrOfLayers); + impp.G = nr_get_G(rel15->rbSize, + rel15->NrOfSymbols, + nb_re_dmrs, + get_num_dmrs(rel15->dlDmrsSymbPos), + harq->unav_res, + rel15->qamModOrder[0], + rel15->nrOfLayers); int r_offset = 0; for (int r = 0; r < impp.n_segments; r++) { impp.E = nr_get_E(impp.G, impp.n_segments, impp.Qm, rel15->nrOfLayers, r); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 927c1fa12e..fa9d692751 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -50,7 +50,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, { start_meas(&ue->ulsch_encoding_stats); -/////////////////////////parameters and variables initialization///////////////////////// + /////////////////////////parameters and variables initialization///////////////////////// unsigned int crc = 1; NR_UL_UE_HARQ_t *harq_process = &ue->ul_harq_processes[harq_pid]; @@ -72,7 +72,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, .tprep = NULL, .tparity = NULL, .toutput = NULL}; -///////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_IN); LOG_D(NR_PHY, "ulsch coding nb_rb %d, Nl = %d\n", nb_rb, ulsch->pusch_pdu.nrOfLayers); @@ -82,7 +82,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, #ifdef DEBUG_ULSCH_CODING printf("encoding thinks this is a new packet \n"); #endif -///////////////////////// a---->| add CRC |---->b ///////////////////////// + ///////////////////////// a---->| add CRC |---->b ///////////////////////// int max_payload_bytes = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers*1056; int B; if (A > NR_MAX_PDSCH_TBS) { @@ -90,41 +90,41 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, crc = crc24a(harq_process->a,A)>>8; harq_process->a[A>>3] = ((uint8_t*)&crc)[2]; harq_process->a[1+(A>>3)] = ((uint8_t*)&crc)[1]; - harq_process->a[2+(A>>3)] = ((uint8_t*)&crc)[0]; + harq_process->a[2 + (A >> 3)] = ((uint8_t *)&crc)[0]; B = A + 24; - AssertFatal((A/8)+4 <= max_payload_bytes,"A %d is too big (A/8+4 = %d > %d)\n",A,(A/8)+4,max_payload_bytes); + AssertFatal((A / 8) + 4 <= max_payload_bytes, "A %d is too big (A/8+4 = %d > %d)\n", A, (A / 8) + 4, max_payload_bytes); memcpy(harq_process->b,harq_process->a,(A/8)+4); } else { // Add 16-bit crc (polynomial A) to payload crc = crc16(harq_process->a,A)>>16; harq_process->a[A>>3] = ((uint8_t*)&crc)[1]; - harq_process->a[1+(A>>3)] = ((uint8_t*)&crc)[0]; + harq_process->a[1 + (A >> 3)] = ((uint8_t *)&crc)[0]; B = A + 16; - AssertFatal((A/8)+3 <= max_payload_bytes,"A %d is too big (A/8+3 = %d > %d)\n",A,(A/8)+3,max_payload_bytes); + AssertFatal((A / 8) + 3 <= max_payload_bytes, "A %d is too big (A/8+3 = %d > %d)\n", A, (A / 8) + 3, max_payload_bytes); memcpy(harq_process->b,harq_process->a,(A/8)+3); // using 3 bytes to mimic the case of 24 bit crc } -///////////////////////// b---->| block segmentation |---->c ///////////////////////// + ///////////////////////// b---->| block segmentation |---->c ///////////////////////// harq_process->BG = ulsch->pusch_pdu.ldpcBaseGraph; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN); start_meas(&ue->ulsch_segmentation_stats); impp.Kb = nr_segmentation(harq_process->b, - harq_process->c, - B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F, - harq_process->BG); + harq_process->c, + B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F, + harq_process->BG); impp.n_segments = harq_process->C; impp.K = harq_process->K; impp.Kr = impp.K; impp.Zc = harq_process->Z; impp.F = harq_process->F; impp.BG = harq_process->BG; - if (impp.n_segments > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*ulsch->pusch_pdu.nrOfLayers) { + if (impp.n_segments > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * ulsch->pusch_pdu.nrOfLayers) { LOG_E(PHY, "nr_segmentation.c: too many segments %d, B %d\n", impp.n_segments, B); return(-1); } @@ -133,10 +133,10 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, #ifdef DEBUG_ULSCH_CODING uint16_t Kr_bytes; - Kr_bytes = impp.Kr>>3; + Kr_bytes = impp.Kr >> 3; #endif -///////////////////////// c---->| LDCP coding |---->d //////////////////////////////////// + ///////////////////////// c---->| LDCP coding |---->d //////////////////////////////////// for (int r = 0; r < impp.n_segments; r++) { #ifdef DEBUG_ULSCH_CODING printf("Encoder: B %d F %d \n", B, impp.F); @@ -169,8 +169,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT); #ifdef DEBUG_ULSCH_CODING - write_output("ulsch_enc_input0.m","enc_in0",&harq_process->c[0][0],Kr_bytes,1,4); - write_output("ulsch_enc_output0.m","enc0",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,4); + write_output("ulsch_enc_input0.m", "enc_in0", &harq_process->c[0][0], Kr_bytes, 1, 4); + write_output("ulsch_enc_output0.m", "enc0", &harq_process->d[0][0], (3 * 8 * Kr_bytes) + 12, 1, 4); #endif } /////////////////////////////////////////////////////////////////////////////// @@ -181,9 +181,18 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, } } - LOG_D(PHY,"Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb %d, rvidx %d)...\n", r, G, impp.Kr*3, impp.Qm, nb_rb, ulsch->pusch_pdu.pusch_data.rv_index); + LOG_D(PHY, + "Rate Matching, Code segment %d (coded bits (G) %u, unpunctured/repeated bits per code segment %d, mod_order %d, nb_rb " + "%d, " + "rvidx %d)...\n", + r, + G, + impp.Kr * 3, + impp.Qm, + nb_rb, + ulsch->pusch_pdu.pusch_data.rv_index); -///////////////////////// d---->| Rate matching bit selection |---->e ///////////////////////// + ///////////////////////// d---->| Rate matching bit selection |---->e ///////////////////////// impp.E = nr_get_E(G, impp.n_segments, impp.Qm, ulsch->pusch_pdu.nrOfLayers, r); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN); @@ -204,8 +213,8 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_OUT); #ifdef DEBUG_ULSCH_CODING - for (int i =0; i<16; i++) - printf("output ratematching e[%d]= %d r_offset %u\n", i,harq_process->e[i + r_offset], r_offset); + for (int i = 0; i < 16; i++) + printf("output ratematching e[%d]= %d r_offset %u\n", i, harq_process->e[i + r_offset], r_offset); #endif ///////////////////////// e---->| Rate matching bit interleaving |---->f ///////////////////////// @@ -227,7 +236,7 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, r_offset += impp.E; } } -/////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_OUT); stop_meas(&ue->ulsch_encoding_stats); return(0);