Commit 79c8d932 authored by Guy De Souza's avatar Guy De Souza

ceil/round macros- TBS calculation corrections

parent 4e485019
......@@ -508,8 +508,8 @@ typedef struct {
uint8_t S;
uint8_t L;
uint8_t Imcs;
uint8_t n_codewords;
uint8_t n_layers;
uint8_t nb_codewords;
uint8_t nb_layers;
/*uint8_t R;
uint8_t Qm;
uint16_t TBS;
......
......@@ -35,6 +35,9 @@
#define DEBUG_DLSCH
uint8_t mod_order[5] = {1, 2, 4, 6, 8};
uint16_t mod_offset[5] = {1,3,7,23,87};
void nr_pdsch_codeword_scrambling(uint32_t *in,
uint8_t size,
uint8_t q,
......@@ -189,11 +192,11 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch,
NR_DL_gNB_HARQ_t *harq = dlsch.harq_processes[dci_alloc.harq_pid];
nfapi_nr_dl_config_dlsch_pdu_rel15_t *rel15 = &harq->dlsch_pdu.dlsch_pdu_rel15;
nfapi_nr_dl_config_pdcch_parameters_rel15_t pdcch_params = dci_alloc.pdcch_params;
uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH]={0};
uint16_t mod_symbs[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>1] = {0};
uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH];
int16_t mod_symbs[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>1];
uint16_t tx_layers[NR_MAX_NB_LAYERS][NR_MAX_PDSCH_ENCODED_LENGTH>>1];
uint16_t n_symbs[NR_MAX_NB_CODEWORDS] = {0};
int8_t Wf[2], Wt[2], l0[2], delta;
uint16_t n_symbs[NR_MAX_NB_CODEWORDS];
int8_t Wf[2], Wt[2], l0, delta;
/// CRC, coding, interleaving and rate matching
......@@ -229,9 +232,9 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch,
/// DMRS QPSK modulation
uint16_t n_dmrs = rel15->n_prb<<1;
uint16_t mod_dmrs[n_dmrs<<1] = {0};
int16_t mod_dmrs[n_dmrs<<1];
uint8_t dmrs_type = config.pdsch_config.dmrs_type.value;
nr_modulation(pdsch_dmrs, n_dmrs, QPSK, mod_dmrs);
nr_modulation(pdsch_dmrs, n_dmrs, MOD_QPSK, mod_dmrs);
/// Resource mapping
AssertFatal(harq->Nl<=config.rf_config.tx_antenna_ports.value, "Not enough Tx antennas (%d) for %d layers\n",\
......@@ -245,8 +248,8 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch,
for (int ap=0; ap<rel15->nb_layers; ap++) {
// DMRS params for this ap
Wt = get_Wt(ap, dmrs_type);
Wf = get_Wf(ap, dmrs_type);
get_Wt(Wt, ap, dmrs_type);
get_Wf(Wf, ap, dmrs_type);
l0 = get_l0(0, config.pdsch_config.dmrs_typeA_position.value);
delta = get_delta(ap, dmrs_type);
uint8_t k_prime=0, n=0, dmrs_idx=0;
......@@ -258,11 +261,12 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch,
k -= frame_parms.ofdm_symbol_size;
if ((l==l0) && (k == ((dmrs_type)? (6*n+k_prime+delta):((n<<2)+(k_prime<<1)+delta)))) {
((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (Wt*Wf*amp*mod_dmrs[dmrs_idx<<1]) >> 15;
((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (Wt*Wf*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
mod_dmrs++;
((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (Wt[k_prime]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15;
((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (Wt[k_prime]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
dmrs_idx++;
n++;
k_prime = (++k_prime)&1;
k_prime++;
k_prime&=1;
}
((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (amp * tx_layers[ap][m<<1]) >> 15;
......
......@@ -56,9 +56,10 @@ uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx);
uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx);
void nr_get_tbs(nfapi_nr_dl_config_dlsch_pdu *dlsch_pdu,
nfapi_nr_dl_config_dci_dl_pdu dci_pdu,
nfapi_nr_config_request_t config);
void nr_get_tbs(NR_gNB_DLSCH_t *dlsch,
nfapi_nr_dl_config_dci_dl_pdu dci_pdu,
nfapi_nr_config_request_t config,
uint8_t harq_pid);
void nr_pdsch_codeword_scrambling(uint32_t *in,
uint8_t size,
......
......@@ -33,8 +33,6 @@
#include "nr_sch_dmrs.h"
/*Table 7.4.1.1.2-1 and 7.4.1.1.2-2 38211 Columns: ap - CDM group - Delta - Wf(0) - Wf(1) - Wt(0) - Wt(1)*/
int8_t pdsch_dmrs_1[8][7] = {{0,0,0,1,1,1,1},
{1,0,0,1,-1,1,1},
......@@ -76,24 +74,20 @@ static inline void *get_antenna_ports(uint8_t n_symbs, uint8_t config) {
return ap;
}
int8_t *get_Wt(uint8_t ap, uint8_t config) {
int8_t *Wt;
void get_Wt(int8_t *Wt, uint8_t ap, uint8_t config) {
for (int i=0; i<2; i++)
*(Wt+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][3+i]):(pdsch_dmrs_2[ap][3+i]);
return Wt;
}
int8_t *get_Wf(uint8_t ap, uint8_t config) {
int8_t *Wf;
void *get_Wf(int8_t *Wf, uint8_t ap, uint8_t config) {
for (int i=0; i<2; i++)
*(Wf+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][5+i]):(pdsch_dmrs_2[ap][5+i]);
return Wf;
}
uint8_t get_delta(uint8_t ap, uint8_t config) {
return ((config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][2]):(pdsch_dmrs_2[ap][2]));
}
uint8_t *get_l0(uint8_t config, uint8_t dmrs_typeA_position) {
uint8_t get_l0(uint8_t config, uint8_t dmrs_typeA_position) {
return ((config==NFAPI_NR_DMRS_TYPE1)?dmrs_typeA_position:0);
}
......@@ -35,10 +35,10 @@
#define NR_PDSCH_DMRS_ANTENNA_PORT0 1000
#define NR_PDSCH_DMRS_NB_ANTENNA_PORTS 12
int8_t *get_Wt(uint8_t ap, uint8_t config);
void get_Wt(int8_t *Wt, uint8_t ap, uint8_t config);
int8_t *get_Wf(uint8_t ap, uint8_t config);
void get_Wf(int8_t *Wf, uint8_t ap, uint8_t config);
uint8_t get_delta(uint8_t ap, uint8_t config);
uint8_t *get_l0(uint8_t config, uint8_t dmrs_typeA_position);
uint8_t get_l0(uint8_t config, uint8_t dmrs_typeA_position);
......@@ -35,9 +35,9 @@
/// Target code rate tables indexed by Imcs
uint16_t nr_target_code_rate_table1[29] = {120, 157, 193, 251, 308, 379, 449, 526, 602, 679, 340, 378, 434, 490, 553, \
616, 658, 438, 466, 517, 567, 616, 666, 719, 772, 822, 873, 910, 948};
// The -1 values correspond to non integer factors which are handled differently for indexes 20(682.5) and 26(916.5)
// Imcs values 20 and 26 have been multiplied by 2 to avoid the floating point
uint16_t nr_target_code_rate_table2[28] = {120, 193, 308, 449, 602, 378, 434, 490, 553, 616, 658, 466, 517, 567, \
616, 666, 719, 772, 822, 873, -1, 711, 754, 797, 841, 885, -1, 948};
616, 666, 719, 772, 822, 873, 1365, 711, 754, 797, 841, 885, 1833, 948};
uint16_t nr_target_code_rate_table3[29] = {30, 40, 50, 64, 78, 99, 120, 157, 193, 251, 308, 379, 449, 526, 602, 340, \
378, 434, 490, 553, 616, 438, 466, 517, 567, 616, 666, 719, 772};
uint16_t nr_tbs_table[93] = {24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 208, 224, 240, 256, 272, 288, 304, 320, \
......@@ -67,15 +67,15 @@ uint8_t nr_get_Qm(uint8_t Imcs, uint8_t table_idx) {
uint32_t nr_get_code_rate(uint8_t Imcs, uint8_t table_idx) {
switch(table_idx) {
case 1:
return (nr_target_code_rate_table1[Imcs]<<10);
return (nr_target_code_rate_table1[Imcs]);
break;
case 2:
return ((Imcs==20)?0xaaa00 : (Imcs==26)?0xe5200 : nr_target_code_rate_table2[Imcs]<<10);
return (nr_target_code_rate_table2[Imcs]);
break;
case 3:
return (nr_target_code_rate_table3[Imcs]<<10);
return (nr_target_code_rate_table3[Imcs]);
break;
default:
......@@ -87,72 +87,79 @@ static inline uint8_t is_codeword_disabled(uint8_t format, uint8_t Imcs, uint8_t
return ((format==NFAPI_NR_DL_DCI_FORMAT_1_1)&&(Imcs==26)&&(rv==1));
}
static inline uint8_t get_table_idx(uint8_t mcs_table, uint8_t dci_format, uint8_t rnti_type, uint8_t ss_type) {
if ((mcs_table == NFAPI_NR_MCS_TABLE_QAM256) && (dci_format == NFAPI_NR_DL_DCI_FORMAT_1_1) && ((rnti_type==NFAPI_NR_RNTI_C)||(rnti_type==NFAPI_NR_RNTI_CS)))
return 2;
else if ((mcs_table == NFAPI_NR_MCS_TABLE_QAM64_LOW_SE) && (rnti_type!=NFAPI_NR_RNTI_new) && (rnti_type==NFAPI_NR_RNTI_C) && (ss_type==NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC))
return 3;
else if (rnti_type==NFAPI_NR_RNTI_new)
return 3;
else if ((mcs_table == NFAPI_NR_MCS_TABLE_QAM256) && (rnti_type==NFAPI_NR_RNTI_CS) && (dci_format == NFAPI_NR_DL_DCI_FORMAT_1_1))
return 2; // Condition mcs_table not configured in sps_config necessary here but not yet implemented
/*else if((mcs_table == NFAPI_NR_MCS_TABLE_QAM64_LOW_SE) && (rnti_type==NFAPI_NR_RNTI_CS))
* table_idx = 3;
* Note: the commented block refers to the case where the mcs_table is from sps_config*/
else
return 1;
}
void nr_get_tbs(NR_gNB_DLSCH_t *dlsch,
nfapi_nr_dl_config_dci_dl_pdu dci_pdu,
nfapi_nr_config_request_t config) {
uint8_t N_PRB_DMRS=2; // tmp hardcoding
nfapi_nr_config_request_t config,
uint8_t harq_pid) {
nfapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_rel15 = &dlsch->dlsch_pdu.dlsch_pdu_rel15;
nfapi_nr_dl_config_pdcch_parameters_rel15_t params_rel15 = dci_pdu.pdcch_params_rel15;
NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[dlsch_rel15->harq_pid];
NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[harq_pid];
nfapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_rel15 = &harq->dlsch_pdu.dlsch_pdu_rel15;
uint8_t rnti_type = params_rel15.rnti_type;
uint8_t dci_format = params_rel15.dci_format;
uint8_t ss_type = params_rel15.search_space_type;
uint8_t N_PRB_oh = ((rnti_type==NFAPI_NR_RNTI_SI)||(rnti_type==NFAPI_NR_RNTI_RA)||(rnti_type==NFAPI_NR_RNTI_P))? 0 : \
(config.pdsch_config.x_overhead.value);
uint8_t N_PRB_DMRS = (config.pdsch_config.dmrs_type.value == NFAPI_NR_DMRS_TYPE1)?4:6; //This only works for antenna port 1000
uint8_t mcs_table = config.pdsch_config.mcs_table.value;
uint8_t N_sh_symb = dlsch_rel15->L;
uint8_t Imcs = dlsch_rel15->Imcs;
uint16_t N_prime_RE = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS - N_PRB_oh;
LOG_I(MAC, "N_prime_RE %d for %d symbols %d DMRS per PRB and %d overhead\n", N_prime_RE, N_sh_symb, N_PRB_DMRS, N_PRB_oh);
uint16_t N_RE, N_info, N_info_prime;
uint8_t table_idx, R, Qm, n;
float tmp, C; // temporary N_info_prime in float to avoid back and forth casting to int
uint16_t N_RE, Ninfo, Ninfo_prime, C;
uint8_t table_idx, R, Qm, n, scale;
table_idx = get_table_idx(mcs_table, dci_format, rnti_type, ss_type);
scale = 10 + (((table_idx==2)&&((Imcs==20)||(Imcs==26)))?1:0);
N_RE = min(156, N_RE)*dlsch_rel15->n_prb;
if ((mcs_table == NFAPI_NR_MCS_TABLE_QAM256) && (dci_format == NFAPI_NR_DL_DCI_FORMAT_1_1) && ((rnti_type==NFAPI_NR_RNTI_C)||(rnti_type==NFAPI_NR_RNTI_CS)))
table_idx = 2;
else if ((mcs_table == NFAPI_NR_MCS_TABLE_QAM64_LOW_SE) && (rnti_type!=NFAPI_NR_RNTI_new) && (rnti_type==NFAPI_NR_RNTI_C) && (ss_type==NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC))
table_idx = 3;
else if (rnti_type==NFAPI_NR_RNTI_new)
table_idx = 3;
else if ((mcs_table == NFAPI_NR_MCS_TABLE_QAM256) && (rnti_type==NFAPI_NR_RNTI_CS) && (dci_format == NFAPI_NR_DL_DCI_FORMAT_1_1))
table_idx = 2; // Condition mcs_table not configured in sps_config necessary here but not yet implemented
/*else if((mcs_table == NFAPI_NR_MCS_TABLE_QAM64_LOW_SE) && (rnti_type==NFAPI_NR_RNTI_CS))
* table_idx = 3;
* Note: the commented block refers to the case where the mcs_table is from sps_config*/
else
table_idx = 1;
R = nr_get_code_rate(Imcs, table_idx);
Qm = nr_get_Qm(Imcs, table_idx);
N_info = N_RE*R*Qm*harq->Nl;
Ninfo = (N_RE*R*Qm*harq->Nl)>>scale;
if (N_info <= 3824) {
n = max(3, (uint8_t)(floor(log2(N_info)-6)));
N_info_prime = max(24, (N_info>>n)<<n);
if (Ninfo <= 3824) {
n = max(3, (log2(Ninfo)-6));
Ninfo_prime = max(24, (Ninfo>>n)<<n);
for (int i=0; i<93; i++)
if (nr_tbs_table[i] >= N_info_prime) {
if (nr_tbs_table[i] >= Ninfo_prime) {
harq->TBS = nr_tbs_table[i];
break;
}
}
else {
n = (uint8_t)floor(log2(N_info)-24) - 5;
tmp = max(3840, ((uint16_t)round(((float)N_info-24)/(1<<n)))<<n);
n = log2(Ninfo)-29;
Ninfo_prime = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n);
if (R<0.25) {
C = ceil((tmp+24)/3816);
harq->TBS = ((uint16_t)(C*ceil((tmp+24)/(8*C))))<<3;
if (R<256) {
C = CEILIDIV((Ninfo_prime+24),3816);
harq->TBS = (C*CEILIDIV((Ninfo_prime+24),(C<<3)))<<3;
}
else {
if (tmp>8424) {
C = ceil((tmp+24)/8424);
harq->TBS = ((uint16_t)(C*ceil((tmp+24)/(8*C))))<<3;
if (Ninfo_prime>8424) {
C = CEILIDIV((Ninfo_prime+24),8424);
harq->TBS = (C*CEILIDIV((Ninfo_prime+24),(C<<3)))<<3;
}
else
harq->TBS = ((uint16_t)ceil((tmp+24)/8) - 24)<<3;
harq->TBS = (CEILIDIV((Ninfo_prime+24),8) - 24)<<3;
}
}
LOG_I(MAC, "TBS %d : N_RE %d N_PRB_DMRS %d N_sh_symb %d N_PRB_oh %d Ninfo %d Ninfo_prime %d R %d Qm %d table %d scale %d\n",
harq->TBS, N_RE, N_PRB_DMRS, N_sh_symb, N_PRB_oh, Ninfo, Ninfo_prime, R, Qm, table_idx, scale);
}
......@@ -102,6 +102,10 @@
#ifdef OCP_FRAMEWORK
#include "enums.h"
#else
#define CEILIDIV(a,b) ((a+b-1)/b)
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
typedef enum {TDD=1,FDD=0} lte_frame_type_t;
typedef enum {EXTENDED=1,NORMAL=0} lte_prefix_type_t;
......
......@@ -119,11 +119,11 @@ typedef enum {
} nr_frequency_range_e;
typedef enum {
BPSK=0,
QPSK,
QAM16,
QAM64,
QAM256
MOD_BPSK=0,
MOD_QPSK,
MOD_QAM16,
MOD_QAM64,
MOD_QAM256
}nr_mod_t;
typedef struct {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment