Merge remote-tracking branch 'origin/NR_precoding_marix_at_MAC' into integration_2024_w03
This commit is contained in:
+3
-415
@@ -99,408 +99,6 @@ void reset_active_stats(PHY_VARS_gNB *gNB, int frame)
|
||||
}
|
||||
}
|
||||
|
||||
int init_codebook_gNB(PHY_VARS_gNB *gNB) {
|
||||
|
||||
if(gNB->frame_parms.nb_antennas_tx>1){
|
||||
int CSI_RS_antenna_ports = gNB->frame_parms.nb_antennas_tx;
|
||||
//NR Codebook Generation for codebook type1 SinglePanel
|
||||
int N1 = gNB->ap_N1;
|
||||
int N2 = gNB->ap_N2;
|
||||
//Uniform Planner Array: UPA
|
||||
// X X X X ... X
|
||||
// X X X X ... X
|
||||
// N2 . . . . ... .
|
||||
// X X X X ... X
|
||||
// |<-----N1---->|
|
||||
int x_polarization = gNB->ap_XP;
|
||||
//Get the uniform planar array parameters
|
||||
// To be confirmed
|
||||
int O2 = N2 > 1? 4 : 1; //Vertical beam oversampling (1 or 4)
|
||||
int O1 = CSI_RS_antenna_ports > 2 ? 4 : 1; //Horizontal beam oversampling (1 or 4)
|
||||
AssertFatal(CSI_RS_antenna_ports == N1*N2*x_polarization,
|
||||
"Nb of antenna ports at PHY %d does not correspond to what passed down with fapi %d\n",
|
||||
N1*N2*x_polarization, CSI_RS_antenna_ports);
|
||||
|
||||
// Generation of codebook Type1 with codebookMode 1 (CSI_RS_antenna_ports < 16)
|
||||
if (CSI_RS_antenna_ports < 16) {
|
||||
//Generate DFT vertical beams
|
||||
//ll: index of a vertical beams vector (represented by i1_1 in TS 38.214)
|
||||
double complex v[N1*O1][N1];
|
||||
for (int ll=0; ll<N1*O1; ll++) { //i1_1
|
||||
for (int nn=0; nn<N1; nn++) {
|
||||
v[ll][nn] = cexp(I*(2*M_PI*nn*ll)/(N1*O1));
|
||||
//printf("v[%d][%d] = %f +j %f\n", ll,nn, creal(v[ll][nn]),cimag(v[ll][nn]));
|
||||
}
|
||||
}
|
||||
//Generate DFT Horizontal beams
|
||||
//mm: index of a Horizontal beams vector (represented by i1_2 in TS 38.214)
|
||||
double complex u[N2*O2][N2];
|
||||
for (int mm=0; mm<N2*O2; mm++) { //i1_2
|
||||
for (int nn=0; nn<N2; nn++) {
|
||||
u[mm][nn] = cexp(I*(2*M_PI*nn*mm)/(N2*O2));
|
||||
//printf("u[%d][%d] = %f +j %f\n", mm,nn, creal(u[mm][nn]),cimag(u[mm][nn]));
|
||||
}
|
||||
}
|
||||
//Generate co-phasing angles
|
||||
//i_2: index of a co-phasing vector
|
||||
//i1_1, i1_2, and i_2 are reported from UEs
|
||||
double complex theta_n[4];
|
||||
for (int nn=0; nn<4; nn++) {
|
||||
theta_n[nn] = cexp(I*M_PI*nn/2);
|
||||
//printf("theta_n[%d] = %f +j %f\n", nn, creal(theta_n[nn]),cimag(theta_n[nn]));
|
||||
}
|
||||
//Kronecker product v_lm
|
||||
double complex v_lm[N1*O1][N2*O2][N2*N1];
|
||||
//v_ll_mm_codebook denotes the elements of a precoding matrix W_i1,1_i_1,2
|
||||
for(int ll=0; ll<N1*O1; ll++) { //i_1_1
|
||||
for (int mm=0; mm<N2*O2; mm++) { //i_1_2
|
||||
for (int nn1=0; nn1<N1; nn1++) {
|
||||
for (int nn2=0; nn2<N2; nn2++) {
|
||||
//printf("indx %d \n",nn1*N2+nn2);
|
||||
v_lm[ll][mm][nn1*N2+nn2] = v[ll][nn1]*u[mm][nn2];
|
||||
//printf("v_lm[%d][%d][%d] = %f +j %f\n",ll,mm, nn1*N2+nn2, creal(v_lm[ll][mm][nn1*N2+nn2]),cimag(v_lm[ll][mm][nn1*N2+nn2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int max_mimo_layers = (CSI_RS_antenna_ports<NR_MAX_NB_LAYERS) ? CSI_RS_antenna_ports : NR_MAX_NB_LAYERS;
|
||||
|
||||
gNB->nr_mimo_precoding_matrix = (int32_t ***)malloc16(max_mimo_layers * sizeof(int32_t **));
|
||||
int32_t ***mat = gNB->nr_mimo_precoding_matrix;
|
||||
double complex res_code;
|
||||
|
||||
//Table 5.2.2.2.1-5:
|
||||
//Codebook for 1-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
|
||||
gNB->pmiq_size[0] = N1*O1*N2*O2*4+1;
|
||||
mat[0] = (int32_t **)malloc16(gNB->pmiq_size[0]*sizeof(int32_t *));
|
||||
|
||||
//pmi=0 corresponds to unit matrix
|
||||
mat[0][0] = (int32_t *)calloc(2*N1*N2,sizeof(int32_t));
|
||||
for(int j_col=0; j_col<1; j_col++) { //1 layer
|
||||
for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna
|
||||
if(j_col==i_rows) {
|
||||
mat[0][0][i_rows+j_col] = 0x7fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int ll=0; ll<N1*O1; ll++) { //i_1_1
|
||||
for (int mm=0; mm<N2*O2; mm++) { //i_1_2
|
||||
for (int nn=0; nn<4; nn++) {
|
||||
int pmiq = 1+ll*N2*O2*4+mm*4+nn;
|
||||
mat[0][pmiq] = (int32_t *)malloc16((2*N1*N2)*1*sizeof(int32_t));
|
||||
LOG_D(PHY, "layer 1 Codebook pmiq = %d\n",pmiq);
|
||||
for (int len=0; len<N1*N2; len++) {
|
||||
res_code=sqrt(1/(double)CSI_RS_antenna_ports)*v_lm[ll][mm][len];
|
||||
if (creal(res_code)>0)
|
||||
((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
|
||||
if (cimag(res_code)>0)
|
||||
((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
|
||||
LOG_D(PHY, "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n",
|
||||
pmiq, len, creal(res_code), cimag(res_code),((short*) &mat[0][pmiq][len])[0],((short*) &mat[0][pmiq][len])[1]);
|
||||
}
|
||||
|
||||
for(int len=N1*N2; len<2*N1*N2; len++) {
|
||||
res_code=sqrt(1/(double)CSI_RS_antenna_ports)*theta_n[nn]*v_lm[ll][mm][len-N1*N2];
|
||||
if (creal(res_code)>0)
|
||||
((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[0][pmiq][len])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
|
||||
if (cimag(res_code)>0)
|
||||
((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[0][pmiq][len])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
|
||||
LOG_D(PHY, "1 Layer Precoding Matrix[0][pmi %d][antPort %d]= %f+j %f -> Fixed Point %d+j %d \n",
|
||||
pmiq, len, creal(res_code), cimag(res_code),((short*) &mat[0][pmiq][len])[0],((short*) &mat[0][pmiq][len])[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int llc = 0;
|
||||
int mmc = 0;
|
||||
double complex phase_sign = 0;
|
||||
//Table 5.2.2.2.1-6:
|
||||
//Codebook for 2-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
|
||||
//Compute the code book size for generating 2 layers out of Tx antenna ports
|
||||
|
||||
//pmi_size is computed as follows
|
||||
gNB->pmiq_size[1] = 1;//1 for unity matrix
|
||||
for(int llb=0; llb<N1*O1; llb++) { //i_1_1
|
||||
for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
|
||||
for(int ll=0; ll<N1*O1; ll++) { //i_1_1
|
||||
for (int mm=0; mm<N2*O2; mm++) { //i_1_2
|
||||
for (int nn=0; nn<2; nn++) {
|
||||
if((llb != ll) || (mmb != mm) || ((N1 == 1) && (N2 == 1))) gNB->pmiq_size[1] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mat[1] = (int32_t **)malloc16(gNB->pmiq_size[1]*sizeof(int32_t *));
|
||||
|
||||
//pmi=0 corresponds to unit matrix
|
||||
mat[1][0] = (int32_t *)calloc((2*N1*N2)*(2),sizeof(int32_t));
|
||||
for(int j_col=0; j_col<2; j_col++) { //2 layers
|
||||
for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna
|
||||
if(j_col==i_rows) {
|
||||
mat[1][0][i_rows*2+j_col] = 0x7fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//pmi=1,...,pmi_size, we construct
|
||||
int pmiq = 0;
|
||||
for(int llb=0; llb<N1*O1; llb++) { //i_1_1
|
||||
for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
|
||||
for(int ll=0; ll<N1*O1; ll++) { //i_1_1
|
||||
for (int mm=0; mm<N2*O2; mm++) { //i_1_2
|
||||
for (int nn=0; nn<2; nn++) {
|
||||
if((llb != ll) || (mmb != mm) || ((N1 == 1) && (N2 == 1))){
|
||||
pmiq += 1;
|
||||
mat[1][pmiq] = (int32_t *)malloc16((2*N1*N2)*(2)*sizeof(int32_t));
|
||||
LOG_D(PHY, "layer 2 Codebook pmiq = %d\n",pmiq);
|
||||
for(int j_col=0; j_col<2; j_col++) {
|
||||
if (j_col==0) {
|
||||
llc = llb;
|
||||
mmc = mmb;
|
||||
phase_sign = 1;
|
||||
}
|
||||
if (j_col==1) {
|
||||
llc = ll;
|
||||
mmc = mm;
|
||||
phase_sign = -1;
|
||||
}
|
||||
for (int i_rows=0; i_rows<N1*N2; i_rows++) {
|
||||
res_code=sqrt(1/(double)(2*CSI_RS_antenna_ports))*v_lm[llc][mmc][i_rows];
|
||||
if (creal(res_code)>0)
|
||||
((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
|
||||
if (cimag(res_code)>0)
|
||||
((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
|
||||
LOG_D(PHY, "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
|
||||
pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[1][pmiq][i_rows*2+j_col])[0],((short*) &mat[1][pmiq][i_rows*2+j_col])[1]);
|
||||
}
|
||||
for (int i_rows=N1*N2; i_rows<2*N1*N2; i_rows++) {
|
||||
res_code=sqrt(1/(double)(2*CSI_RS_antenna_ports))*(phase_sign)*theta_n[nn]*v_lm[llc][mmc][i_rows-N1*N2];
|
||||
if (creal(res_code)>0)
|
||||
((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[1][pmiq][i_rows*2+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
|
||||
if (cimag(res_code)>0)
|
||||
((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[1][pmiq][i_rows*2+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
|
||||
LOG_D(PHY, "2 Layer Precoding Matrix[1][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
|
||||
pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[1][pmiq][i_rows*2+j_col])[0],((short*) &mat[1][pmiq][i_rows*2+j_col])[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Table 5.2.2.2.1-7:
|
||||
//Codebook for 3-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
|
||||
if(max_mimo_layers>=3) {
|
||||
|
||||
//pmi_size is computed as follows
|
||||
gNB->pmiq_size[2] = 1;//unity matrix
|
||||
for(int llb=0; llb<N1*O1; llb++) { //i_1_1
|
||||
for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
|
||||
for(int ll=0; ll<N1*O1; ll++) { //i_1_1
|
||||
for (int mm=0; mm<N2*O2; mm++) { //i_1_2
|
||||
for (int nn=0; nn<2; nn++) {
|
||||
if((llb != ll) || (mmb != mm)) gNB->pmiq_size[2] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mat[2] = (int32_t **)malloc16(gNB->pmiq_size[2]*sizeof(int32_t *));
|
||||
//pmi=0 corresponds to unit matrix
|
||||
mat[2][0] = (int32_t *)calloc((2*N1*N2)*(3),sizeof(int32_t));
|
||||
for(int j_col=0; j_col<3; j_col++) { //3 layers
|
||||
for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna
|
||||
if(j_col==i_rows) {
|
||||
mat[2][0][i_rows*3+j_col] = 0x7fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pmiq = 0;
|
||||
//pmi=1,...,pmi_size are computed as follows
|
||||
for(int llb=0; llb<N1*O1; llb++) { //i_1_1
|
||||
for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
|
||||
for(int ll=0; ll<N1*O1; ll++) { //i_1_1
|
||||
for (int mm=0; mm<N2*O2; mm++) { //i_1_2
|
||||
for (int nn=0; nn<2; nn++) {
|
||||
if((llb != ll) || (mmb != mm)){
|
||||
pmiq += 1;
|
||||
mat[2][pmiq] = (int32_t *)malloc16((2*N1*N2)*(3)*sizeof(int32_t));
|
||||
LOG_D(PHY, "layer 3 Codebook pmiq = %d\n",pmiq);
|
||||
for(int j_col=0; j_col<3; j_col++) {
|
||||
if (j_col==0) {
|
||||
llc = llb;
|
||||
mmc = mmb;
|
||||
phase_sign = 1;
|
||||
}
|
||||
if (j_col==1) {
|
||||
llc = ll;
|
||||
mmc = mm;
|
||||
phase_sign = 1;
|
||||
}
|
||||
if (j_col==2) {
|
||||
llc = ll;
|
||||
mmc = mm;
|
||||
phase_sign = -1;
|
||||
}
|
||||
for (int i_rows=0; i_rows<N1*N2; i_rows++) {
|
||||
res_code=sqrt(1/(double)(3*CSI_RS_antenna_ports))*v_lm[llc][mmc][i_rows];
|
||||
if (creal(res_code)>0)
|
||||
((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
|
||||
if (cimag(res_code)>0)
|
||||
((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
|
||||
LOG_D(PHY, "3 Layer Precoding Matrix[2][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
|
||||
pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[2][pmiq][i_rows*3+j_col])[0],((short*) &mat[2][pmiq][i_rows*3+j_col])[1]);
|
||||
}
|
||||
for (int i_rows=N1*N2; i_rows<2*N1*N2; i_rows++) {
|
||||
res_code=sqrt(1/(double)(3*CSI_RS_antenna_ports))*(phase_sign)*theta_n[nn]*v_lm[llc][mmc][i_rows-N1*N2];
|
||||
if (creal(res_code)>0)
|
||||
((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[2][pmiq][i_rows*3+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
|
||||
if (cimag(res_code)>0)
|
||||
((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[2][pmiq][i_rows*3+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
|
||||
LOG_D(PHY, "3 Layer Precoding Matrix[2][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
|
||||
pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[2][pmiq][i_rows*3+j_col])[0],((short*) &mat[2][pmiq][i_rows*3+j_col])[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Table 5.2.2.2.1-8:
|
||||
//Codebook for 4-layer CSI reporting using antenna ports 3000 to 2999+PCSI-RS
|
||||
if(max_mimo_layers>=4) {
|
||||
//pmi_size is computed as follows
|
||||
gNB->pmiq_size[3] = 1;//unity matrix
|
||||
for(int llb=0; llb<N1*O1; llb++) { //i_1_1
|
||||
for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
|
||||
for(int ll=0; ll<N1*O1; ll++) { //i_1_1
|
||||
for (int mm=0; mm<N2*O2; mm++) { //i_1_2
|
||||
for (int nn=0; nn<2; nn++) {
|
||||
if((llb != ll) || (mmb != mm)) gNB->pmiq_size[3] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mat[3] = (int32_t **)malloc16(gNB->pmiq_size[3]*sizeof(int32_t *));
|
||||
//pmi=0 corresponds to unit matrix
|
||||
mat[3][0] = (int32_t *)calloc((2*N1*N2)*(4),sizeof(int32_t));
|
||||
for(int j_col=0; j_col<4; j_col++) { //4 layers
|
||||
for (int i_rows=0; i_rows<2*N1*N2; i_rows++) { //2-x polarized antenna
|
||||
if(j_col==i_rows) {
|
||||
mat[3][0][i_rows*4+j_col] = 0x7fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pmiq = 0;
|
||||
//pmi=1,...,pmi_size are computed as follows
|
||||
for(int llb=0; llb<N1*O1; llb++) { //i_1_1
|
||||
for (int mmb=0; mmb<N2*O2; mmb++) { //i_1_2
|
||||
for(int ll=0; ll<N1*O1; ll++) { //i_1_1
|
||||
for (int mm=0; mm<N2*O2; mm++) { //i_1_2
|
||||
for (int nn=0; nn<2; nn++) {
|
||||
|
||||
if((llb != ll) || (mmb != mm)){
|
||||
pmiq += 1;
|
||||
mat[3][pmiq] = (int32_t *)malloc16((2*N1*N2)*4*sizeof(int32_t));
|
||||
LOG_D(PHY, "layer 4 pmiq = %d\n",pmiq);
|
||||
for(int j_col=0; j_col<4; j_col++) {
|
||||
if (j_col==0) {
|
||||
llc = llb;
|
||||
mmc = mmb;
|
||||
phase_sign = 1;
|
||||
}
|
||||
if (j_col==1) {
|
||||
llc = ll;
|
||||
mmc = mm;
|
||||
phase_sign = 1;
|
||||
}
|
||||
if (j_col==2) {
|
||||
llc = llb;
|
||||
mmc = mmb;
|
||||
phase_sign = -1;
|
||||
}
|
||||
if (j_col==3) {
|
||||
llc = ll;
|
||||
mmc = mm;
|
||||
phase_sign = -1;
|
||||
}
|
||||
for (int i_rows=0; i_rows<N1*N2; i_rows++) {
|
||||
res_code=sqrt(1/(double)(4*CSI_RS_antenna_ports))*v_lm[llc][mmc][i_rows];
|
||||
if (creal(res_code)>0)
|
||||
((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
|
||||
if (cimag(res_code)>0)
|
||||
((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
|
||||
LOG_D(PHY, "4 Layer Precoding Matrix[3][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
|
||||
pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[3][pmiq][i_rows*4+j_col])[0],((short*) &mat[3][pmiq][i_rows*4+j_col])[1]);
|
||||
}
|
||||
|
||||
for (int i_rows=N1*N2; i_rows<2*N1*N2; i_rows++) {
|
||||
res_code=sqrt(1/(double)(4*CSI_RS_antenna_ports))*(phase_sign)*theta_n[nn]*v_lm[llc][mmc][i_rows-N1*N2];
|
||||
if (creal(res_code)>0)
|
||||
((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[3][pmiq][i_rows*4+j_col])[0] = (short) ((creal(res_code)*32768)-0.5);//convert to Q15
|
||||
if (cimag(res_code)>0)
|
||||
((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)+0.5);//convert to Q15
|
||||
else
|
||||
((short*) &mat[3][pmiq][i_rows*4+j_col])[1] = (short) ((cimag(res_code)*32768)-0.5);//convert to Q15
|
||||
LOG_D(PHY, "4 Layer Precoding Matrix[3][pmi %d][antPort %d][layerIdx %d]= %f+j %f -> Fixed Point %d+j %d \n",
|
||||
pmiq,i_rows,j_col, creal(res_code), cimag(res_code),((short*) &mat[3][pmiq][i_rows*4+j_col])[0],((short*) &mat[3][pmiq][i_rows*4+j_col])[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A global var to reduce the changes size
|
||||
ldpc_interface_t ldpc_interface = {0}, ldpc_interface_offload = {0};
|
||||
|
||||
@@ -536,8 +134,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
if (gNB->ldpc_offload_flag)
|
||||
load_LDPClib("_t2", &ldpc_interface_offload);
|
||||
gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB;
|
||||
|
||||
init_codebook_gNB(gNB);
|
||||
init_delay_table(fp->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, fp->delay_table);
|
||||
|
||||
// PBCH DMRS gold sequences generation
|
||||
@@ -725,23 +321,15 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
|
||||
void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
{
|
||||
NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms;
|
||||
NR_DL_FRAME_PARMS* const fp = &gNB->frame_parms;
|
||||
const int Ptx = gNB->gNB_config.carrier_config.num_tx_ant.value;
|
||||
const int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value;
|
||||
const int max_ul_mimo_layers = 4; // taken from phy_init_nr_gNB()
|
||||
const int n_buf = Prx * max_ul_mimo_layers;
|
||||
PHY_MEASUREMENTS_gNB *meas=&gNB->measurements;
|
||||
|
||||
PHY_MEASUREMENTS_gNB *meas = &gNB->measurements;
|
||||
free_and_zero(meas->n0_subband_power);
|
||||
free_and_zero(meas->n0_subband_power_dB);
|
||||
int max_dl_mimo_layers =(fp->nb_antennas_tx<NR_MAX_NB_LAYERS) ? fp->nb_antennas_tx : NR_MAX_NB_LAYERS;
|
||||
if (fp->nb_antennas_tx>1) {
|
||||
for (int nl = 0; nl < max_dl_mimo_layers; nl++) {
|
||||
for(int size = 0; size < gNB->pmiq_size[nl]; size++)
|
||||
free_and_zero(gNB->nr_mimo_precoding_matrix[nl][size]);
|
||||
free_and_zero(gNB->nr_mimo_precoding_matrix[nl]);
|
||||
}
|
||||
free_and_zero(gNB->nr_mimo_precoding_matrix);
|
||||
}
|
||||
|
||||
uint32_t ***pdcch_dmrs = gNB->nr_gold_pdcch_dmrs;
|
||||
for (int slot = 0; slot < fp->slots_per_frame; slot++) {
|
||||
|
||||
@@ -703,13 +703,17 @@ c16_t nr_layer_precoder_cm(int n_layers,
|
||||
int n_symbols,
|
||||
int symSz,
|
||||
c16_t datatx_F_precoding[n_layers][n_symbols][symSz],
|
||||
c16_t *prec_matrix,
|
||||
int ap,
|
||||
nfapi_nr_pm_pdu_t *pmi_pdu,
|
||||
int symbol,
|
||||
int offset)
|
||||
{
|
||||
c16_t precodatatx_F = {0};
|
||||
for (int al = 0; al < n_layers; al++)
|
||||
precodatatx_F = c16maddShift(datatx_F_precoding[al][symbol][offset], prec_matrix[al], precodatatx_F, 15);
|
||||
for (int al = 0; al < n_layers; al++) {
|
||||
nfapi_nr_pm_weights_t *w = &pmi_pdu->weights[al][ap];
|
||||
c16_t prec_weight = {.r = w->precoder_weight_Re, .i = w->precoder_weight_Im};
|
||||
precodatatx_F = c16maddShift(datatx_F_precoding[al][symbol][offset], prec_weight, precodatatx_F, 15);
|
||||
}
|
||||
return precodatatx_F;
|
||||
}
|
||||
|
||||
@@ -717,69 +721,77 @@ void nr_layer_precoder_simd(const int n_layers,
|
||||
const int n_symbols,
|
||||
const int symSz,
|
||||
const c16_t txdataF_res_mapped[n_layers][n_symbols][symSz],
|
||||
const c16_t prec_matrix[n_layers],
|
||||
const int ant,
|
||||
const nfapi_nr_pm_pdu_t *pmi_pdu,
|
||||
const int symbol,
|
||||
const int sc_offset,
|
||||
const int re_cnt,
|
||||
c16_t *txdataF_precoded)
|
||||
{
|
||||
uint32_t sc = sc_offset;
|
||||
|
||||
c16_t prec_weight = {0};
|
||||
// For x86, use 256 SIMD for every 8 RE and 128 SIMD for last 4 RE
|
||||
// For aarch64, use 128 SIMD for every 4 RE
|
||||
|
||||
// 256 SIMD: Do 8 RE in one iteration, 3 iterations for 2 RB
|
||||
#ifdef __AVX2__
|
||||
const uint32_t re_cnt_align8 = re_cnt & ~7;
|
||||
for(; sc<sc_offset+(re_cnt_align8); sc+=sizeof(simde__m256i)/sizeof(*prec_matrix)){
|
||||
// Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8)
|
||||
simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1]
|
||||
for(int nl=0; nl<n_layers; nl++){
|
||||
const simde__m256i x = simde_mm256_loadu_epi32(&txdataF_res_mapped[nl][symbol][sc]);
|
||||
#ifdef __AVX2__
|
||||
const uint32_t re_cnt_align8 = re_cnt & ~7;
|
||||
for(; sc < sc_offset + (re_cnt_align8); sc += sizeof(simde__m256i) / sizeof(prec_weight)) {
|
||||
// Matrix multiplication for 4 elements of the result (sizeof(simde__m256i) / sizeof(*prec_matrix) = 8)
|
||||
simde__m256i y = simde_mm256_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1]
|
||||
for(int nl = 0; nl < n_layers; nl++) {
|
||||
prec_weight.r = pmi_pdu->weights[nl][ant].precoder_weight_Re;
|
||||
prec_weight.i = pmi_pdu->weights[nl][ant].precoder_weight_Im;
|
||||
|
||||
// Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size
|
||||
const simde__m256i w_c = simde_mm256_set1_epi32(c16toI32(c16conj(prec_matrix[nl]))); // broadcast conjugate of w
|
||||
const simde__m256i w_s = simde_mm256_set1_epi32(c16toI32(c16swap(prec_matrix[nl]))); // broadcast swapped real and img of w
|
||||
const simde__m256i x = simde_mm256_loadu_epi32(&txdataF_res_mapped[nl][symbol][sc]);
|
||||
|
||||
// Multiplication and shift
|
||||
const simde__m256i reals = simde_mm256_srai_epi32(simde_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15
|
||||
const simde__m256i imags = simde_mm256_slli_epi32(simde_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16
|
||||
// Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size
|
||||
const simde__m256i w_c = simde_mm256_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w
|
||||
const simde__m256i w_s = simde_mm256_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w
|
||||
|
||||
// Re-arrange to match c16_t format
|
||||
const simde__m256i produ = simde_mm256_blend_epi16(reals, imags, 0xAA);
|
||||
// Multiplication and shift
|
||||
const simde__m256i reals = simde_mm256_srai_epi32(simde_mm256_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15
|
||||
const simde__m256i imags = simde_mm256_slli_epi32(simde_mm256_madd_epi16(x, w_s), 1); // (int32_t) .i = (x.r * w.i + x.i * w.r) << 1, since higher 16 bit of each 32 bit is taken by blend_epi16
|
||||
|
||||
// Accumulate the product
|
||||
y = simde_mm256_adds_epi16(y, produ);
|
||||
}
|
||||
// Store the result to txdataF
|
||||
simde_mm256_storeu_si256(&txdataF_precoded[sc], y);
|
||||
// Re-arrange to match c16_t format
|
||||
const simde__m256i produ = simde_mm256_blend_epi16(reals, imags, 0xAA);
|
||||
|
||||
// Accumulate the product
|
||||
y = simde_mm256_adds_epi16(y, produ);
|
||||
}
|
||||
#endif
|
||||
// Store the result to txdataF
|
||||
simde_mm256_storeu_si256(&txdataF_precoded[sc], y);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 128 SIMD: Do 4 RE in one iteration, 3 iterations for 1 RB
|
||||
const uint32_t re_cnt_align4 = re_cnt & ~3;
|
||||
for(; sc<sc_offset+re_cnt_align4; sc+=sizeof(simde__m128i)/sizeof(*prec_matrix)){
|
||||
for(; sc < sc_offset+re_cnt_align4; sc += sizeof(simde__m128i) / sizeof(prec_weight)) {
|
||||
#ifdef DEBUG_DLSCH_PRECODING_PRINT_WITH_TRIVIAL // Get result with trivial solution, TODO: To be removed
|
||||
c16_t y_triv[4];
|
||||
for(int i=0; i<4; i++)
|
||||
for(int i = 0; i < 4; i++)
|
||||
y_triv[i] = nr_layer_precoder_cm(n_layers,
|
||||
NR_SYMBOLS_PER_SLOT,
|
||||
symSz,
|
||||
txdataF_res_mapped,
|
||||
prec_matrix,
|
||||
symbol,
|
||||
sc + i);
|
||||
NR_SYMBOLS_PER_SLOT,
|
||||
symSz,
|
||||
txdataF_res_mapped,
|
||||
ant,
|
||||
pmi_pdu,
|
||||
symbol,
|
||||
sc + i);
|
||||
memcpy(&txdataF_precoded[sc], y_triv, sizeof(y_triv));
|
||||
#endif
|
||||
|
||||
// Matrix multiplication for 4 elements of the result (sizeof(simde__m128i) / sizeof(c16_t) = 4)
|
||||
simde__m128i y = simde_mm_set1_epi16(0); // Y = W[0]*X[0] + W[1]*X[1] + ... + W[nrOfLayers-1]*X[nrOfLayers-1]
|
||||
for(int nl=0; nl<n_layers; nl++){
|
||||
for(int nl = 0; nl < n_layers; nl++) {
|
||||
prec_weight.r = pmi_pdu->weights[nl][ant].precoder_weight_Re;
|
||||
prec_weight.i = pmi_pdu->weights[nl][ant].precoder_weight_Im;
|
||||
|
||||
const simde__m128i x = simde_mm_loadu_epi32(&txdataF_res_mapped[nl][symbol][sc]);
|
||||
|
||||
// Rearrange precoding matrix weight to match complex multiplication and broadcast it to match SIMD size
|
||||
const simde__m128i w_c = simde_mm_set1_epi32(c16toI32(c16conj(prec_matrix[nl]))); // broadcast conjugate of w
|
||||
const simde__m128i w_s = simde_mm_set1_epi32(c16toI32(c16swap(prec_matrix[nl]))); // broadcast swapped real and img of w
|
||||
const simde__m128i w_c = simde_mm_set1_epi32(c16toI32(c16conj(prec_weight))); // broadcast conjugate of w
|
||||
const simde__m128i w_s = simde_mm_set1_epi32(c16toI32(c16swap(prec_weight))); // broadcast swapped real and img of w
|
||||
|
||||
// Multiplication and shift
|
||||
const simde__m128i reals = simde_mm_srai_epi32(simde_mm_madd_epi16(x, w_c), 15); // (int32_t) .r = (x.r * w.r - x.i * w.i) >> 15
|
||||
|
||||
@@ -138,11 +138,13 @@ void apply_nr_rotation_RX(NR_DL_FRAME_PARMS *frame_parms,
|
||||
@param[in] n_layers, number of DLSCH layers
|
||||
*/
|
||||
int nr_layer_precoder(int16_t **datatx_F_precoding, const char *prec_matrix, uint8_t n_layers, int32_t re_offset);
|
||||
|
||||
c16_t nr_layer_precoder_cm(int n_layers,
|
||||
int n_symbols,
|
||||
int symSz,
|
||||
c16_t datatx_F_precoding[n_layers][n_symbols][symSz],
|
||||
c16_t *prec_matrix,
|
||||
int ap,
|
||||
nfapi_nr_pm_pdu_t *pmi_pdu,
|
||||
int symbol,
|
||||
int offset);
|
||||
|
||||
@@ -156,7 +158,8 @@ void nr_layer_precoder_simd(const int n_layers,
|
||||
const int n_symbols,
|
||||
const int symSz,
|
||||
const c16_t txdataF_res_mapped[n_layers][n_symbols][symSz],
|
||||
const c16_t prec_matrix[n_layers],
|
||||
const int ant,
|
||||
const nfapi_nr_pm_pdu_t *pmi_pdu,
|
||||
const int symbol,
|
||||
const int sc_offset,
|
||||
const int re_cnt,
|
||||
|
||||
@@ -535,58 +535,52 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
}
|
||||
}
|
||||
else { // non-unitary Precoding
|
||||
if(frame_parms->nb_antennas_tx == 1){ // no precoding matrix defined
|
||||
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
|
||||
&txdataF_precoding[ant][l_symbol][subCarrier],
|
||||
re_cnt * sizeof(**txdataF));
|
||||
AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n");
|
||||
//get the precoding matrix weights:
|
||||
nfapi_nr_pm_pdu_t *pmi_pdu = &gNB->gNB_config.pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix
|
||||
AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n",
|
||||
pmi, pmi_pdu->pm_idx);
|
||||
AssertFatal(ant < pmi_pdu->num_ant_ports, "Antenna port index %d exceeds precoding matrix AP size %d\n",
|
||||
ant, pmi_pdu->num_ant_ports);
|
||||
AssertFatal(rel15->nrOfLayers == pmi_pdu->numLayers, "Number of layers %d doesn't match to the one in precoding matrix %d\n",
|
||||
rel15->nrOfLayers, pmi_pdu->numLayers);
|
||||
if((subCarrier + re_cnt) < frame_parms->ofdm_symbol_size){ // within ofdm_symbol_size, use SIMDe
|
||||
nr_layer_precoder_simd(rel15->nrOfLayers,
|
||||
NR_SYMBOLS_PER_SLOT,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
txdataF_precoding,
|
||||
ant,
|
||||
pmi_pdu,
|
||||
l_symbol,
|
||||
subCarrier,
|
||||
re_cnt,
|
||||
&txdataF[ant][txdataF_offset_per_symbol]);
|
||||
subCarrier += re_cnt;
|
||||
if (subCarrier >= frame_parms->ofdm_symbol_size) {
|
||||
subCarrier -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
}
|
||||
else { // precoding with more than 1 tx
|
||||
//get the precoding matrix weights:
|
||||
c16_t **mat = (c16_t**)gNB->nr_mimo_precoding_matrix[rel15->nrOfLayers - 1];
|
||||
//i_row =0,...,dl_antenna_port
|
||||
//j_col =0,...,nrOfLayers
|
||||
//mat[pmi][i_rows*2+j_col]
|
||||
c16_t *W_prec = &mat[pmi][ant * rel15->nrOfLayers];
|
||||
if((subCarrier + re_cnt) < frame_parms->ofdm_symbol_size){ // within ofdm_symbol_size, use SIMDe
|
||||
nr_layer_precoder_simd(rel15->nrOfLayers,
|
||||
NR_SYMBOLS_PER_SLOT,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
txdataF_precoding,
|
||||
W_prec,
|
||||
l_symbol,
|
||||
subCarrier,
|
||||
re_cnt,
|
||||
&txdataF[ant][txdataF_offset_per_symbol]);
|
||||
subCarrier += re_cnt;
|
||||
}
|
||||
else{ // crossing ofdm_symbol_size, use simple arithmetic operations
|
||||
for (int i = 0; i < re_cnt; i++) {
|
||||
txdataF[ant][txdataF_offset_per_symbol + subCarrier] =
|
||||
nr_layer_precoder_cm(rel15->nrOfLayers,
|
||||
NR_SYMBOLS_PER_SLOT,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
txdataF_precoding,
|
||||
W_prec,
|
||||
l_symbol,
|
||||
subCarrier);
|
||||
else{ // crossing ofdm_symbol_size, use simple arithmetic operations
|
||||
for (int i = 0; i < re_cnt; i++) {
|
||||
txdataF[ant][txdataF_offset_per_symbol + subCarrier] =
|
||||
nr_layer_precoder_cm(rel15->nrOfLayers,
|
||||
NR_SYMBOLS_PER_SLOT,
|
||||
frame_parms->ofdm_symbol_size,
|
||||
txdataF_precoding,
|
||||
ant,
|
||||
pmi_pdu,
|
||||
l_symbol,
|
||||
subCarrier);
|
||||
#ifdef DEBUG_DLSCH_MAPPING
|
||||
printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n",
|
||||
ant,
|
||||
symbol,
|
||||
subCarrier,
|
||||
txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].r,
|
||||
txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].i);
|
||||
printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n",
|
||||
ant,
|
||||
symbol,
|
||||
subCarrier,
|
||||
txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].r,
|
||||
txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].i);
|
||||
#endif
|
||||
if (++subCarrier >= frame_parms->ofdm_symbol_size) {
|
||||
subCarrier -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
if (++subCarrier >= frame_parms->ofdm_symbol_size) {
|
||||
subCarrier -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
} // else{ // crossing ofdm_symbol_size, use simple arithmetic operations
|
||||
} // else { // precoding with more than 1 tx
|
||||
}
|
||||
} // else{ // crossing ofdm_symbol_size, use simple arithmetic operations
|
||||
} // else { // non-unitary Precoding
|
||||
|
||||
rb += rb_step;
|
||||
|
||||
@@ -619,13 +619,6 @@ typedef struct PHY_VARS_gNB_s {
|
||||
/// PDSCH DMRS sequence
|
||||
uint32_t ****nr_gold_pdsch_dmrs;
|
||||
|
||||
/// PDSCH codebook I precoding LUTs
|
||||
/// first dimension: Rank number [0,...,noOfLayers-1[
|
||||
/// second dimension: PMI [0,...,CodeSize-1[
|
||||
/// third dimension: [i_rows*noOfLayers+j_col], i_rows=0,...pdsch_AntennaPorts-1 and j_col=0,...,noOfLayers-1
|
||||
int32_t ***nr_mimo_precoding_matrix;
|
||||
int pmiq_size[NR_MAX_NB_LAYERS];
|
||||
|
||||
/// PUSCH DMRS
|
||||
uint32_t ****nr_gold_pusch_dmrs;
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
|
||||
#define NR_MAX_PDCCH_AGG_LEVEL 16 // 3GPP TS 38.211 V15.8 Section 7.3.2 Table 7.3.2.1-1: Supported PDCCH aggregation levels
|
||||
|
||||
#define NR_MAX_NB_LAYERS 4 // 8
|
||||
#define NR_MAX_NB_PORTS 32
|
||||
|
||||
#define NR_MAX_PDSCH_TBS 3824
|
||||
|
||||
@@ -223,35 +223,21 @@ nrUE_params_t *get_nrUE_params(void) {
|
||||
}
|
||||
|
||||
|
||||
void validate_input_pmi(nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int nrOfLayers, int pmi)
|
||||
void validate_input_pmi(nfapi_nr_config_request_scf_t *gNB_config,
|
||||
nr_pdsch_AntennaPorts_t pdsch_AntennaPorts,
|
||||
int nrOfLayers,
|
||||
int pmi)
|
||||
{
|
||||
if (pmi == 0)
|
||||
return;
|
||||
|
||||
nfapi_nr_pm_pdu_t *pmi_pdu = &gNB_config->pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix
|
||||
AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n", pmi, pmi_pdu->pm_idx);
|
||||
AssertFatal(nrOfLayers == pmi_pdu->numLayers, "Number of layers %d doesn't match to the one in precoding matrix %d for PMI %d\n",
|
||||
nrOfLayers, pmi_pdu->numLayers, pmi);
|
||||
int num_antenna_ports = pdsch_AntennaPorts.N1 * pdsch_AntennaPorts.N2 * pdsch_AntennaPorts.XP;
|
||||
int N1 = pdsch_AntennaPorts.N1;
|
||||
int N2 = pdsch_AntennaPorts.N2;
|
||||
int O1 = N1 > 1 ? 4 : 1;
|
||||
int O2 = N2 > 1 ? 4 : 1;
|
||||
int K1, K2;
|
||||
if (num_antenna_ports > 2)
|
||||
get_K1_K2(N1, N2, &K1, &K2);
|
||||
else {
|
||||
K1 = 1; K2 = 1;
|
||||
}
|
||||
int num_pmi = 1; // pmi = 0 is the identity matrix
|
||||
switch (nrOfLayers) {
|
||||
case 1 :
|
||||
num_pmi += N1 * O1 * N2 * O2 * 4;
|
||||
AssertFatal(pmi < num_pmi, "Input PMI index %d exceeds the limit of configured matrices %d for %d layers\n", pmi, num_pmi, nrOfLayers);
|
||||
return;
|
||||
case 2 :
|
||||
num_pmi += N1 * O1 * N2 * O2 * K1 * K2 * 2;
|
||||
AssertFatal(pmi < num_pmi, "Input PMI index %d exceeds the limit of conigured matrices %d for %d layers\n", pmi, num_pmi, nrOfLayers);
|
||||
break;
|
||||
default :
|
||||
AssertFatal(false, "Precoding with more than 2 nrOfLayers not yet supported\n");
|
||||
}
|
||||
AssertFatal(num_antenna_ports == pmi_pdu->num_ant_ports, "Configured antenna ports %d does not match precoding matrix AP size %d for PMI %d\n",
|
||||
num_antenna_ports, pmi_pdu->num_ant_ports, pmi);
|
||||
}
|
||||
|
||||
|
||||
@@ -709,7 +695,7 @@ int main(int argc, char **argv)
|
||||
gNB->ap_N2 = pdsch_AntennaPorts.N2;
|
||||
gNB->ap_XP = pdsch_AntennaPorts.XP;
|
||||
|
||||
validate_input_pmi(pdsch_AntennaPorts, g_nrOfLayers, g_pmi);
|
||||
validate_input_pmi(&gNB_mac->config[0], pdsch_AntennaPorts, g_nrOfLayers, g_pmi);
|
||||
|
||||
NR_UE_NR_Capability_t* UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t));
|
||||
prepare_sim_uecap(UE_Capability_nr,scc,mu,
|
||||
|
||||
Reference in New Issue
Block a user