/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /*! \file PHY/LTE_TRANSPORT/dlsch_demodulation.c * \brief Top-level routines for demodulating the PDSCH physical channel from 36-211, V8.6 2009-03 * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, X. Xiang * \date 2011 * \version 0.1 * \company Eurecom * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,ankit.bhamri@eurecom.fr,sebastien.aubert@eurecom.fr * \note * \warning */ #include "PHY/defs_UE.h" #include "PHY/phy_extern_ue.h" #include "SCHED_UE/sched_UE.h" #include "transport_ue.h" #include "transport_proto_ue.h" #include "PHY/sse_intrin.h" #include "T.h" #include<stdio.h> #include<math.h> #include <stdlib.h> #include <string.h> #include <lapacke_utils.h> #include <lapacke.h> #include <cblas.h> #include "linear_preprocessing_rec.h" #define NOCYGWIN_STATIC //#define DEBUG_MMSE /* dynamic shift for LLR computation for TM3/4 * set as command line argument, see lte-softmodem.c * default value: 0 */ int16_t dlsch_demod_shift = 0; int16_t interf_unaw_shift = 13; //#define DEBUG_HARQ //#define DEBUG_PHY 1 //#define DEBUG_DLSCH_DEMOD 1 //#define DISABLE_LOG_X // [MCS][i_mod (0,1,2) = (2,4,6)] unsigned char offset_mumimo_llr_drange_fix=0; //inferference-free case unsigned char interf_unaw_shift_tm4_mcs[29]={5, 3, 4, 3, 3, 2, 1, 1, 2, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 2, 1, 0, 1, 0, 1, 0, 0} ; unsigned char interf_unaw_shift_tm1_mcs[29]={5, 5, 4, 3, 3, 3, 2, 2, 4, 4, 2, 3, 3, 3, 1, 1, 0, 1, 1, 2, 5, 4, 4, 6, 5, 1, 0, 5, 6} ; // mcs 21, 26, 28 seem to be errorneous /* //original values from sebastion + same hand tuning unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{6,6,6},{6,6,6},{6,6,6},{5,5,5},{4,4,4},{1,2,4}, // QPSK {5,5,4},{5,5,5},{5,5,5},{3,3,3},{2,2,2},{2,2,2},{2,2,2}, // 16-QAM {2,2,1},{3,3,3},{3,3,3},{3,3,1},{2,2,2},{2,2,2},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; //64-QAM */ /* //first optimization try unsigned char offset_mumimo_llr_drange[29][3]={{7, 8, 7},{6, 6, 7},{6, 6, 7},{6, 6, 6},{5, 6, 6},{5, 5, 6},{5, 5, 6},{4, 5, 4},{4, 3, 4},{3, 2, 2},{6, 5, 5},{5, 4, 4},{5, 5, 4},{3, 3, 2},{2, 2, 1},{2, 1, 1},{2, 2, 2},{3, 3, 3},{3, 3, 2},{3, 3, 2},{3, 2, 1},{2, 2, 2},{2, 2, 2},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}}; */ //second optimization try /* unsigned char offset_mumimo_llr_drange[29][3]={{5, 8, 7},{4, 6, 8},{3, 6, 7},{7, 7, 6},{4, 7, 8},{4, 7, 4},{6, 6, 6},{3, 6, 6},{3, 6, 6},{1, 3, 4},{1, 1, 0},{3, 3, 2},{3, 4, 1},{4, 0, 1},{4, 2, 2},{3, 1, 2},{2, 1, 0},{2, 1, 1},{1, 0, 1},{1, 0, 1},{0, 0, 0},{1, 0, 0},{0, 0, 0},{0, 1, 0},{1, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}}; w */ unsigned char offset_mumimo_llr_drange[29][3]= {{0, 6, 5},{0, 4, 5},{0, 4, 5},{0, 5, 4},{0, 5, 6},{0, 5, 3},{0, 4, 4},{0, 4, 4},{0, 3, 3},{0, 1, 2},{1, 1, 0},{1, 3, 2},{3, 4, 1},{2, 0, 0},{2, 2, 2},{1, 1, 1},{2, 1, 0},{2, 1, 1},{1, 0, 1},{1, 0, 1},{0, 0, 0},{1, 0, 0},{0, 0, 0},{0, 1, 0},{1, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}}; extern void print_shorts(char *s,int16_t *x); int rx_pdsch(PHY_VARS_UE *ue, PDSCH_t type, unsigned char eNB_id, unsigned char eNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference uint32_t frame, uint8_t subframe, unsigned char symbol, unsigned char first_symbol_flag, RX_type_t rx_type, unsigned char i_mod, unsigned char harq_pid) { LTE_UE_COMMON *common_vars = &ue->common_vars; LTE_UE_PDSCH **pdsch_vars; LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; PHY_MEASUREMENTS *measurements = &ue->measurements; LTE_UE_DLSCH_t **dlsch; int avg[4]; int avg_0[2]; int avg_1[2]; unsigned short mmse_flag=0; #if UE_TIMING_TRACE uint8_t slot = 0; #endif unsigned char aatx,aarx; unsigned short nb_rb = 0, round; int avgs = 0, rb; LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_harq = 0; uint8_t beamforming_mode; uint32_t *rballoc; int32_t **rxdataF_comp_ptr; int32_t **dl_ch_mag_ptr; int32_t codeword_TB0 = -1; int32_t codeword_TB1 = -1; switch (type) { case SI_PDSCH: pdsch_vars = &ue->pdsch_vars_SI[eNB_id]; dlsch = &ue->dlsch_SI[eNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; beamforming_mode = 0; break; case RA_PDSCH: pdsch_vars = &ue->pdsch_vars_ra[eNB_id]; dlsch = &ue->dlsch_ra[eNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; beamforming_mode = 0; break; case PDSCH: pdsch_vars = ue->pdsch_vars[ue->current_thread_id[subframe]]; dlsch = ue->dlsch[ue->current_thread_id[subframe]][eNB_id]; //printf("status TB0 = %d, status TB1 = %d \n", dlsch[0]->harq_processes[harq_pid]->status, dlsch[1]->harq_processes[harq_pid]->status); LOG_D(PHY,"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", frame,subframe,symbol,harq_pid, dlsch[0]->harq_processes[harq_pid]->status, dlsch[1]->harq_processes[harq_pid]->status); if ((dlsch[0]->harq_processes[harq_pid]->status == ACTIVE) && (dlsch[1]->harq_processes[harq_pid]->status == ACTIVE)){ codeword_TB0 = dlsch[0]->harq_processes[harq_pid]->codeword; codeword_TB1 = dlsch[1]->harq_processes[harq_pid]->codeword; dlsch0_harq = dlsch[codeword_TB0]->harq_processes[harq_pid]; dlsch1_harq = dlsch[codeword_TB1]->harq_processes[harq_pid]; #ifdef DEBUG_HARQ printf("[DEMOD] I am assuming both TBs are active\n"); #endif } else if ((dlsch[0]->harq_processes[harq_pid]->status == ACTIVE) && (dlsch[1]->harq_processes[harq_pid]->status != ACTIVE) ) { codeword_TB0 = dlsch[0]->harq_processes[harq_pid]->codeword; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; dlsch1_harq = NULL; codeword_TB1 = -1; #ifdef DEBUG_HARQ printf("[DEMOD] I am assuming only TB0 is active\n"); #endif } else if ((dlsch[0]->harq_processes[harq_pid]->status != ACTIVE) && (dlsch[1]->harq_processes[harq_pid]->status == ACTIVE) ){ codeword_TB1 = dlsch[1]->harq_processes[harq_pid]->codeword; dlsch0_harq = dlsch[1]->harq_processes[harq_pid]; dlsch1_harq = NULL; codeword_TB0 = -1; #ifdef DEBUG_HARQ printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", dlsch0_harq->codeword); #endif } else { LOG_E(PHY,"[UE][FATAL] Frame %d subframe %d: no active DLSCH\n",ue->proc.proc_rxtx[0].frame_rx,subframe); return(-1); } beamforming_mode = ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]; break; default: LOG_E(PHY,"[UE][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",ue->proc.proc_rxtx[0].frame_rx,subframe,type); return(-1); break; } #ifdef DEBUG_HARQ printf("[DEMOD] MIMO mode = %d\n", dlsch0_harq->mimo_mode); printf("[DEMOD] cw for TB0 = %d, cw for TB1 = %d\n", codeword_TB0, codeword_TB1); #endif DevAssert(dlsch0_harq); round = dlsch0_harq->round; //printf("round = %d\n", round); if (eNB_id > 2) { LOG_W(PHY,"dlsch_demodulation.c: Illegal eNB_id %d\n",eNB_id); return(-1); } if (!common_vars) { LOG_W(PHY,"dlsch_demodulation.c: Null common_vars\n"); return(-1); } if (!dlsch[0]) { LOG_W(PHY,"dlsch_demodulation.c: Null dlsch_ue pointer\n"); return(-1); } if (!pdsch_vars) { LOG_W(PHY,"dlsch_demodulation.c: Null pdsch_vars pointer\n"); return(-1); } if (!frame_parms) { LOG_W(PHY,"dlsch_demodulation.c: Null frame_parms\n"); return(-1); } if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) || ((frame_parms->Ncp == EXTENDED) && (symbol>=6))) rballoc = dlsch0_harq->rb_alloc_odd; else rballoc = dlsch0_harq->rb_alloc_even; if (dlsch0_harq->mimo_mode>DUALSTREAM_PUSCH_PRECODING) { LOG_E(PHY,"This transmission mode is not yet supported!\n"); return(-1); } if ((dlsch0_harq->mimo_mode==LARGE_CDD) || ((dlsch0_harq->mimo_mode>=DUALSTREAM_UNIFORM_PRECODING1) && (dlsch0_harq->mimo_mode<=DUALSTREAM_PUSCH_PRECODING))) { DevAssert(dlsch1_harq); if (eNB_id!=eNB_id_i) { LOG_E(PHY,"TM3/TM4 requires to set eNB_id==eNB_id_i!\n"); return(-1); } } #if UE_TIMING_TRACE if(symbol > ue->frame_parms.symbols_per_tti>>1) { slot = 1; } #endif #ifdef DEBUG_HARQ printf("Demod dlsch0_harq->pmi_alloc %d\n", dlsch0_harq->pmi_alloc); #endif if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) { #ifdef DEBUG_DLSCH_MOD LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch[0],dlsch0_harq->rb_alloc_even[0]); #endif #if UE_TIMING_TRACE start_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #endif nb_rb = dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id], pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, pdsch_vars[eNB_id]->pmi_ext, rballoc, symbol, subframe, ue->high_speed_flag, frame_parms, dlsch0_harq->mimo_mode); #ifdef DEBUG_DLSCH_MOD printf("dlsch: using pmi %lx, rb_alloc %x, pmi_ext ",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),*rballoc); for (rb=0;rb<nb_rb;rb++) printf("%d",pdsch_vars[eNB_id]->pmi_ext[rb]); printf("\n"); #endif if (rx_type >= rx_IC_single_stream) { if (eNB_id_i<ue->n_connected_eNB) // we are in TM5 nb_rb = dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id_i], pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, pdsch_vars[eNB_id_i]->pmi_ext, rballoc, symbol, subframe, ue->high_speed_flag, frame_parms, dlsch0_harq->mimo_mode); else nb_rb = dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id], pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, pdsch_vars[eNB_id_i]->pmi_ext, rballoc, symbol, subframe, ue->high_speed_flag, frame_parms, dlsch0_harq->mimo_mode); } } else if (beamforming_mode==0) { //else if nb_antennas_ports_eNB==1 && beamforming_mode == 0 nb_rb = dlsch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id], pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, pdsch_vars[eNB_id]->pmi_ext, rballoc, symbol, subframe, ue->high_speed_flag, frame_parms); if (rx_type==rx_IC_single_stream) { if (eNB_id_i<ue->n_connected_eNB) nb_rb = dlsch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id_i], pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, pdsch_vars[eNB_id_i]->pmi_ext, rballoc, symbol, subframe, ue->high_speed_flag, frame_parms); else nb_rb = dlsch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF, common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id], pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, pdsch_vars[eNB_id_i]->pmi_ext, rballoc, symbol, subframe, ue->high_speed_flag, frame_parms); } } else if (beamforming_mode==7) { //else if beamforming_mode == 7 nb_rb = dlsch_extract_rbs_TM7(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF, pdsch_vars[eNB_id]->dl_bf_ch_estimates, pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext, rballoc, symbol, subframe, ue->high_speed_flag, frame_parms); } else if(beamforming_mode>7) { LOG_W(PHY,"dlsch_demodulation: beamforming mode not supported yet.\n"); } //printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id); if (nb_rb==0) { // LOG_D(PHY,"dlsch_demodulation.c: nb_rb=0\n"); return(-1); } #if UE_TIMING_TRACE stop_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #if DISABLE_LOG_X printf("[AbsSFN %d.%d] Slot%d Symbol %d Flag %d type %d: Pilot/Data extraction %5.2f \n",frame,subframe,slot, symbol,ue->high_speed_flag,type,symbol,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #else LOG_I(PHY, "[AbsSFN %d.%d] Slot%d Symbol %d Flag %d type %d: Pilot/Data extraction %5.2f \n",frame,subframe,slot,symbol, ue->high_speed_flag,type,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #endif #endif #if UE_TIMING_TRACE start_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #endif aatx = frame_parms->nb_antenna_ports_eNB; aarx = frame_parms->nb_antennas_rx; dlsch_scale_channel(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, dlsch, symbol, nb_rb); if ((dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) && (rx_type==rx_IC_single_stream) && (eNB_id_i==ue->n_connected_eNB) && (dlsch0_harq->dl_power_off==0) ) // TM5 two-user { dlsch_scale_channel(pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, frame_parms, dlsch, symbol, nb_rb); } #if UE_TIMING_TRACE stop_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #if DISABLE_LOG_X printf("[AbsSFN %d.%d] Slot%d Symbol %d: Channel Scale %5.2f \n",frame,subframe,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #else LOG_I(PHY, "[AbsSFN %d.%d] Slot%d Symbol %d: Channel Scale %5.2f \n",frame,subframe,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #endif #endif #if UE_TIMING_TRACE start_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #endif if (first_symbol_flag==1) { if (beamforming_mode==0){ if (dlsch0_harq->mimo_mode<LARGE_CDD) { dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avg, symbol, nb_rb); avgs = 0; for (aatx=0;aatx<frame_parms->nb_antenna_ports_eNB;aatx++) for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) avgs = cmax(avgs,avg[(aatx<<1)+aarx]); pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1; } else if ((dlsch0_harq->mimo_mode == LARGE_CDD) || ((dlsch0_harq->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && (dlsch0_harq->mimo_mode <=DUALSTREAM_PUSCH_PRECODING))) { dlsch_channel_level_TM34(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, pdsch_vars[eNB_id]->pmi_ext, avg_0, avg_1, symbol, nb_rb, mmse_flag, dlsch0_harq->mimo_mode); LOG_D(PHY,"Channel Level TM34 avg_0 %d, avg_1 %d, rx_type %d, rx_standard %d, dlsch_demod_shift %d \n", avg_0[0], avg_1[0], rx_type, rx_standard, dlsch_demod_shift); if (rx_type>rx_standard) { avg_0[0] = (log2_approx(avg_0[0])/2) + dlsch_demod_shift;// + 2 ;//+ 4; avg_1[0] = (log2_approx(avg_1[0])/2) + dlsch_demod_shift;// + 2 ;//+ 4; pdsch_vars[eNB_id]->log2_maxh0 = cmax(avg_0[0],0); pdsch_vars[eNB_id]->log2_maxh1 = cmax(avg_1[0],0); // printf("dlsch_demod_shift %d\n", dlsch_demod_shift); } else { avg_0[0] = (log2_approx(avg_0[0])/2) - 13 + interf_unaw_shift; avg_1[0] = (log2_approx(avg_1[0])/2) - 13 + interf_unaw_shift; pdsch_vars[eNB_id]->log2_maxh0 = cmax(avg_0[0],0); pdsch_vars[eNB_id]->log2_maxh1 = cmax(avg_1[0],0); } } else if (dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) {// single-layer precoding (TM5, TM6) if ((rx_type==rx_IC_single_stream) && (eNB_id_i==ue->n_connected_eNB) && (dlsch0_harq->dl_power_off==0)) { dlsch_channel_level_TM56(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb); avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(i_mod>>1)-1]; pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0); } else if (dlsch0_harq->dl_power_off==1) { //TM6 dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avg, symbol, nb_rb); avgs = 0; for (aatx=0;aatx<frame_parms->nb_antenna_ports_eNB;aatx++) for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) avgs = cmax(avgs,avg[(aatx<<1)+aarx]); pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1; pdsch_vars[eNB_id]->log2_maxh++; } } } else if (beamforming_mode==7) dlsch_channel_level_TM7(pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext, frame_parms, avg, symbol, nb_rb); #ifdef UE_DEBUG_TRACE LOG_D(PHY,"[DLSCH] AbsSubframe %d.%d log2_maxh = %d [log2_maxh0 %d log2_maxh1 %d] (%d,%d)\n", frame%1024,subframe, pdsch_vars[eNB_id]->log2_maxh, pdsch_vars[eNB_id]->log2_maxh0, pdsch_vars[eNB_id]->log2_maxh1, avg[0],avgs); //LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode); #endif //wait until pdcch is decoded //proc->channel_level = 1; } /* uint32_t wait = 0; while(proc->channel_level == 0) { usleep(1); wait++; } */ #if T_TRACER if (type == PDSCH) { T(T_UE_PHY_PDSCH_ENERGY, T_INT(eNB_id), T_INT(frame%1024), T_INT(subframe), T_INT(avg[0]), T_INT(avg[1]), T_INT(avg[2]), T_INT(avg[3])); } #endif #if UE_TIMING_TRACE stop_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #if DISABLE_LOG_X printf("[AbsSFN %d.%d] Slot%d Symbol %d first_symbol_flag %d: Channel Level %5.2f \n",frame,subframe,slot,symbol,first_symbol_flag,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #else LOG_I(PHY, "[AbsSFN %d.%d] Slot%d Symbol %d first_symbol_flag %d: Channel Level %5.2f \n",frame,subframe,slot,symbol,first_symbol_flag,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #endif #endif #if UE_TIMING_TRACE start_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #endif if (rx_type==rx_IC_dual_stream && mmse_flag==1){ precode_channel_est(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, pdsch_vars[eNB_id], symbol, nb_rb, dlsch0_harq->mimo_mode); mmse_processing_oai(pdsch_vars[eNB_id], frame_parms, measurements, first_symbol_flag, dlsch0_harq->mimo_mode, mmse_flag, 0.0, symbol, nb_rb); } // Now channel compensation if (dlsch0_harq->mimo_mode<LARGE_CDD) { dlsch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, pdsch_vars[eNB_id]->rxdataF_comp0, (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL, frame_parms, symbol, first_symbol_flag, dlsch0_harq->Qm, nb_rb, pdsch_vars[eNB_id]->log2_maxh, measurements); // log2_maxh+I0_shift if (symbol == 5) { LOG_M("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } if ((rx_type==rx_IC_single_stream) && (eNB_id_i<ue->n_connected_eNB)) { dlsch_channel_compensation(pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_mag0, pdsch_vars[eNB_id_i]->dl_ch_magb0, pdsch_vars[eNB_id_i]->rxdataF_comp0, (aatx>1) ? pdsch_vars[eNB_id_i]->rho : NULL, frame_parms, symbol, first_symbol_flag, i_mod, nb_rb, pdsch_vars[eNB_id]->log2_maxh, measurements); // log2_maxh+I0_shift if (symbol == 5) { LOG_M("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); LOG_M("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->log2_maxh); } } else if ((dlsch0_harq->mimo_mode == LARGE_CDD) || ((dlsch0_harq->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && (dlsch0_harq->mimo_mode <=DUALSTREAM_PUSCH_PRECODING))){ dlsch_channel_compensation_TM34(frame_parms, pdsch_vars[eNB_id], measurements, eNB_id, symbol, dlsch0_harq->Qm, dlsch1_harq->Qm, harq_pid, dlsch0_harq->round, dlsch0_harq->mimo_mode, nb_rb, mmse_flag, pdsch_vars[eNB_id]->log2_maxh0, pdsch_vars[eNB_id]->log2_maxh1); if (symbol == 5) { LOG_M("rxF_comp_d00.m","rxF_c_d00",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM LOG_M("rxF_comp_d01.m","rxF_c_d01",&pdsch_vars[eNB_id]->rxdataF_comp0[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 LOG_M("rxF_comp_d10.m","rxF_c_d10",&pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 LOG_M("rxF_comp_d11.m","rxF_c_d11",&pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM } // compute correlation between signal and interference channels (rho12 and rho21) dlsch_dual_stream_correlation(frame_parms, // this is doing h11'*h12 and h21'*h22 symbol, nb_rb, pdsch_vars[eNB_id]->dl_ch_estimates_ext, &(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->log2_maxh0); //printf("rho stream1 =%d\n", &pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round] ); //to be optimized (just take complex conjugate) dlsch_dual_stream_correlation(frame_parms, // this is doing h12'*h11 and h22'*h21 symbol, nb_rb, &(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->log2_maxh1); // printf("rho stream2 =%d\n",&pdsch_vars[eNB_id]->dl_ch_rho2_ext ); //printf("TM3 log2_maxh : %d\n",pdsch_vars[eNB_id]->log2_maxh); if (symbol == 5) { LOG_M("rho0_0.m","rho0_0",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM LOG_M("rho2_0.m","rho2_0",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 LOG_M("rho0_1.m.m","rho0_1",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 LOG_M("rho2_1.m","rho2_1",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM } } else if (dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) {// single-layer precoding (TM5, TM6) if ((rx_type==rx_IC_single_stream) && (eNB_id_i==ue->n_connected_eNB) && (dlsch0_harq->dl_power_off==0)) { dlsch_channel_compensation_TM56(pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->pmi_ext, frame_parms, measurements, eNB_id, symbol, dlsch0_harq->Qm, nb_rb, pdsch_vars[eNB_id]->log2_maxh, dlsch0_harq->dl_power_off); for (rb=0; rb<nb_rb; rb++) { switch(pdsch_vars[eNB_id]->pmi_ext[rb]) { case 0: pdsch_vars[eNB_id_i]->pmi_ext[rb]=1; break; case 1: pdsch_vars[eNB_id_i]->pmi_ext[rb]=0; break; case 2: pdsch_vars[eNB_id_i]->pmi_ext[rb]=3; break; case 3: pdsch_vars[eNB_id_i]->pmi_ext[rb]=2; break; } // if (rb==0) // printf("pmi %d, pmi_i %d\n",pdsch_vars[eNB_id]->pmi_ext[rb],pdsch_vars[eNB_id_i]->pmi_ext[rb]); } dlsch_channel_compensation_TM56(pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_mag0, pdsch_vars[eNB_id_i]->dl_ch_magb0, pdsch_vars[eNB_id_i]->rxdataF_comp0, pdsch_vars[eNB_id_i]->pmi_ext, frame_parms, measurements, eNB_id_i, symbol, i_mod, nb_rb, pdsch_vars[eNB_id]->log2_maxh, dlsch0_harq->dl_power_off); if (symbol==5) { LOG_M("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); LOG_M("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->log2_maxh); } else if (dlsch0_harq->dl_power_off==1) { dlsch_channel_compensation_TM56(pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->pmi_ext, frame_parms, measurements, eNB_id, symbol, dlsch0_harq->Qm, nb_rb, pdsch_vars[eNB_id]->log2_maxh, 1); } } else if (dlsch0_harq->mimo_mode==TM7) { //TM7 dlsch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext, pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, pdsch_vars[eNB_id]->rxdataF_comp0, (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL, frame_parms, symbol, first_symbol_flag, get_Qm(dlsch0_harq->mcs), nb_rb, //9, pdsch_vars[eNB_id]->log2_maxh, measurements); // log2_maxh+I0_shift } #if UE_TIMING_TRACE stop_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #if DISABLE_LOG_X printf("[AbsSFN %d.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n",frame,subframe,slot,symbol,pdsch_vars[eNB_id]->log2_maxh,proc->channel_level,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #else LOG_I(PHY, "[AbsSFN %d.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n",frame,subframe,slot,symbol,pdsch_vars[eNB_id]->log2_maxh,proc->channel_level,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #endif #endif // MRC #if UE_TIMING_TRACE start_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #endif if (frame_parms->nb_antennas_rx > 1) { if ((dlsch0_harq->mimo_mode == LARGE_CDD) || ((dlsch0_harq->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && (dlsch0_harq->mimo_mode <=DUALSTREAM_PUSCH_PRECODING))){ // TM3 or TM4 if (frame_parms->nb_antenna_ports_eNB == 2) { dlsch_detection_mrc_TM34(frame_parms, pdsch_vars[eNB_id], harq_pid, dlsch0_harq->round, symbol, nb_rb, 1); if (symbol == 5) { LOG_M("rho0_mrc.m","rho0_0",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM LOG_M("rho2_mrc.m","rho2_0",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 } } } else { dlsch_detection_mrc(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id_i]->rxdataF_comp0, pdsch_vars[eNB_id]->rho, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, pdsch_vars[eNB_id_i]->dl_ch_mag0, pdsch_vars[eNB_id_i]->dl_ch_magb0, symbol, nb_rb, rx_type==rx_IC_single_stream); } } // printf("Combining"); if ((dlsch0_harq->mimo_mode == SISO) || ((dlsch0_harq->mimo_mode >= UNIFORM_PRECODING11) && (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0)) || (dlsch0_harq->mimo_mode == TM7)) { /* dlsch_siso(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp, pdsch_vars[eNB_id_i]->rxdataF_comp, symbol, nb_rb); */ } else if (dlsch0_harq->mimo_mode == ALAMOUTI) { dlsch_alamouti(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol, nb_rb); } // printf("LLR"); if ((dlsch0_harq->mimo_mode == LARGE_CDD) || ((dlsch0_harq->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && (dlsch0_harq->mimo_mode <=DUALSTREAM_PUSCH_PRECODING))) { rxdataF_comp_ptr = pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round]; dl_ch_mag_ptr = pdsch_vars[eNB_id]->dl_ch_mag1[harq_pid][round]; } else { rxdataF_comp_ptr = pdsch_vars[eNB_id_i]->rxdataF_comp0; dl_ch_mag_ptr = pdsch_vars[eNB_id_i]->dl_ch_mag0; //i_mod should have been passed as a parameter } #if UE_TIMING_TRACE stop_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #if DISABLE_LOG_X printf("[AbsSFN %d.%d] Slot%d Symbol %d: Channel Combine %5.2f \n",frame,subframe,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #else LOG_I(PHY, "[AbsSFN %d.%d] Slot%d Symbol %d: Channel Combine %5.2f \n",frame,subframe,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #endif #endif #if UE_TIMING_TRACE start_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #endif //printf("LLR dlsch0_harq->Qm %d rx_type %d cw0 %d cw1 %d symbol %d \n",dlsch0_harq->Qm,rx_type,codeword_TB0,codeword_TB1,symbol); // compute LLRs // -> // compute @pointer where llrs should filled for this ofdm-symbol int8_t *pllr_symbol_cw0; int8_t *pllr_symbol_cw1; uint32_t llr_offset_symbol; llr_offset_symbol = pdsch_vars[eNB_id]->llr_offset[symbol]; pllr_symbol_cw0 = (int8_t*)pdsch_vars[eNB_id]->llr[0]; pllr_symbol_cw1 = (int8_t*)pdsch_vars[eNB_id]->llr[1]; pllr_symbol_cw0 += llr_offset_symbol; pllr_symbol_cw1 += llr_offset_symbol; /* LOG_I(PHY,"compute LLRs [AbsSubframe %d.%d-%d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %p @LLR Buff(symb) %p\n", frame, subframe,symbol, nb_rb,dlsch0_harq->Qm, pdsch_vars[eNB_id]->llr_length[symbol], pdsch_vars[eNB_id]->llr_offset[symbol], (int16_t*)pdsch_vars[eNB_id]->llr[0], pllr_symbol_cw0); */ switch (dlsch0_harq->Qm) { case 2 : if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { dlsch_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, (int16_t*)pllr_symbol_cw0, symbol, first_symbol_flag, nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), beamforming_mode); } else if (codeword_TB0 == -1){ dlsch_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, (int16_t*)pllr_symbol_cw1, symbol, first_symbol_flag, nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { if (dlsch1_harq->Qm == 2) { dlsch_qpsk_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, rxdataF_comp_ptr, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { dlsch_qpsk_qpsk_llr(frame_parms, rxdataF_comp_ptr, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else if (dlsch1_harq->Qm == 4) { dlsch_qpsk_16qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i dl_ch_mag_ptr,//i pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { dlsch_16qam_qpsk_llr(frame_parms, rxdataF_comp_ptr, pdsch_vars[eNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else { dlsch_qpsk_64qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i dl_ch_mag_ptr,//i pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { dlsch_64qam_qpsk_llr(frame_parms, rxdataF_comp_ptr, pdsch_vars[eNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } } break; case 4 : if ((rx_type==rx_standard ) || (codeword_TB1 == -1)) { dlsch_16qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->llr[0], pdsch_vars[eNB_id]->dl_ch_mag0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128, beamforming_mode); } else if (codeword_TB0 == -1){ dlsch_16qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->llr[1], pdsch_vars[eNB_id]->dl_ch_mag0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream, beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { if (dlsch1_harq->Qm == 2) { dlsch_16qam_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { dlsch_qpsk_16qam_llr(frame_parms, rxdataF_comp_ptr, pdsch_vars[eNB_id]->rxdataF_comp0,//i pdsch_vars[eNB_id]->dl_ch_mag0,//i pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else if (dlsch1_harq->Qm == 4) { dlsch_16qam_16qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i pdsch_vars[eNB_id]->dl_ch_mag0, dl_ch_mag_ptr,//i pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { dlsch_16qam_16qam_llr(frame_parms, rxdataF_comp_ptr, pdsch_vars[eNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, pdsch_vars[eNB_id]->dl_ch_mag0,//i pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else { dlsch_16qam_64qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i pdsch_vars[eNB_id]->dl_ch_mag0, dl_ch_mag_ptr,//i pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { dlsch_64qam_16qam_llr(frame_parms, rxdataF_comp_ptr, pdsch_vars[eNB_id]->rxdataF_comp0, dl_ch_mag_ptr, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } } break; case 6 : if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { dlsch_64qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, (int16_t*)pllr_symbol_cw0, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol], beamforming_mode); } else if (codeword_TB0 == -1){ dlsch_64qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, (int16_t*)pllr_symbol_cw1, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol], beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { if (dlsch1_harq->Qm == 2) { dlsch_64qam_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { dlsch_qpsk_64qam_llr(frame_parms, rxdataF_comp_ptr, pdsch_vars[eNB_id]->rxdataF_comp0,//i pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else if (dlsch1_harq->Qm == 4) { dlsch_64qam_16qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i pdsch_vars[eNB_id]->dl_ch_mag0, dl_ch_mag_ptr,//i pdsch_vars[eNB_id]->dl_ch_rho2_ext, pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { dlsch_16qam_64qam_llr(frame_parms, rxdataF_comp_ptr, pdsch_vars[eNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, pdsch_vars[eNB_id]->dl_ch_mag0,//i pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], pdsch_vars[eNB_id]->llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128_2ndstream); } } else { dlsch_64qam_64qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i pdsch_vars[eNB_id]->dl_ch_mag0, dl_ch_mag_ptr,//i pdsch_vars[eNB_id]->dl_ch_rho2_ext, (int16_t*)pllr_symbol_cw0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol]); if (rx_type==rx_IC_dual_stream) { dlsch_64qam_64qam_llr(frame_parms, rxdataF_comp_ptr, pdsch_vars[eNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, pdsch_vars[eNB_id]->dl_ch_mag0,//i pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], (int16_t*)pllr_symbol_cw1, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol]); } } } break; default: LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); return(-1); break; } if (dlsch1_harq) { switch (get_Qm(dlsch1_harq->mcs)) { case 2 : if (rx_type==rx_standard) { dlsch_qpsk_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, (int16_t*)pllr_symbol_cw0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol), beamforming_mode); } break; case 4: if (rx_type==rx_standard) { dlsch_16qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, pdsch_vars[eNB_id]->llr[0], pdsch_vars[eNB_id]->dl_ch_mag0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol), pdsch_vars[eNB_id]->llr128, beamforming_mode); } break; case 6 : if (rx_type==rx_standard) { dlsch_64qam_llr(frame_parms, pdsch_vars[eNB_id]->rxdataF_comp0, (int16_t*)pllr_symbol_cw0, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol), pdsch_vars[eNB_id]->llr_offset[symbol], beamforming_mode); } break; default: LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); return(-1); break; } } #if UE_TIMING_TRACE stop_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #if DISABLE_LOG_X printf("[AbsSFN %d.%d] Slot%d Symbol %d: LLR Computation %5.2f \n",frame,subframe,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #else LOG_D(PHY, "[AbsSFN %d.%d] Slot%d Symbol %d: LLR Computation %5.2f \n",frame,subframe,slot,symbol,ue->generic_stat_bis[ue->current_thread_id[subframe]][slot].p_time/(cpuf*1000.0)); #endif #endif // Please keep it: useful for debugging #if 0 if( (symbol == 13) && (subframe==0) && (dlsch0_harq->Qm == 6) /*&& (nb_rb==25)*/) { LOG_E(PHY,"Dump Phy Chan Est \n"); if(1) { #if 1 LOG_M("rxdataF0.m" , "rxdataF0", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[0][0],14*frame_parms->ofdm_symbol_size,1,1); //LOG_M("rxdataF1.m" , "rxdataF1", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[0][0],14*frame_parms->ofdm_symbol_size,1,1); LOG_M("dl_ch_estimates00.m", "dl_ch_estimates00", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id][0][0],14*frame_parms->ofdm_symbol_size,1,1); //LOG_M("dl_ch_estimates01.m", "dl_ch_estimates01", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id][1][0],14*frame_parms->ofdm_symbol_size,1,1); //LOG_M("dl_ch_estimates10.m", "dl_ch_estimates10", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id][2][0],14*frame_parms->ofdm_symbol_size,1,1); //LOG_M("dl_ch_estimates11.m", "dl_ch_estimates11", &common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id][3][0],14*frame_parms->ofdm_symbol_size,1,1); //LOG_M("rxdataF_ext00.m" , "rxdataF_ext00", &pdsch_vars[eNB_id]->rxdataF_ext[0][0],14*frame_parms->N_RB_DL*12,1,1); //LOG_M("rxdataF_ext01.m" , "rxdataF_ext01", &pdsch_vars[eNB_id]->rxdataF_ext[1][0],14*frame_parms->N_RB_DL*12,1,1); //LOG_M("rxdataF_ext10.m" , "rxdataF_ext10", &pdsch_vars[eNB_id]->rxdataF_ext[2][0],14*frame_parms->N_RB_DL*12,1,1); //LOG_M("rxdataF_ext11.m" , "rxdataF_ext11", &pdsch_vars[eNB_id]->rxdataF_ext[3][0],14*frame_parms->N_RB_DL*12,1,1); LOG_M("dl_ch_estimates_ext00.m", "dl_ch_estimates_ext00", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[0][0],14*frame_parms->N_RB_DL*12,1,1); //LOG_M("dl_ch_estimates_ext01.m", "dl_ch_estimates_ext01", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[1][0],14*frame_parms->N_RB_DL*12,1,1); //LOG_M("dl_ch_estimates_ext10.m", "dl_ch_estimates_ext10", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[2][0],14*frame_parms->N_RB_DL*12,1,1); //LOG_M("dl_ch_estimates_ext11.m", "dl_ch_estimates_ext11", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[3][0],14*frame_parms->N_RB_DL*12,1,1); LOG_M("rxdataF_comp00.m","rxdataF_comp00", &pdsch_vars[eNB_id]->rxdataF_comp0[0][0],14*frame_parms->N_RB_DL*12,1,1); //LOG_M("rxdataF_comp01.m","rxdataF_comp01", &pdsch_vars[eNB_id]->rxdataF_comp0[1][0],14*frame_parms->N_RB_DL*12,1,1); //LOG_M("rxdataF_comp10.m","rxdataF_comp10", &pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][0][0],14*frame_parms->N_RB_DL*12,1,1); //LOG_M("rxdataF_comp11.m","rxdataF_comp11", &pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][1][0],14*frame_parms->N_RB_DL*12,1,1); #endif LOG_M("llr0.m","llr0", &pdsch_vars[eNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); //LOG_M("llr1.m","llr1", &pdsch_vars[eNB_id]->llr[1][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); AssertFatal(0," "); } } #endif T(T_UE_PHY_PDSCH_IQ, T_INT(eNB_id), T_INT(frame%1024), T_INT(subframe), T_INT(nb_rb), T_INT(frame_parms->N_RB_UL), T_INT(frame_parms->symbols_per_tti), T_BUFFER(&pdsch_vars[eNB_id]->rxdataF_comp0[eNB_id][0], 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_tti*2)); return 0; } //============================================================================================== // Pre-processing for LLR computation //============================================================================================== void dlsch_channel_compensation(int **rxdataF_ext, int **dl_ch_estimates_ext, int **dl_ch_mag, int **dl_ch_magb, int **rxdataF_comp, int **rho, LTE_DL_FRAME_PARMS *frame_parms, unsigned char symbol, uint8_t first_symbol_flag, unsigned char mod_order, unsigned short nb_rb, unsigned char output_shift, PHY_MEASUREMENTS *measurements) { #if defined(__i386) || defined(__x86_64) unsigned short rb; unsigned char aatx,aarx,symbol_mod,pilots=0; __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { if (frame_parms->nb_antenna_ports_eNB==1) // 10 out of 12 so don't reduce size nb_rb=1+(5*nb_rb/6); else pilots=1; } for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { if (mod_order == 4) { QAM_amp128 = _mm_set1_epi16(QAM16_n1); // 2/sqrt(10) QAM_amp128b = _mm_setzero_si128(); } else if (mod_order == 6) { QAM_amp128 = _mm_set1_epi16(QAM64_n1); // QAM_amp128b = _mm_set1_epi16(QAM64_n2); } for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; //print_shorts("dl_ch128[0]=",&dl_ch128[0]);*/ dl_ch_mag128 = (__m128i *)&dl_ch_mag[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128b = (__m128i *)&dl_ch_magb[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { if (mod_order>2) { // get channel amplitude if not QPSK mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128[0]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_madd_epi16(dl_ch128[1],dl_ch128[1]); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); // store channel magnitude here in a new field of dlsch dl_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[0] = dl_ch_mag128[0]; dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1); //print_ints("Re(ch):",(int16_t*)&mmtmpD0); //print_shorts("QAM_amp:",(int16_t*)&QAM_amp128); //print_shorts("mag:",(int16_t*)&dl_ch_mag128[0]); dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[1] = dl_ch_mag128[1]; dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128); dl_ch_mag128[1] = _mm_slli_epi16(dl_ch_mag128[1],1); if (pilots==0) { mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128[2]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0); dl_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1); dl_ch_mag128b[2] = dl_ch_mag128[2]; dl_ch_mag128[2] = _mm_mulhi_epi16(dl_ch_mag128[2],QAM_amp128); dl_ch_mag128[2] = _mm_slli_epi16(dl_ch_mag128[2],1); } dl_ch_mag128b[0] = _mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b); dl_ch_mag128b[0] = _mm_slli_epi16(dl_ch_mag128b[0],1); dl_ch_mag128b[1] = _mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b); dl_ch_mag128b[1] = _mm_slli_epi16(dl_ch_mag128b[1],1); if (pilots==0) { dl_ch_mag128b[2] = _mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b); dl_ch_mag128b[2] = _mm_slli_epi16(dl_ch_mag128b[2],1); } } // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch128); // print_shorts("pack:",rxdataF_comp128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+1); // print_shorts("ch:",dl_ch128+1); // print_shorts("pack:",rxdataF_comp128+1); if (pilots==0) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+2); // print_shorts("ch:",dl_ch128+2); // print_shorts("pack:",rxdataF_comp128+2); dl_ch128+=3; dl_ch_mag128+=3; dl_ch_mag128b+=3; rxdataF128+=3; rxdataF_comp128+=3; } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less dl_ch128+=2; dl_ch_mag128+=2; dl_ch_mag128b+=2; rxdataF128+=2; rxdataF_comp128+=2; } } } } if (rho) { for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { rho128 = (__m128i *)&rho[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128_2 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128_2[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rho128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); //print_shorts("rx:",dl_ch128_2); //print_shorts("ch:",dl_ch128); //print_shorts("pack:",rho128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128_2[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rho128[1] =_mm_packs_epi32(mmtmpD2,mmtmpD3); //print_shorts("rx:",dl_ch128_2+1); //print_shorts("ch:",dl_ch128+1); //print_shorts("pack:",rho128+1); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128_2[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rho128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); //print_shorts("rx:",dl_ch128_2+2); //print_shorts("ch:",dl_ch128+2); //print_shorts("pack:",rho128+2); dl_ch128+=3; dl_ch128_2+=3; rho128+=3; } if (first_symbol_flag==1) { measurements->rx_correlation[0][aarx] = signal_energy(&rho[aarx][symbol*frame_parms->N_RB_DL*12],rb*12); } } } _mm_empty(); _m_empty(); #elif defined(__arm__) unsigned short rb; unsigned char aatx,aarx,symbol_mod,pilots=0; int16x4_t *dl_ch128,*dl_ch128_2,*rxdataF128; int32x4_t mmtmpD0,mmtmpD1,mmtmpD0b,mmtmpD1b; int16x8_t *dl_ch_mag128,*dl_ch_mag128b,mmtmpD2,mmtmpD3,mmtmpD4; int16x8_t QAM_amp128,QAM_amp128b; int16x4x2_t *rxdataF_comp128,*rho128; int16_t conj[4]__attribute__((aligned(16))) = {1,-1,1,-1}; int32x4_t output_shift128 = vmovq_n_s32(-(int32_t)output_shift); symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { if (frame_parms->nb_antenna_ports_eNB==1) { // 10 out of 12 so don't reduce size nb_rb=1+(5*nb_rb/6); } else { pilots=1; } } for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { if (mod_order == 4) { QAM_amp128 = vmovq_n_s16(QAM16_n1); // 2/sqrt(10) QAM_amp128b = vmovq_n_s16(0); } else if (mod_order == 6) { QAM_amp128 = vmovq_n_s16(QAM64_n1); // QAM_amp128b = vmovq_n_s16(QAM64_n2); } // printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol); for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch128 = (int16x4_t*)&dl_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128 = (int16x8_t*)&dl_ch_mag[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128b = (int16x8_t*)&dl_ch_magb[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (int16x4_t*)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (int16x4x2_t*)&rxdataF_comp[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { if (mod_order>2) { // get channel amplitude if not QPSK mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128[0]); // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits mmtmpD1 = vmull_s16(dl_ch128[1], dl_ch128[1]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits mmtmpD0 = vmull_s16(dl_ch128[2], dl_ch128[2]); mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); mmtmpD1 = vmull_s16(dl_ch128[3], dl_ch128[3]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); if (pilots==0) { mmtmpD0 = vmull_s16(dl_ch128[4], dl_ch128[4]); mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); mmtmpD1 = vmull_s16(dl_ch128[5], dl_ch128[5]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); } dl_ch_mag128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128b); dl_ch_mag128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128b); dl_ch_mag128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128); dl_ch_mag128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128); if (pilots==0) { dl_ch_mag128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128b); dl_ch_mag128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128); } } mmtmpD0 = vmull_s16(dl_ch128[0], rxdataF128[0]); //mmtmpD0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] mmtmpD1 = vmull_s16(dl_ch128[1], rxdataF128[1]); //mmtmpD1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); //mmtmpD0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[0],*(int16x4_t*)conj)), rxdataF128[0]); //mmtmpD0 = [-Im(ch[0])Re(rx[0]) Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1]) Re(ch[1])Im(rx[1])] mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[1],*(int16x4_t*)conj)), rxdataF128[1]); //mmtmpD0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])] mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); //mmtmpD1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])] mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp128[0] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); mmtmpD0 = vmull_s16(dl_ch128[2], rxdataF128[2]); mmtmpD1 = vmull_s16(dl_ch128[3], rxdataF128[3]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[2],*(int16x4_t*)conj)), rxdataF128[2]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[3],*(int16x4_t*)conj)), rxdataF128[3]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp128[1] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); if (pilots==0) { mmtmpD0 = vmull_s16(dl_ch128[4], rxdataF128[4]); mmtmpD1 = vmull_s16(dl_ch128[5], rxdataF128[5]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[4],*(int16x4_t*)conj)), rxdataF128[4]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[5],*(int16x4_t*)conj)), rxdataF128[5]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp128[2] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); dl_ch128+=6; dl_ch_mag128+=3; dl_ch_mag128b+=3; rxdataF128+=6; rxdataF_comp128+=3; } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less dl_ch128+=4; dl_ch_mag128+=2; dl_ch_mag128b+=2; rxdataF128+=4; rxdataF_comp128+=2; } } } } if (rho) { for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { rho128 = (int16x4x2_t*)&rho[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128 = (int16x4_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128_2 = (int16x4_t*)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128_2[0]); mmtmpD1 = vmull_s16(dl_ch128[1], dl_ch128_2[1]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[0],*(int16x4_t*)conj)), dl_ch128_2[0]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[1],*(int16x4_t*)conj)), dl_ch128_2[1]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rho128[0] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); mmtmpD0 = vmull_s16(dl_ch128[2], dl_ch128_2[2]); mmtmpD1 = vmull_s16(dl_ch128[3], dl_ch128_2[3]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[2],*(int16x4_t*)conj)), dl_ch128_2[2]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[3],*(int16x4_t*)conj)), dl_ch128_2[3]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rho128[1] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); mmtmpD0 = vmull_s16(dl_ch128[0], dl_ch128_2[0]); mmtmpD1 = vmull_s16(dl_ch128[1], dl_ch128_2[1]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[4],*(int16x4_t*)conj)), dl_ch128_2[4]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch128[5],*(int16x4_t*)conj)), dl_ch128_2[5]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rho128[2] = vzip_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); dl_ch128+=6; dl_ch128_2+=6; rho128+=3; } if (first_symbol_flag==1) { measurements->rx_correlation[0][aarx] = signal_energy(&rho[aarx][symbol*frame_parms->N_RB_DL*12],rb*12); } } } #endif } void dlsch_channel_compensation_core(int **rxdataF_ext, int **dl_ch_estimates_ext, int **dl_ch_mag, int **dl_ch_magb, int **rxdataF_comp, int **rho, unsigned char n_tx, unsigned char n_rx, unsigned char mod_order, unsigned char output_shift, int length, int start_point) { unsigned short ii; int length_mod8 = 0; int length2; __m128i *dl_ch128,*dl_ch_mag128,*dl_ch_mag128b, *dl_ch128_2, *rxdataF128,*rxdataF_comp128,*rho128; __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; int aatx = 0, aarx = 0; for (aatx=0; aatx<n_tx; aatx++) { if (mod_order == 4) { QAM_amp128 = _mm_set1_epi16(QAM16_n1); // 2/sqrt(10) QAM_amp128b = _mm_setzero_si128(); } else if (mod_order == 6) { QAM_amp128 = _mm_set1_epi16(QAM64_n1); // QAM_amp128b = _mm_set1_epi16(QAM64_n2); } for (aarx=0; aarx<n_rx; aarx++) { dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aatx*n_rx + aarx][start_point]; dl_ch_mag128 = (__m128i *)&dl_ch_mag[aatx*n_rx + aarx][start_point]; dl_ch_mag128b = (__m128i *)&dl_ch_magb[aatx*n_rx + aarx][start_point]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][start_point]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[aatx*n_rx + aarx][start_point]; length_mod8 = length&7; if (length_mod8 == 0){ length2 = length>>3; for (ii=0; ii<length2; ++ii) { if (mod_order>2) { // get channel amplitude if not QPSK mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128[0]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_madd_epi16(dl_ch128[1],dl_ch128[1]); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); // store channel magnitude here in a new field of dlsch dl_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[0] = dl_ch_mag128[0]; dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1); //print_ints("Re(ch):",(int16_t*)&mmtmpD0); //print_shorts("QAM_amp:",(int16_t*)&QAM_amp128); //print_shorts("mag:",(int16_t*)&dl_ch_mag128[0]); dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[1] = dl_ch_mag128[1]; dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128); dl_ch_mag128[1] = _mm_slli_epi16(dl_ch_mag128[1],1); dl_ch_mag128b[0] = _mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b); dl_ch_mag128b[0] = _mm_slli_epi16(dl_ch_mag128b[0],1); dl_ch_mag128b[1] = _mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b); dl_ch_mag128b[1] = _mm_slli_epi16(dl_ch_mag128b[1],1); } // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch128); // print_shorts("pack:",rxdataF_comp128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+1); // print_shorts("ch:",dl_ch128+1); //print_shorts("pack:",rxdataF_comp128+1); dl_ch128+=2; dl_ch_mag128+=2; dl_ch_mag128b+=2; rxdataF128+=2; rxdataF_comp128+=2; } }else { printf ("Channel Compensation: Received number of subcarriers is not multiple of 8, \n" "need to adapt the code!\n"); } } } /*This part of code makes sense only for processing in 2x2 blocks*/ if (rho) { for (aarx=0; aarx<n_rx; aarx++) { rho128 = (__m128i *)&rho[aarx][start_point]; dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][start_point]; dl_ch128_2 = (__m128i *)&dl_ch_estimates_ext[2+aarx][start_point]; if (length_mod8 == 0){ length2 = length>>3; for (ii=0; ii<length2; ++ii) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128_2[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rho128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); //print_shorts("rx:",dl_ch128_2); //print_shorts("ch:",dl_ch128); //print_shorts("pack:",rho128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128_2[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rho128[1] =_mm_packs_epi32(mmtmpD2,mmtmpD3); dl_ch128+=2; dl_ch128_2+=2; rho128+=2; } }else { printf ("Channel Compensation: Received number of subcarriers is not multiple of 8, \n" "need to adapt the code!\n"); } } } _mm_empty(); _m_empty(); } #if defined(__x86_64__) || defined(__i386__) void prec2A_TM56_128(unsigned char pmi,__m128i *ch0,__m128i *ch1) { __m128i amp; amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); switch (pmi) { case 0 : // +1 +1 // print_shorts("phase 0 :ch0",ch0); // print_shorts("phase 0 :ch1",ch1); ch0[0] = _mm_adds_epi16(ch0[0],ch1[0]); break; case 1 : // +1 -1 // print_shorts("phase 1 :ch0",ch0); // print_shorts("phase 1 :ch1",ch1); ch0[0] = _mm_subs_epi16(ch0[0],ch1[0]); // print_shorts("phase 1 :ch0-ch1",ch0); break; case 2 : // +1 +j ch1[0] = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); ch1[0] = _mm_shufflelo_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch1[0] = _mm_shufflehi_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch0[0] = _mm_subs_epi16(ch0[0],ch1[0]); break; // +1 -j case 3 : ch1[0] = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); ch1[0] = _mm_shufflelo_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch1[0] = _mm_shufflehi_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch0[0] = _mm_adds_epi16(ch0[0],ch1[0]); break; } ch0[0] = _mm_mulhi_epi16(ch0[0],amp); ch0[0] = _mm_slli_epi16(ch0[0],1); _mm_empty(); _m_empty(); } #elif defined(__arm__) void prec2A_TM56_128(unsigned char pmi,__m128i *ch0,__m128i *ch1) { // sqrt(2) is already taken into account in computation sqrt_rho_a, sqrt_rho_b, //so removed it //__m128i amp; //amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); switch (pmi) { case 0 : // +1 +1 // print_shorts("phase 0 :ch0",ch0); // print_shorts("phase 0 :ch1",ch1); ch0[0] = _mm_adds_epi16(ch0[0],ch1[0]); break; case 1 : // +1 -1 // print_shorts("phase 1 :ch0",ch0); // print_shorts("phase 1 :ch1",ch1); ch0[0] = _mm_subs_epi16(ch0[0],ch1[0]); // print_shorts("phase 1 :ch0-ch1",ch0); break; case 2 : // +1 +j ch1[0] = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); ch1[0] = _mm_shufflelo_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch1[0] = _mm_shufflehi_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch0[0] = _mm_subs_epi16(ch0[0],ch1[0]); break; // +1 -j case 3 : ch1[0] = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); ch1[0] = _mm_shufflelo_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch1[0] = _mm_shufflehi_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch0[0] = _mm_adds_epi16(ch0[0],ch1[0]); break; } //ch0[0] = _mm_mulhi_epi16(ch0[0],amp); //ch0[0] = _mm_slli_epi16(ch0[0],1); _mm_empty(); _m_empty(); } #endif // precoding is stream 0 .5(1,1) .5(1,-1) .5(1,1) .5(1,-1) // stream 1 .5(1,-1) .5(1,1) .5(1,-1) .5(1,1) // store "precoded" channel for stream 0 in ch0, stream 1 in ch1 short TM3_prec[8]__attribute__((aligned(16))) = {1,1,-1,-1,1,1,-1,-1} ; void prec2A_TM3_128(__m128i *ch0,__m128i *ch1) { __m128i amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); __m128i tmp0,tmp1; //_mm_mulhi_epi16 // print_shorts("prec2A_TM3 ch0 (before):",ch0); // print_shorts("prec2A_TM3 ch1 (before):",ch1); tmp0 = ch0[0]; tmp1 = _mm_sign_epi16(ch1[0],((__m128i*)&TM3_prec)[0]); // print_shorts("prec2A_TM3 ch1*s (mid):",(__m128i*)TM3_prec); ch0[0] = _mm_adds_epi16(ch0[0],tmp1); ch1[0] = _mm_subs_epi16(tmp0,tmp1); ch0[0] = _mm_mulhi_epi16(ch0[0],amp); ch0[0] = _mm_slli_epi16(ch0[0],1); ch1[0] = _mm_mulhi_epi16(ch1[0],amp); ch1[0] = _mm_slli_epi16(ch1[0],1); // print_shorts("prec2A_TM3 ch0 (mid):",&tmp0); // print_shorts("prec2A_TM3 ch1 (mid):",ch1); //ch0[0] = _mm_mulhi_epi16(ch0[0],amp); //ch0[0] = _mm_slli_epi16(ch0[0],1); //ch1[0] = _mm_mulhi_epi16(ch1[0],amp); //ch1[0] = _mm_slli_epi16(ch1[0],1); //ch0[0] = _mm_srai_epi16(ch0[0],1); //ch1[0] = _mm_srai_epi16(ch1[0],1); // print_shorts("prec2A_TM3 ch0 (after):",ch0); // print_shorts("prec2A_TM3 ch1 (after):",ch1); _mm_empty(); _m_empty(); } // pmi = 0 => stream 0 (1,1), stream 1 (1,-1) // pmi = 1 => stream 0 (1,j), stream 2 (1,-j) void prec2A_TM4_128(int pmi,__m128i *ch0,__m128i *ch1) { // sqrt(2) is already taken into account in computation sqrt_rho_a, sqrt_rho_b, //so divide by 2 is replaced by divide by sqrt(2). // printf ("demod pmi=%d\n", pmi); __m128i amp; amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); __m128i tmp0,tmp1; // print_shorts("prec2A_TM4 ch0 (before):",ch0); // print_shorts("prec2A_TM4 ch1 (before):",ch1); if (pmi == 0) { //[1 1;1 -1] tmp0 = ch0[0]; tmp1 = ch1[0]; ch0[0] = _mm_adds_epi16(tmp0,tmp1); ch1[0] = _mm_subs_epi16(tmp0,tmp1); } else { //ch0+j*ch1 ch0-j*ch1 tmp0 = ch0[0]; tmp1 = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); tmp1 = _mm_shufflelo_epi16(tmp1,_MM_SHUFFLE(2,3,0,1)); tmp1 = _mm_shufflehi_epi16(tmp1,_MM_SHUFFLE(2,3,0,1)); ch0[0] = _mm_subs_epi16(tmp0,tmp1); ch1[0] = _mm_add_epi16(tmp0,tmp1); } //print_shorts("prec2A_TM4 ch0 (middle):",ch0); //print_shorts("prec2A_TM4 ch1 (middle):",ch1); ch0[0] = _mm_mulhi_epi16(ch0[0],amp); ch0[0] = _mm_slli_epi16(ch0[0],1); ch1[0] = _mm_mulhi_epi16(ch1[0],amp); ch1[0] = _mm_slli_epi16(ch1[0],1); // ch0[0] = _mm_srai_epi16(ch0[0],1); //divide by 2 // ch1[0] = _mm_srai_epi16(ch1[0],1); //divide by 2 //print_shorts("prec2A_TM4 ch0 (end):",ch0); //print_shorts("prec2A_TM4 ch1 (end):",ch1); _mm_empty(); _m_empty(); // print_shorts("prec2A_TM4 ch0 (end):",ch0); //print_shorts("prec2A_TM4 ch1 (end):",ch1); } void dlsch_channel_compensation_TM56(int **rxdataF_ext, int **dl_ch_estimates_ext, int **dl_ch_mag, int **dl_ch_magb, int **rxdataF_comp, unsigned char *pmi_ext, LTE_DL_FRAME_PARMS *frame_parms, PHY_MEASUREMENTS *measurements, int eNB_id, unsigned char symbol, unsigned char mod_order, unsigned short nb_rb, unsigned char output_shift, unsigned char dl_power_off) { #if defined(__x86_64__) || defined(__i386__) unsigned short rb,Nre; __m128i *dl_ch0_128,*dl_ch1_128,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128; unsigned char aarx=0,symbol_mod,pilots=0; int precoded_signal_strength=0; __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) pilots=1; //printf("comp prec: symbol %d, pilots %d\n",symbol, pilots); if (mod_order == 4) { QAM_amp128 = _mm_set1_epi16(QAM16_n1); QAM_amp128b = _mm_setzero_si128(); } else if (mod_order == 6) { QAM_amp128 = _mm_set1_epi16(QAM64_n1); QAM_amp128b = _mm_set1_epi16(QAM64_n2); } for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128 = (__m128i *)&dl_ch_mag[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128b = (__m128i *)&dl_ch_magb[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { // combine TX channels using precoder from pmi #ifdef DEBUG_DLSCH_DEMOD printf("mode 6 prec: rb %d, pmi->%d\n",rb,pmi_ext[rb]); #endif prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128[2],&dl_ch1_128[2]); } if (mod_order>2) { // get channel amplitude if not QPSK mmtmpD0 = _mm_madd_epi16(dl_ch0_128[0],dl_ch0_128[0]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_madd_epi16(dl_ch0_128[1],dl_ch0_128[1]); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); dl_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[0] = dl_ch_mag128[0]; dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1); //print_shorts("dl_ch_mag128[0]=",&dl_ch_mag128[0]); //print_shorts("dl_ch_mag128[0]=",&dl_ch_mag128[0]); dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[1] = dl_ch_mag128[1]; dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128); dl_ch_mag128[1] = _mm_slli_epi16(dl_ch_mag128[1],1); if (pilots==0) { mmtmpD0 = _mm_madd_epi16(dl_ch0_128[2],dl_ch0_128[2]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0); dl_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1); dl_ch_mag128b[2] = dl_ch_mag128[2]; dl_ch_mag128[2] = _mm_mulhi_epi16(dl_ch_mag128[2],QAM_amp128); dl_ch_mag128[2] = _mm_slli_epi16(dl_ch_mag128[2],1); } dl_ch_mag128b[0] = _mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b); dl_ch_mag128b[0] = _mm_slli_epi16(dl_ch_mag128b[0],1); //print_shorts("dl_ch_mag128b[0]=",&dl_ch_mag128b[0]); dl_ch_mag128b[1] = _mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b); dl_ch_mag128b[1] = _mm_slli_epi16(dl_ch_mag128b[1],1); if (pilots==0) { dl_ch_mag128b[2] = _mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b); dl_ch_mag128b[2] = _mm_slli_epi16(dl_ch_mag128b[2],1); } } // MF multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[0],rxdataF128[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch0_128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch128); // print_shorts("pack:",rxdataF_comp128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[1],rxdataF128[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch0_128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+1); // print_shorts("ch:",dl_ch128+1); // print_shorts("pack:",rxdataF_comp128+1); if (pilots==0) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[2],rxdataF128[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch0_128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+2); // print_shorts("ch:",dl_ch128+2); // print_shorts("pack:",rxdataF_comp128+2); dl_ch0_128+=3; dl_ch1_128+=3; dl_ch_mag128+=3; dl_ch_mag128b+=3; rxdataF128+=3; rxdataF_comp128+=3; } else { dl_ch0_128+=2; dl_ch1_128+=2; dl_ch_mag128+=2; dl_ch_mag128b+=2; rxdataF128+=2; rxdataF_comp128+=2; } } Nre = (pilots==0) ? 12 : 8; precoded_signal_strength += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], (nb_rb*Nre))) - (measurements->n0_power[aarx])); } // rx_antennas measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength,measurements->n0_power_tot); //printf("eNB_id %d, symbol %d: precoded CQI %d dB\n",eNB_id,symbol, // measurements->precoded_cqi_dB[eNB_id][0]); #elif defined(__arm__) uint32_t rb,Nre; uint32_t aarx,symbol_mod,pilots=0; int16x4_t *dl_ch0_128,*dl_ch1_128,*rxdataF128; int16x8_t *dl_ch0_128b,*dl_ch1_128b; int32x4_t mmtmpD0,mmtmpD1,mmtmpD0b,mmtmpD1b; int16x8_t *dl_ch_mag128,*dl_ch_mag128b,mmtmpD2,mmtmpD3,mmtmpD4,*rxdataF_comp128; int16x8_t QAM_amp128,QAM_amp128b; int16_t conj[4]__attribute__((aligned(16))) = {1,-1,1,-1}; int32x4_t output_shift128 = vmovq_n_s32(-(int32_t)output_shift); int32_t precoded_signal_strength=0; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { if (frame_parms->nb_antenna_ports_eNB==1) // 10 out of 12 so don't reduce size { nb_rb=1+(5*nb_rb/6); } else { pilots=1; } } if (mod_order == 4) { QAM_amp128 = vmovq_n_s16(QAM16_n1); // 2/sqrt(10) QAM_amp128b = vmovq_n_s16(0); } else if (mod_order == 6) { QAM_amp128 = vmovq_n_s16(QAM64_n1); // QAM_amp128b = vmovq_n_s16(QAM64_n2); } // printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol); for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch0_128 = (int16x4_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch1_128 = (int16x4_t*)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch0_128b = (int16x8_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch1_128b = (int16x8_t*)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128 = (int16x8_t*)&dl_ch_mag[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128b = (int16x8_t*)&dl_ch_magb[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (int16x4_t*)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (int16x8_t*)&rxdataF_comp[aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { #ifdef DEBUG_DLSCH_DEMOD printf("mode 6 prec: rb %d, pmi->%d\n",rb,pmi_ext[rb]); #endif prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[0],&dl_ch1_128b[0]); prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[1],&dl_ch1_128b[1]); if (pilots==0) { prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128b[2],&dl_ch1_128b[2]); } if (mod_order>2) { // get channel amplitude if not QPSK mmtmpD0 = vmull_s16(dl_ch0_128[0], dl_ch0_128[0]); // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits mmtmpD1 = vmull_s16(dl_ch0_128[1], dl_ch0_128[1]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits mmtmpD0 = vmull_s16(dl_ch0_128[2], dl_ch0_128[2]); mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); mmtmpD1 = vmull_s16(dl_ch0_128[3], dl_ch0_128[3]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); if (pilots==0) { mmtmpD0 = vmull_s16(dl_ch0_128[4], dl_ch0_128[4]); mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); mmtmpD1 = vmull_s16(dl_ch0_128[5], dl_ch0_128[5]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); } dl_ch_mag128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128b); dl_ch_mag128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128b); dl_ch_mag128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp128); dl_ch_mag128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp128); if (pilots==0) { dl_ch_mag128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128b); dl_ch_mag128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp128); } } mmtmpD0 = vmull_s16(dl_ch0_128[0], rxdataF128[0]); //mmtmpD0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] mmtmpD1 = vmull_s16(dl_ch0_128[1], rxdataF128[1]); //mmtmpD1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); //mmtmpD0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[0],*(int16x4_t*)conj)), rxdataF128[0]); //mmtmpD0 = [-Im(ch[0])Re(rx[0]) Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1]) Re(ch[1])Im(rx[1])] mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[1],*(int16x4_t*)conj)), rxdataF128[1]); //mmtmpD0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])] mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); //mmtmpD1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])] mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp128[0] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); mmtmpD0 = vmull_s16(dl_ch0_128[2], rxdataF128[2]); mmtmpD1 = vmull_s16(dl_ch0_128[3], rxdataF128[3]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[2],*(int16x4_t*)conj)), rxdataF128[2]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[3],*(int16x4_t*)conj)), rxdataF128[3]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp128[1] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); if (pilots==0) { mmtmpD0 = vmull_s16(dl_ch0_128[4], rxdataF128[4]); mmtmpD1 = vmull_s16(dl_ch0_128[5], rxdataF128[5]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[4],*(int16x4_t*)conj)), rxdataF128[4]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[5],*(int16x4_t*)conj)), rxdataF128[5]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp128[2] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); dl_ch0_128+=6; dl_ch1_128+=6; dl_ch_mag128+=3; dl_ch_mag128b+=3; rxdataF128+=6; rxdataF_comp128+=3; } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less dl_ch0_128+=4; dl_ch1_128+=4; dl_ch_mag128+=2; dl_ch_mag128b+=2; rxdataF128+=4; rxdataF_comp128+=2; } } Nre = (pilots==0) ? 12 : 8; precoded_signal_strength += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], (nb_rb*Nre))) - (measurements->n0_power[aarx])); // rx_antennas } measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength,measurements->n0_power_tot); //printf("eNB_id %d, symbol %d: precoded CQI %d dB\n",eNB_id,symbol, // measurements->precoded_cqi_dB[eNB_id][0]); #endif _mm_empty(); _m_empty(); } void precode_channel_est(int32_t **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, LTE_UE_PDSCH *pdsch_vars, unsigned char symbol, unsigned short nb_rb, MIMO_mode_t mimo_mode){ unsigned short rb; __m128i *dl_ch0_128,*dl_ch1_128; unsigned char aarx=0,symbol_mod,pilots=0; unsigned char *pmi_ext = pdsch_vars->pmi_ext; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) pilots=1; for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; // this is h11 dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; // this is h12 for (rb=0; rb<nb_rb; rb++) { if (mimo_mode==LARGE_CDD) { prec2A_TM3_128(&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM3_128(&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM3_128(&dl_ch0_128[2],&dl_ch1_128[2]); } }else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) { prec2A_TM4_128(0,&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM4_128(0,&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM4_128(0,&dl_ch0_128[2],&dl_ch1_128[2]); } }else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) { prec2A_TM4_128(1,&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM4_128(1,&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM4_128(1,&dl_ch0_128[2],&dl_ch1_128[2]); } }else if (mimo_mode==DUALSTREAM_PUSCH_PRECODING) { prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128[2],&dl_ch1_128[2]); } }else { LOG_E(PHY,"Unknown MIMO mode\n"); return; } if (pilots==0){ dl_ch0_128+=3; dl_ch1_128+=3; }else { dl_ch0_128+=2; dl_ch1_128+=2; } } } } void dlsch_channel_compensation_TM34(LTE_DL_FRAME_PARMS *frame_parms, LTE_UE_PDSCH *pdsch_vars, PHY_MEASUREMENTS *measurements, int eNB_id, unsigned char symbol, unsigned char mod_order0, unsigned char mod_order1, int harq_pid, int round, MIMO_mode_t mimo_mode, unsigned short nb_rb, unsigned short mmse_flag, unsigned char output_shift0, unsigned char output_shift1) { #if defined(__x86_64__) || defined(__i386__) unsigned short rb,Nre; __m128i *dl_ch0_128,*dl_ch1_128,*dl_ch_mag0_128,*dl_ch_mag1_128,*dl_ch_mag0_128b,*dl_ch_mag1_128b,*rxdataF128,*rxdataF_comp0_128,*rxdataF_comp1_128; unsigned char aarx=0,symbol_mod,pilots=0; int precoded_signal_strength0=0,precoded_signal_strength1=0; int rx_power_correction; int **rxdataF_ext = pdsch_vars->rxdataF_ext; int **dl_ch_estimates_ext = pdsch_vars->dl_ch_estimates_ext; int **dl_ch_mag0 = pdsch_vars->dl_ch_mag0; int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1[harq_pid][round]; int **dl_ch_magb0 = pdsch_vars->dl_ch_magb0; int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1[harq_pid][round]; int **rxdataF_comp0 = pdsch_vars->rxdataF_comp0; int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[harq_pid][round]; unsigned char *pmi_ext = pdsch_vars->pmi_ext; __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp0_128,QAM_amp0_128b,QAM_amp1_128,QAM_amp1_128b; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) pilots=1; rx_power_correction = 1; // printf("comp prec: symbol %d, pilots %d\n",symbol, pilots); if (mod_order0 == 4) { QAM_amp0_128 = _mm_set1_epi16(QAM16_n1); QAM_amp0_128b = _mm_setzero_si128(); } else if (mod_order0 == 6) { QAM_amp0_128 = _mm_set1_epi16(QAM64_n1); QAM_amp0_128b = _mm_set1_epi16(QAM64_n2); } if (mod_order1 == 4) { QAM_amp1_128 = _mm_set1_epi16(QAM16_n1); QAM_amp1_128b = _mm_setzero_si128(); } else if (mod_order1 == 6) { QAM_amp1_128 = _mm_set1_epi16(QAM64_n1); QAM_amp1_128b = _mm_set1_epi16(QAM64_n2); } for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; // this is h11 dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; // this is h12 dl_ch_mag0_128 = (__m128i *)&dl_ch_mag0[aarx][symbol*frame_parms->N_RB_DL*12]; //responsible for x1 dl_ch_mag0_128b = (__m128i *)&dl_ch_magb0[aarx][symbol*frame_parms->N_RB_DL*12];//responsible for x1 dl_ch_mag1_128 = (__m128i *)&dl_ch_mag1[aarx][symbol*frame_parms->N_RB_DL*12]; //responsible for x2. always coming from tx2 dl_ch_mag1_128b = (__m128i *)&dl_ch_magb1[aarx][symbol*frame_parms->N_RB_DL*12]; //responsible for x2. always coming from tx2 rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; //received signal on antenna of interest h11*x1+h12*x2 rxdataF_comp0_128 = (__m128i *)&rxdataF_comp0[aarx][symbol*frame_parms->N_RB_DL*12]; //result of multipl with MF x1 on antenna of interest rxdataF_comp1_128 = (__m128i *)&rxdataF_comp1[aarx][symbol*frame_parms->N_RB_DL*12]; //result of multipl with MF x2 on antenna of interest for (rb=0; rb<nb_rb; rb++) { if (mmse_flag == 0) { // combine TX channels using precoder from pmi if (mimo_mode==LARGE_CDD) { prec2A_TM3_128(&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM3_128(&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM3_128(&dl_ch0_128[2],&dl_ch1_128[2]); } }else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) { prec2A_TM4_128(0,&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM4_128(0,&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM4_128(0,&dl_ch0_128[2],&dl_ch1_128[2]); } }else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) { prec2A_TM4_128(1,&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM4_128(1,&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM4_128(1,&dl_ch0_128[2],&dl_ch1_128[2]); } }else if (mimo_mode==DUALSTREAM_PUSCH_PRECODING) { prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128[2],&dl_ch1_128[2]); } }else { LOG_E(PHY,"Unknown MIMO mode\n"); return; } } if (mod_order0>2) { // get channel amplitude if not QPSK mmtmpD0 = _mm_madd_epi16(dl_ch0_128[0],dl_ch0_128[0]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); mmtmpD1 = _mm_madd_epi16(dl_ch0_128[1],dl_ch0_128[1]); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift0); mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); dl_ch_mag0_128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0); dl_ch_mag0_128b[0] = dl_ch_mag0_128[0]; dl_ch_mag0_128[0] = _mm_mulhi_epi16(dl_ch_mag0_128[0],QAM_amp0_128); dl_ch_mag0_128[0] = _mm_slli_epi16(dl_ch_mag0_128[0],1); // print_shorts("dl_ch_mag0_128[0]=",&dl_ch_mag0_128[0]); dl_ch_mag0_128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag0_128b[1] = dl_ch_mag0_128[1]; dl_ch_mag0_128[1] = _mm_mulhi_epi16(dl_ch_mag0_128[1],QAM_amp0_128); dl_ch_mag0_128[1] = _mm_slli_epi16(dl_ch_mag0_128[1],1); if (pilots==0) { mmtmpD0 = _mm_madd_epi16(dl_ch0_128[2],dl_ch0_128[2]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0); dl_ch_mag0_128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1); dl_ch_mag0_128b[2] = dl_ch_mag0_128[2]; dl_ch_mag0_128[2] = _mm_mulhi_epi16(dl_ch_mag0_128[2],QAM_amp0_128); dl_ch_mag0_128[2] = _mm_slli_epi16(dl_ch_mag0_128[2],1); } dl_ch_mag0_128b[0] = _mm_mulhi_epi16(dl_ch_mag0_128b[0],QAM_amp0_128b); dl_ch_mag0_128b[0] = _mm_slli_epi16(dl_ch_mag0_128b[0],1); // print_shorts("dl_ch_mag0_128b[0]=",&dl_ch_mag0_128b[0]); dl_ch_mag0_128b[1] = _mm_mulhi_epi16(dl_ch_mag0_128b[1],QAM_amp0_128b); dl_ch_mag0_128b[1] = _mm_slli_epi16(dl_ch_mag0_128b[1],1); if (pilots==0) { dl_ch_mag0_128b[2] = _mm_mulhi_epi16(dl_ch_mag0_128b[2],QAM_amp0_128b); dl_ch_mag0_128b[2] = _mm_slli_epi16(dl_ch_mag0_128b[2],1); } } if (mod_order1>2) { // get channel amplitude if not QPSK mmtmpD0 = _mm_madd_epi16(dl_ch1_128[0],dl_ch1_128[0]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); mmtmpD1 = _mm_madd_epi16(dl_ch1_128[1],dl_ch1_128[1]); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift1); mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); dl_ch_mag1_128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0); dl_ch_mag1_128b[0] = dl_ch_mag1_128[0]; dl_ch_mag1_128[0] = _mm_mulhi_epi16(dl_ch_mag1_128[0],QAM_amp1_128); dl_ch_mag1_128[0] = _mm_slli_epi16(dl_ch_mag1_128[0],1); // print_shorts("dl_ch_mag1_128[0]=",&dl_ch_mag1_128[0]); dl_ch_mag1_128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag1_128b[1] = dl_ch_mag1_128[1]; dl_ch_mag1_128[1] = _mm_mulhi_epi16(dl_ch_mag1_128[1],QAM_amp1_128); dl_ch_mag1_128[1] = _mm_slli_epi16(dl_ch_mag1_128[1],1); if (pilots==0) { mmtmpD0 = _mm_madd_epi16(dl_ch1_128[2],dl_ch1_128[2]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0); dl_ch_mag1_128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1); dl_ch_mag1_128b[2] = dl_ch_mag1_128[2]; dl_ch_mag1_128[2] = _mm_mulhi_epi16(dl_ch_mag1_128[2],QAM_amp1_128); dl_ch_mag1_128[2] = _mm_slli_epi16(dl_ch_mag1_128[2],1); } dl_ch_mag1_128b[0] = _mm_mulhi_epi16(dl_ch_mag1_128b[0],QAM_amp1_128b); dl_ch_mag1_128b[0] = _mm_slli_epi16(dl_ch_mag1_128b[0],1); // print_shorts("dl_ch_mag1_128b[0]=",&dl_ch_mag1_128b[0]); dl_ch_mag1_128b[1] = _mm_mulhi_epi16(dl_ch_mag1_128b[1],QAM_amp1_128b); dl_ch_mag1_128b[1] = _mm_slli_epi16(dl_ch_mag1_128b[1],1); if (pilots==0) { dl_ch_mag1_128b[2] = _mm_mulhi_epi16(dl_ch_mag1_128b[2],QAM_amp1_128b); dl_ch_mag1_128b[2] = _mm_slli_epi16(dl_ch_mag1_128b[2],1); } } // layer 0 // MF multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[0],rxdataF128[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch0_128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); // print_ints("im",&mmtmpD1); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); // printf("Shift: %d\n",output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift0); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rxdataF_comp0_128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch0_128); //print_shorts("pack:",rxdataF_comp0_128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[1],rxdataF128[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch0_128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift0); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp0_128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+1); // print_shorts("ch:",dl_ch0_128+1); // print_shorts("pack:",rxdataF_comp0_128+1); if (pilots==0) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[2],rxdataF128[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch0_128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift0); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp0_128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+2); // print_shorts("ch:",dl_ch0_128+2); // print_shorts("pack:",rxdataF_comp0_128+2); } // layer 1 // MF multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch1_128[0],rxdataF128[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch1_128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift1); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rxdataF_comp1_128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch1_128); // print_shorts("pack:",rxdataF_comp1_128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch1_128[1],rxdataF128[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch1_128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp1_128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+1); // print_shorts("ch:",dl_ch1_128+1); // print_shorts("pack:",rxdataF_comp1_128+1); if (pilots==0) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch1_128[2],rxdataF128[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch1_128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift1); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp1_128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+2); // print_shorts("ch:",dl_ch1_128+2); // print_shorts("pack:",rxdataF_comp1_128+2); dl_ch0_128+=3; dl_ch1_128+=3; dl_ch_mag0_128+=3; dl_ch_mag1_128+=3; dl_ch_mag0_128b+=3; dl_ch_mag1_128b+=3; rxdataF128+=3; rxdataF_comp0_128+=3; rxdataF_comp1_128+=3; } else { dl_ch0_128+=2; dl_ch1_128+=2; dl_ch_mag0_128+=2; dl_ch_mag1_128+=2; dl_ch_mag0_128b+=2; dl_ch_mag1_128b+=2; rxdataF128+=2; rxdataF_comp0_128+=2; rxdataF_comp1_128+=2; } } // rb loop Nre = (pilots==0) ? 12 : 8; precoded_signal_strength0 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], (nb_rb*Nre))*rx_power_correction) - (measurements->n0_power[aarx])); precoded_signal_strength1 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx+2][symbol*frame_parms->N_RB_DL*Nre], (nb_rb*Nre))*rx_power_correction) - (measurements->n0_power[aarx])); } // rx_antennas measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength0,measurements->n0_power_tot); measurements->precoded_cqi_dB[eNB_id][1] = dB_fixed2(precoded_signal_strength1,measurements->n0_power_tot); // printf("eNB_id %d, symbol %d: precoded CQI %d dB\n",eNB_id,symbol, // measurements->precoded_cqi_dB[eNB_id][0]); _mm_empty(); _m_empty(); #elif defined(__arm__) unsigned short rb,Nre; unsigned char aarx,symbol_mod,pilots=0; int precoded_signal_strength0=0,precoded_signal_strength1=0, rx_power_correction; int16x4_t *dl_ch0_128,*rxdataF128; int16x4_t *dl_ch1_128; int16x8_t *dl_ch0_128b,*dl_ch1_128b; int32x4_t mmtmpD0,mmtmpD1,mmtmpD0b,mmtmpD1b; int16x8_t *dl_ch_mag0_128,*dl_ch_mag0_128b,*dl_ch_mag1_128,*dl_ch_mag1_128b,mmtmpD2,mmtmpD3,mmtmpD4,*rxdataF_comp0_128,*rxdataF_comp1_128; int16x8_t QAM_amp0_128,QAM_amp0_128b,QAM_amp1_128,QAM_amp1_128b; int32x4_t output_shift128 = vmovq_n_s32(-(int32_t)output_shift); int **rxdataF_ext = pdsch_vars->rxdataF_ext; int **dl_ch_estimates_ext = pdsch_vars->dl_ch_estimates_ext; int **dl_ch_mag0 = pdsch_vars->dl_ch_mag0; int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1[harq_pid][round]; int **dl_ch_magb0 = pdsch_vars->dl_ch_magb0; int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1[harq_pid][round]; int **rxdataF_comp0 = pdsch_vars->rxdataF_comp0; int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[harq_pid][round]; int16_t conj[4]__attribute__((aligned(16))) = {1,-1,1,-1}; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { if (frame_parms->nb_antenna_ports_eNB==1) // 10 out of 12 so don't reduce size { nb_rb=1+(5*nb_rb/6); } else { pilots=1; } } rx_power_correction=1; if (mod_order0 == 4) { QAM_amp0_128 = vmovq_n_s16(QAM16_n1); // 2/sqrt(10) QAM_amp0_128b = vmovq_n_s16(0); } else if (mod_order0 == 6) { QAM_amp0_128 = vmovq_n_s16(QAM64_n1); // QAM_amp0_128b = vmovq_n_s16(QAM64_n2); } if (mod_order1 == 4) { QAM_amp1_128 = vmovq_n_s16(QAM16_n1); // 2/sqrt(10) QAM_amp1_128b = vmovq_n_s16(0); } else if (mod_order1 == 6) { QAM_amp1_128 = vmovq_n_s16(QAM64_n1); // QAM_amp1_128b = vmovq_n_s16(QAM64_n2); } // printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol); for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch0_128 = (int16x4_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch1_128 = (int16x4_t*)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch0_128b = (int16x8_t*)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch1_128b = (int16x8_t*)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag0_128 = (int16x8_t*)&dl_ch_mag0[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag0_128b = (int16x8_t*)&dl_ch_magb0[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag1_128 = (int16x8_t*)&dl_ch_mag1[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag1_128b = (int16x8_t*)&dl_ch_magb1[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (int16x4_t*)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp0_128 = (int16x8_t*)&rxdataF_comp0[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp1_128 = (int16x8_t*)&rxdataF_comp1[aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { if (mmse_flag == 0) { // combine TX channels using precoder from pmi if (mimo_mode==LARGE_CDD) { prec2A_TM3_128(&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM3_128(&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM3_128(&dl_ch0_128[2],&dl_ch1_128[2]); } }else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) { prec2A_TM4_128(0,&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM4_128(0,&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM4_128(0,&dl_ch0_128[2],&dl_ch1_128[2]); } }else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) { prec2A_TM4_128(1,&dl_ch0_128[0],&dl_ch1_128[0]); prec2A_TM4_128(1,&dl_ch0_128[1],&dl_ch1_128[1]); if (pilots==0) { prec2A_TM4_128(1,&dl_ch0_128[2],&dl_ch1_128[2]); } }else { LOG_E(PHY,"Unknown MIMO mode\n"); return; } } if (mod_order0>2) { // get channel amplitude if not QPSK mmtmpD0 = vmull_s16(dl_ch0_128[0], dl_ch0_128[0]); // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits mmtmpD1 = vmull_s16(dl_ch0_128[1], dl_ch0_128[1]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits mmtmpD0 = vmull_s16(dl_ch0_128[2], dl_ch0_128[2]); mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); mmtmpD1 = vmull_s16(dl_ch0_128[3], dl_ch0_128[3]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); if (pilots==0) { mmtmpD0 = vmull_s16(dl_ch0_128[4], dl_ch0_128[4]); mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); mmtmpD1 = vmull_s16(dl_ch0_128[5], dl_ch0_128[5]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); } dl_ch_mag0_128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp0_128b); dl_ch_mag0_128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp0_128b); dl_ch_mag0_128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp0_128); dl_ch_mag0_128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp0_128); if (pilots==0) { dl_ch_mag0_128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp0_128b); dl_ch_mag0_128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp0_128); } } if (mod_order1>2) { // get channel amplitude if not QPSK mmtmpD0 = vmull_s16(dl_ch1_128[0], dl_ch1_128[0]); // mmtmpD0 = [ch0*ch0,ch1*ch1,ch2*ch2,ch3*ch3]; mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); // mmtmpD0 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3]>>output_shift128 on 32-bits mmtmpD1 = vmull_s16(dl_ch1_128[1], dl_ch1_128[1]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD2 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); // mmtmpD2 = [ch0*ch0 + ch1*ch1,ch0*ch0 + ch1*ch1,ch2*ch2 + ch3*ch3,ch2*ch2 + ch3*ch3,ch4*ch4 + ch5*ch5,ch4*ch4 + ch5*ch5,ch6*ch6 + ch7*ch7,ch6*ch6 + ch7*ch7]>>output_shift128 on 16-bits mmtmpD0 = vmull_s16(dl_ch1_128[2], dl_ch1_128[2]); mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); mmtmpD1 = vmull_s16(dl_ch1_128[3], dl_ch1_128[3]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD3 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); if (pilots==0) { mmtmpD0 = vmull_s16(dl_ch1_128[4], dl_ch1_128[4]); mmtmpD0 = vqshlq_s32(vqaddq_s32(mmtmpD0,vrev64q_s32(mmtmpD0)),output_shift128); mmtmpD1 = vmull_s16(dl_ch1_128[5], dl_ch1_128[5]); mmtmpD1 = vqshlq_s32(vqaddq_s32(mmtmpD1,vrev64q_s32(mmtmpD1)),output_shift128); mmtmpD4 = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); } dl_ch_mag1_128b[0] = vqdmulhq_s16(mmtmpD2,QAM_amp1_128b); dl_ch_mag1_128b[1] = vqdmulhq_s16(mmtmpD3,QAM_amp1_128b); dl_ch_mag1_128[0] = vqdmulhq_s16(mmtmpD2,QAM_amp1_128); dl_ch_mag1_128[1] = vqdmulhq_s16(mmtmpD3,QAM_amp1_128); if (pilots==0) { dl_ch_mag1_128b[2] = vqdmulhq_s16(mmtmpD4,QAM_amp1_128b); dl_ch_mag1_128[2] = vqdmulhq_s16(mmtmpD4,QAM_amp1_128); } } mmtmpD0 = vmull_s16(dl_ch0_128[0], rxdataF128[0]); //mmtmpD0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] mmtmpD1 = vmull_s16(dl_ch0_128[1], rxdataF128[1]); //mmtmpD1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); //mmtmpD0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[0],*(int16x4_t*)conj)), rxdataF128[0]); //mmtmpD0 = [-Im(ch[0])Re(rx[0]) Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1]) Re(ch[1])Im(rx[1])] mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[1],*(int16x4_t*)conj)), rxdataF128[1]); //mmtmpD0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])] mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); //mmtmpD1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])] mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp0_128[0] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); mmtmpD0 = vmull_s16(dl_ch0_128[2], rxdataF128[2]); mmtmpD1 = vmull_s16(dl_ch0_128[3], rxdataF128[3]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[2],*(int16x4_t*)conj)), rxdataF128[2]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[3],*(int16x4_t*)conj)), rxdataF128[3]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp0_128[1] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); // second stream mmtmpD0 = vmull_s16(dl_ch1_128[0], rxdataF128[0]); mmtmpD1 = vmull_s16(dl_ch1_128[1], rxdataF128[1]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[0],*(int16x4_t*)conj)), rxdataF128[0]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[1],*(int16x4_t*)conj)), rxdataF128[1]); //mmtmpD0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])] mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); //mmtmpD1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])] mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp1_128[0] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); mmtmpD0 = vmull_s16(dl_ch1_128[2], rxdataF128[2]); mmtmpD1 = vmull_s16(dl_ch1_128[3], rxdataF128[3]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[2],*(int16x4_t*)conj)), rxdataF128[2]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[3],*(int16x4_t*)conj)), rxdataF128[3]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp1_128[1] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); if (pilots==0) { mmtmpD0 = vmull_s16(dl_ch0_128[4], rxdataF128[4]); mmtmpD1 = vmull_s16(dl_ch0_128[5], rxdataF128[5]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[4],*(int16x4_t*)conj)), rxdataF128[4]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch0_128[5],*(int16x4_t*)conj)), rxdataF128[5]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp0_128[2] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); mmtmpD0 = vmull_s16(dl_ch1_128[4], rxdataF128[4]); mmtmpD1 = vmull_s16(dl_ch1_128[5], rxdataF128[5]); mmtmpD0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0),vget_high_s32(mmtmpD0)), vpadd_s32(vget_low_s32(mmtmpD1),vget_high_s32(mmtmpD1))); mmtmpD0b = vmull_s16(vrev32_s16(vmul_s16(dl_ch1_128[4],*(int16x4_t*)conj)), rxdataF128[4]); mmtmpD1b = vmull_s16(vrev32_s16(vmul_s16(dl_ch1_128[5],*(int16x4_t*)conj)), rxdataF128[5]); mmtmpD1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpD0b),vget_high_s32(mmtmpD0b)), vpadd_s32(vget_low_s32(mmtmpD1b),vget_high_s32(mmtmpD1b))); mmtmpD0 = vqshlq_s32(mmtmpD0,output_shift128); mmtmpD1 = vqshlq_s32(mmtmpD1,output_shift128); rxdataF_comp1_128[2] = vcombine_s16(vmovn_s32(mmtmpD0),vmovn_s32(mmtmpD1)); } } Nre = (pilots==0) ? 12 : 8; // rx_antennas } Nre = (pilots==0) ? 12 : 8; precoded_signal_strength0 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], (nb_rb*Nre))*rx_power_correction) - (measurements->n0_power[aarx])); precoded_signal_strength1 += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx+2][symbol*frame_parms->N_RB_DL*Nre], (nb_rb*Nre))*rx_power_correction) - (measurements->n0_power[aarx])); measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength0,measurements->n0_power_tot); measurements->precoded_cqi_dB[eNB_id][1] = dB_fixed2(precoded_signal_strength1,measurements->n0_power_tot); #endif } void dlsch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms, unsigned char symbol, unsigned short nb_rb, int **dl_ch_estimates_ext, int **dl_ch_estimates_ext_i, int **dl_ch_rho_ext, unsigned char output_shift) { #if defined(__x86_64__)||defined(__i386__) unsigned short rb; __m128i *dl_ch128,*dl_ch128i,*dl_ch_rho128,mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3; unsigned char aarx,symbol_mod,pilots=0; // printf("dlsch_dual_stream_correlation: symbol %d\n",symbol); symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { pilots=1; } // printf("Dual stream correlation (%p)\n",dl_ch_estimates_ext_i); for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; if (dl_ch_estimates_ext_i == NULL) // TM3/4 dl_ch128i = (__m128i *)&dl_ch_estimates_ext[aarx + frame_parms->nb_antennas_rx][symbol*frame_parms->N_RB_DL*12]; else dl_ch128i = (__m128i *)&dl_ch_estimates_ext_i[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_rho128 = (__m128i *)&dl_ch_rho_ext[aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128i[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128i[0]); // print_ints("im",&mmtmpD1); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); dl_ch_rho128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rho 0:",dl_ch_rho128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128i[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128i[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); dl_ch_rho128[1] =_mm_packs_epi32(mmtmpD2,mmtmpD3); if (pilots==0) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128i[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128i[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); dl_ch_rho128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); dl_ch128+=3; dl_ch128i+=3; dl_ch_rho128+=3; } else { dl_ch128+=2; dl_ch128i+=2; dl_ch_rho128+=2; } } } _mm_empty(); _m_empty(); #elif defined(__arm__) #endif } void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, int **rxdataF_comp, int **rxdataF_comp_i, int **rho, int **rho_i, int **dl_ch_mag, int **dl_ch_magb, int **dl_ch_mag_i, int **dl_ch_magb_i, unsigned char symbol, unsigned short nb_rb, unsigned char dual_stream_UE) { #if defined(__x86_64__)||defined(__i386__) unsigned char aatx; int i; __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1, *dl_ch_mag128_i0,*dl_ch_mag128_i1,*dl_ch_mag128_i0b,*dl_ch_mag128_i1b; if (frame_parms->nb_antennas_rx>1) { for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_0 = (__m128i *)&dl_ch_mag[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_1 = (__m128i *)&dl_ch_mag[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_0b = (__m128i *)&dl_ch_magb[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_1b = (__m128i *)&dl_ch_magb[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) for (i=0;i<nb_rb*3;i++) { rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); dl_ch_mag128_0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0[i],1),_mm_srai_epi16(dl_ch_mag128_1[i],1)); dl_ch_mag128_0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0b[i],1),_mm_srai_epi16(dl_ch_mag128_1b[i],1)); // print_shorts("mrc comp0:",&rxdataF_comp128_0[i]); // print_shorts("mrc mag0:",&dl_ch_mag128_0[i]); // print_shorts("mrc mag0b:",&dl_ch_mag128_0b[i]); // print_shorts("mrc rho1:",&rho128_1[i]); } } if (rho) { rho128_0 = (__m128i *) &rho[0][symbol*frame_parms->N_RB_DL*12]; rho128_1 = (__m128i *) &rho[1][symbol*frame_parms->N_RB_DL*12]; for (i=0;i<nb_rb*3;i++) { // print_shorts("mrc rho0:",&rho128_0[i]); // print_shorts("mrc rho1:",&rho128_1[i]); rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1)); } } if (dual_stream_UE == 1) { rho128_i0 = (__m128i *) &rho_i[0][symbol*frame_parms->N_RB_DL*12]; rho128_i1 = (__m128i *) &rho_i[1][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i0 = (__m128i *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i1 = (__m128i *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i0 = (__m128i *)&dl_ch_mag_i[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i1 = (__m128i *)&dl_ch_mag_i[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i0b = (__m128i *)&dl_ch_magb_i[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i1b = (__m128i *)&dl_ch_magb_i[1][symbol*frame_parms->N_RB_DL*12]; for (i=0; i<nb_rb*3; i++) { rxdataF_comp128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_i0[i],1),_mm_srai_epi16(rxdataF_comp128_i1[i],1)); rho128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i1[i],1)); dl_ch_mag128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0[i],1),_mm_srai_epi16(dl_ch_mag128_i1[i],1)); dl_ch_mag128_i0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0b[i],1),_mm_srai_epi16(dl_ch_mag128_i1b[i],1)); } } } _mm_empty(); _m_empty(); #elif defined(__arm__) unsigned char aatx; int i; int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1,*dl_ch_mag128_i0,*dl_ch_mag128_i1,*dl_ch_mag128_i0b,*dl_ch_mag128_i1b; if (frame_parms->nb_antennas_rx>1) { for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_0 = (int16x8_t *)&dl_ch_mag[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_1 = (int16x8_t *)&dl_ch_mag[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_0b = (int16x8_t *)&dl_ch_magb[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_1b = (int16x8_t *)&dl_ch_magb[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) for (i=0; i<nb_rb*3; i++) { rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]); dl_ch_mag128_0[i] = vhaddq_s16(dl_ch_mag128_0[i],dl_ch_mag128_1[i]); dl_ch_mag128_0b[i] = vhaddq_s16(dl_ch_mag128_0b[i],dl_ch_mag128_1b[i]); } } if (rho) { rho128_0 = (int16x8_t *) &rho[0][symbol*frame_parms->N_RB_DL*12]; rho128_1 = (int16x8_t *) &rho[1][symbol*frame_parms->N_RB_DL*12]; for (i=0; i<nb_rb*3; i++) { // print_shorts("mrc rho0:",&rho128_0[i]); // print_shorts("mrc rho1:",&rho128_1[i]); rho128_0[i] = vhaddq_s16(rho128_0[i],rho128_1[i]); } } if (dual_stream_UE == 1) { rho128_i0 = (int16x8_t *) &rho_i[0][symbol*frame_parms->N_RB_DL*12]; rho128_i1 = (int16x8_t *) &rho_i[1][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i0 = (int16x8_t *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i1 = (int16x8_t *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i0 = (int16x8_t *)&dl_ch_mag_i[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i1 = (int16x8_t *)&dl_ch_mag_i[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i0b = (int16x8_t *)&dl_ch_magb_i[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i1b = (int16x8_t *)&dl_ch_magb_i[1][symbol*frame_parms->N_RB_DL*12]; for (i=0; i<nb_rb*3; i++) { rxdataF_comp128_i0[i] = vhaddq_s16(rxdataF_comp128_i0[i],rxdataF_comp128_i1[i]); rho128_i0[i] = vhaddq_s16(rho128_i0[i],rho128_i1[i]); dl_ch_mag128_i0[i] = vhaddq_s16(dl_ch_mag128_i0[i],dl_ch_mag128_i1[i]); dl_ch_mag128_i0b[i] = vhaddq_s16(dl_ch_mag128_i0b[i],dl_ch_mag128_i1b[i]); } } } #endif } void dlsch_detection_mrc_TM34(LTE_DL_FRAME_PARMS *frame_parms, LTE_UE_PDSCH *pdsch_vars, int harq_pid, int round, unsigned char symbol, unsigned short nb_rb, unsigned char dual_stream_UE) { int i; __m128i *rxdataF_comp128_0,*rxdataF_comp128_1; __m128i *dl_ch_mag128_0,*dl_ch_mag128_1; __m128i *dl_ch_mag128_0b,*dl_ch_mag128_1b; __m128i *rho128_0, *rho128_1; int **rxdataF_comp0 = pdsch_vars->rxdataF_comp0; int **rxdataF_comp1 = pdsch_vars->rxdataF_comp1[harq_pid][round]; int **dl_ch_rho_ext = pdsch_vars->dl_ch_rho_ext[harq_pid][round]; //for second stream int **dl_ch_rho2_ext = pdsch_vars->dl_ch_rho2_ext; int **dl_ch_mag0 = pdsch_vars->dl_ch_mag0; int **dl_ch_mag1 = pdsch_vars->dl_ch_mag1[harq_pid][round]; int **dl_ch_magb0 = pdsch_vars->dl_ch_magb0; int **dl_ch_magb1 = pdsch_vars->dl_ch_magb1[harq_pid][round]; rxdataF_comp128_0 = (__m128i *)&rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (__m128i *)&rxdataF_comp0[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_0 = (__m128i *)&dl_ch_mag0[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_1 = (__m128i *)&dl_ch_mag0[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_0b = (__m128i *)&dl_ch_magb0[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_1b = (__m128i *)&dl_ch_magb0[1][symbol*frame_parms->N_RB_DL*12]; rho128_0 = (__m128i *) &dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12]; rho128_1 = (__m128i *) &dl_ch_rho2_ext[1][symbol*frame_parms->N_RB_DL*12]; // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) for (i=0;i<nb_rb*3;i++) { rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); dl_ch_mag128_0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0[i],1),_mm_srai_epi16(dl_ch_mag128_1[i],1)); dl_ch_mag128_0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0b[i],1),_mm_srai_epi16(dl_ch_mag128_1b[i],1)); rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1)); if (frame_parms->nb_antennas_rx>2) { __m128i *rxdataF_comp128_2 = NULL; __m128i *rxdataF_comp128_3 = NULL; __m128i *dl_ch_mag128_2 = NULL; __m128i *dl_ch_mag128_3 = NULL; __m128i *dl_ch_mag128_2b = NULL; __m128i *dl_ch_mag128_3b = NULL; __m128i *rho128_2 = NULL; __m128i *rho128_3 = NULL; rxdataF_comp128_2 = (__m128i *)&rxdataF_comp0[2][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_3 = (__m128i *)&rxdataF_comp0[3][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_2 = (__m128i *)&dl_ch_mag0[2][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_3 = (__m128i *)&dl_ch_mag0[3][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_2b = (__m128i *)&dl_ch_magb0[2][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_3b = (__m128i *)&dl_ch_magb0[3][symbol*frame_parms->N_RB_DL*12]; rho128_2 = (__m128i *) &dl_ch_rho2_ext[2][symbol*frame_parms->N_RB_DL*12]; rho128_3 = (__m128i *) &dl_ch_rho2_ext[3][symbol*frame_parms->N_RB_DL*12]; /*rxdataF_comp*/ rxdataF_comp128_2[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_2[i],1),_mm_srai_epi16(rxdataF_comp128_3[i],1)); rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_2[i],1)); /*dl_ch_mag*/ dl_ch_mag128_2[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_2[i],1),_mm_srai_epi16(dl_ch_mag128_3[i],1)); dl_ch_mag128_0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0[i],1),_mm_srai_epi16(dl_ch_mag128_2[i],1)); /*dl_ch_mag*/ dl_ch_mag128_2b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_2b[i],1),_mm_srai_epi16(dl_ch_mag128_3b[i],1)); dl_ch_mag128_0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0b[i],1),_mm_srai_epi16(dl_ch_mag128_2b[i],1)); /*rho*/ rho128_2[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_2[i],1),_mm_srai_epi16(rho128_3[i],1)); rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_2[i],1)); } } if (dual_stream_UE == 1) { __m128i *dl_ch_mag128_i0, *dl_ch_mag128_i1; __m128i *dl_ch_mag128_i0b, *dl_ch_mag128_i1b; __m128i *rho128_i0, *rho128_i1; __m128i *rxdataF_comp128_i0, *rxdataF_comp128_i1; rxdataF_comp128_i0 = (__m128i *)&rxdataF_comp1[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i1 = (__m128i *)&rxdataF_comp1[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i0 = (__m128i *)&dl_ch_mag1[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i1 = (__m128i *)&dl_ch_mag1[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i0b = (__m128i *)&dl_ch_magb1[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i1b = (__m128i *)&dl_ch_magb1[1][symbol*frame_parms->N_RB_DL*12]; rho128_i0 = (__m128i *) &dl_ch_rho_ext[0][symbol*frame_parms->N_RB_DL*12]; rho128_i1 = (__m128i *) &dl_ch_rho_ext[1][symbol*frame_parms->N_RB_DL*12]; for (i=0;i<nb_rb*3;i++) { rxdataF_comp128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_i0[i],1),_mm_srai_epi16(rxdataF_comp128_i1[i],1)); dl_ch_mag128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0[i],1),_mm_srai_epi16(dl_ch_mag128_i1[i],1)); dl_ch_mag128_i0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0b[i],1),_mm_srai_epi16(dl_ch_mag128_i1b[i],1)); rho128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i1[i],1)); if (frame_parms->nb_antennas_rx>2) { __m128i *rxdataF_comp128_i2 = NULL; __m128i *rxdataF_comp128_i3 = NULL; __m128i *dl_ch_mag128_i2 = NULL; __m128i *dl_ch_mag128_i3 = NULL; __m128i *dl_ch_mag128_i2b = NULL; __m128i *dl_ch_mag128_i3b = NULL; __m128i *rho128_i2 = NULL; __m128i *rho128_i3 = NULL; rxdataF_comp128_i2 = (__m128i *)&rxdataF_comp1[2][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i3 = (__m128i *)&rxdataF_comp1[3][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i2 = (__m128i *)&dl_ch_mag1[2][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i3 = (__m128i *)&dl_ch_mag1[3][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i2b = (__m128i *)&dl_ch_magb1[2][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i3b = (__m128i *)&dl_ch_magb1[3][symbol*frame_parms->N_RB_DL*12]; rho128_i2 = (__m128i *) &dl_ch_rho_ext[2][symbol*frame_parms->N_RB_DL*12]; rho128_i3 = (__m128i *) &dl_ch_rho_ext[3][symbol*frame_parms->N_RB_DL*12]; /*rxdataF_comp*/ rxdataF_comp128_i2[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_i2[i],1),_mm_srai_epi16(rxdataF_comp128_i3[i],1)); rxdataF_comp128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_i0[i],1),_mm_srai_epi16(rxdataF_comp128_i2[i],1)); /*dl_ch_mag*/ dl_ch_mag128_i2[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i2[i],1),_mm_srai_epi16(dl_ch_mag128_i3[i],1)); dl_ch_mag128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0[i],1),_mm_srai_epi16(dl_ch_mag128_i2[i],1)); /*dl_ch_mag*/ dl_ch_mag128_i2b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i2b[i],1),_mm_srai_epi16(dl_ch_mag128_i3b[i],1)); dl_ch_mag128_i0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0b[i],1),_mm_srai_epi16(dl_ch_mag128_i2b[i],1)); /*rho*/ rho128_i2[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i2[i],1),_mm_srai_epi16(rho128_i3[i],1)); rho128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i2[i],1)); } } } _mm_empty(); _m_empty(); } void dlsch_scale_channel(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, LTE_UE_DLSCH_t **dlsch_ue, uint8_t symbol, unsigned short nb_rb) { #if defined(__x86_64__)||defined(__i386__) short rb, ch_amp; unsigned char aatx,aarx,pilots=0,symbol_mod; __m128i *dl_ch128, ch_amp128; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { if (frame_parms->nb_antenna_ports_eNB==1) // 10 out of 12 so don't reduce size nb_rb=1+(5*nb_rb/6); else pilots=1; } // Determine scaling amplitude based the symbol ch_amp = ((pilots) ? (dlsch_ue[0]->sqrt_rho_b) : (dlsch_ue[0]->sqrt_rho_a)); LOG_D(PHY,"Scaling PDSCH Chest in OFDM symbol %d by %d, pilots %d nb_rb %d NCP %d symbol %d\n",symbol_mod,ch_amp,pilots,nb_rb,frame_parms->Ncp,symbol); // printf("Scaling PDSCH Chest in OFDM symbol %d by %d\n",symbol_mod,ch_amp); ch_amp128 = _mm_set1_epi16(ch_amp); // Q3.13 for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) { for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { dl_ch128[0] = _mm_mulhi_epi16(dl_ch128[0],ch_amp128); dl_ch128[0] = _mm_slli_epi16(dl_ch128[0],3); dl_ch128[1] = _mm_mulhi_epi16(dl_ch128[1],ch_amp128); dl_ch128[1] = _mm_slli_epi16(dl_ch128[1],3); if (pilots) { dl_ch128+=2; } else { dl_ch128[2] = _mm_mulhi_epi16(dl_ch128[2],ch_amp128); dl_ch128[2] = _mm_slli_epi16(dl_ch128[2],3); dl_ch128+=3; } } } } #elif defined(__arm__) #endif } //compute average channel_level on each (TX,RX) antenna pair void dlsch_channel_level(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, int32_t *avg, uint8_t symbol, unsigned short nb_rb) { #if defined(__x86_64__)||defined(__i386__) //printf("symbol = %d\n", symbol); short rb; unsigned char aatx,aarx,nre=12,symbol_mod; __m128i *dl_ch128, avg128D; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) nre=8; else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB==1)) nre=10; else nre=12; //nb_rb*nre = y * 2^x int16_t x = factor2(nb_rb*nre); int16_t y = (nb_rb*nre)>>x; for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { //clear average level //printf("aatx = %d, aarx = %d, aatx*frame_parms->nb_antennas_rx + aarx] = %d \n", aatx, aarx, aatx*frame_parms->nb_antennas_rx + aarx); avg128D = _mm_setzero_si128(); // 5 is always a symbol with no pilots for both normal and extended prefix dl_ch128=(__m128i *)&dl_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { //printf("rb %d : ",rb); avg128D = _mm_add_epi32(avg128D,_mm_srai_epi32(_mm_madd_epi16(dl_ch128[0],dl_ch128[0]),x)); avg128D = _mm_add_epi32(avg128D,_mm_srai_epi32(_mm_madd_epi16(dl_ch128[1],dl_ch128[1]),x)); //avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[0],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[0], coeff128),15))); //avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[1],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[1], coeff128),15))); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) { dl_ch128+=2; } else { avg128D = _mm_add_epi32(avg128D,_mm_srai_epi32(_mm_madd_epi16(dl_ch128[2],dl_ch128[2]),x)); //avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[2],_mm_srai_epi16(_mm_mulhi_epi16(dl_ch128[2], coeff128),15))); dl_ch128+=3; } /*if(rb==0){ print_shorts("dl_ch128",&dl_ch128[0]); print_shorts("dl_ch128",&dl_ch128[1]); print_shorts("dl_ch128",&dl_ch128[2]); }*/ } avg[aatx*frame_parms->nb_antennas_rx + aarx] =(((int32_t*)&avg128D)[0] + ((int32_t*)&avg128D)[1] + ((int32_t*)&avg128D)[2] + ((int32_t*)&avg128D)[3])/y; } _mm_empty(); _m_empty(); #elif defined(__arm__) short rb; unsigned char aatx,aarx,nre=12,symbol_mod; int32x4_t avg128D; int16x4_t *dl_ch128; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { //clear average level avg128D = vdupq_n_s32(0); // 5 is always a symbol with no pilots for both normal and extended prefix dl_ch128=(int16x4_t *)&dl_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { // printf("rb %d : ",rb); // print_shorts("ch",&dl_ch128[0]); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[0],dl_ch128[0])); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[1],dl_ch128[1])); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[2],dl_ch128[2])); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[3],dl_ch128[3])); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) { dl_ch128+=4; } else { avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[4],dl_ch128[4])); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[5],dl_ch128[5])); dl_ch128+=6; } /* if (rb==0) { print_shorts("dl_ch128",&dl_ch128[0]); print_shorts("dl_ch128",&dl_ch128[1]); print_shorts("dl_ch128",&dl_ch128[2]); } */ } if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) nre=8; else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==1)) nre=10; else nre=12; avg[aatx*frame_parms->nb_antennas_rx + aarx] = (((int32_t*)&avg128D)[0] + ((int32_t*)&avg128D)[1] + ((int32_t*)&avg128D)[2] + ((int32_t*)&avg128D)[3])/(nb_rb*nre); //printf("Channel level : %d\n",avg[aatx*(frame_parms->nb_antennas_rx-1) + aarx]); } #endif } void dlsch_channel_level_core(int **dl_ch_estimates_ext, int32_t *avg, int n_tx, int n_rx, int length, int start_point) { #if defined(__x86_64__)||defined(__i386__) short ii; int aatx,aarx; int length_mod8; int length2; __m128i *dl_ch128, avg128D; int16_t x = factor2(length); int16_t y = (length)>>x; for (aatx=0; aatx<n_tx; aatx++) for (aarx=0; aarx<n_rx; aarx++) { avg128D = _mm_setzero_si128(); dl_ch128=(__m128i *)&dl_ch_estimates_ext[aatx*n_rx + aarx][start_point]; length_mod8=length&7; if (length_mod8 == 0){ length2 = length>>3; for (ii=0;ii<length2;ii++) { avg128D = _mm_add_epi32(avg128D,_mm_srai_epi32(_mm_madd_epi16(dl_ch128[0],dl_ch128[0]),x)); avg128D = _mm_add_epi32(avg128D,_mm_srai_epi32(_mm_madd_epi16(dl_ch128[1],dl_ch128[1]),x)); dl_ch128+=2; } }else { printf ("Channel level: Received number of subcarriers is not multiple of 4, \n" "need to adapt the code!\n"); } avg[aatx*n_rx + aarx] =(((int32_t*)&avg128D)[0] + ((int32_t*)&avg128D)[1] + ((int32_t*)&avg128D)[2] + ((int32_t*)&avg128D)[3])/y; //printf("Channel level [%d]: %d\n",aatx*n_rx + aarx, avg[aatx*n_rx + aarx]); } _mm_empty(); _m_empty(); /* FIXME This part needs to be adapted like the one above */ #elif defined(__arm__) short rb; unsigned char aatx,aarx,nre=12,symbol_mod; int32x4_t avg128D; int16x4_t *dl_ch128; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { //clear average level avg128D = vdupq_n_s32(0); // 5 is always a symbol with no pilots for both normal and extended prefix dl_ch128=(int16x4_t *)&dl_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { // printf("rb %d : ",rb); // print_shorts("ch",&dl_ch128[0]); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[0],dl_ch128[0])); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[1],dl_ch128[1])); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[2],dl_ch128[2])); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[3],dl_ch128[3])); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) { dl_ch128+=4; } else { avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[4],dl_ch128[4])); avg128D = vqaddq_s32(avg128D,vmull_s16(dl_ch128[5],dl_ch128[5])); dl_ch128+=6; } } if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) nre=8; else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB==1)) nre=10; else nre=12; avg[aatx*frame_parms->nb_antennas_rx + aarx] = (((int32_t*)&avg128D)[0] + ((int32_t*)&avg128D)[1] + ((int32_t*)&avg128D)[2] + ((int32_t*)&avg128D)[3])/(nb_rb*nre); //printf("Channel level : %d\n",avg[aatx*(frame_parms->nb_antennas_rx-1) + aarx]); } #endif } void mmse_processing_oai(LTE_UE_PDSCH *pdsch_vars, LTE_DL_FRAME_PARMS *frame_parms, PHY_MEASUREMENTS *measurements, unsigned char first_symbol_flag, MIMO_mode_t mimo_mode, unsigned short mmse_flag, int noise_power, unsigned char symbol, unsigned short nb_rb){ int **rxdataF_ext = pdsch_vars->rxdataF_ext; int **dl_ch_estimates_ext = pdsch_vars->dl_ch_estimates_ext; unsigned char *pmi_ext = pdsch_vars->pmi_ext; int avg_00[frame_parms->nb_antenna_ports_eNB*frame_parms->nb_antennas_rx]; int avg_01[frame_parms->nb_antenna_ports_eNB*frame_parms->nb_antennas_rx]; int symbol_mod, length, start_point, nre; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) nre=8; else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB==1)) nre=10; else nre=12; length = nre*nb_rb; start_point = symbol*nb_rb*12; mmse_processing_core(rxdataF_ext, dl_ch_estimates_ext, noise_power, frame_parms->nb_antenna_ports_eNB, frame_parms->nb_antennas_rx, length, start_point); /*dlsch_channel_aver_band(dl_ch_estimates_ext, frame_parms, chan_avg, symbol, nb_rb); for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { H[aatx*frame_parms->nb_antennas_rx + aarx] = (float)(chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].r/(32768.0)) + I*(float)(chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i/(32768.0)); // printf("H [%d] = (%f, %f) \n", aatx*frame_parms->nb_antennas_rx + aarx, creal(H[aatx*frame_parms->nb_antennas_rx + aarx]), cimag(H[aatx*frame_parms->nb_antennas_rx + aarx])); }*/ if (first_symbol_flag == 1){ dlsch_channel_level_TM34(dl_ch_estimates_ext, frame_parms, pmi_ext, avg_00, avg_01, symbol, nb_rb, mmse_flag, mimo_mode); avg_00[0] = (log2_approx(avg_00[0])/2) + dlsch_demod_shift+4;// + 2 ;//+ 4; avg_01[0] = (log2_approx(avg_01[0])/2) + dlsch_demod_shift+4;// + 2 ;//+ 4; pdsch_vars->log2_maxh0 = cmax(avg_00[0],0); pdsch_vars->log2_maxh1 = cmax(avg_01[0],0); } } void mmse_processing_core(int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, int noise_power, int n_tx, int n_rx, int length, int start_point){ int aatx, aarx, re; float imag; float real; float complex **W_MMSE= malloc(n_tx*n_rx*sizeof(float complex*)); for (int j=0; j<n_tx*n_rx; j++) { W_MMSE[j] = malloc(sizeof(float complex)*length); } float complex *H= malloc(n_tx*n_rx*sizeof(float complex)); float complex *W_MMSE_re= malloc(n_tx*n_rx*sizeof(float complex)); float complex** dl_ch_estimates_ext_flcpx = malloc(n_tx*n_rx*sizeof(float complex*)); for (int j=0; j<n_tx*n_rx; j++) { dl_ch_estimates_ext_flcpx[j] = malloc(sizeof(float complex)*length); } float complex** rxdataF_ext_flcpx = malloc(n_rx*sizeof(float complex*)); for (int j=0; j<n_rx; j++) { rxdataF_ext_flcpx[j] = malloc(sizeof(float complex)*length); } chan_est_to_float(dl_ch_estimates_ext, dl_ch_estimates_ext_flcpx, n_tx, n_rx, length, start_point); for (re=0; re<length; re++){ for (aatx=0; aatx<n_tx; aatx++){ for (aarx=0; aarx<n_rx; aarx++) { imag = cimag(dl_ch_estimates_ext_flcpx[aatx*n_rx + aarx][re]); real = creal(dl_ch_estimates_ext_flcpx[aatx*n_rx + aarx][re]); H[aatx*n_rx + aarx] = real+ I*imag; } } compute_MMSE(H, n_tx, noise_power, W_MMSE_re); for (aatx=0; aatx<n_tx; aatx++){ for (aarx=0; aarx<n_rx; aarx++) { W_MMSE[aatx*n_rx + aarx][re] = W_MMSE_re[aatx*n_rx + aarx]; } } } rxdataF_to_float(rxdataF_ext, rxdataF_ext_flcpx, n_rx, length, start_point); mult_mmse_rxdataF(W_MMSE, rxdataF_ext_flcpx, n_tx, n_rx, length, start_point); mult_mmse_chan_est(W_MMSE, dl_ch_estimates_ext_flcpx, n_tx, n_rx, length, start_point); float_to_rxdataF(rxdataF_ext, rxdataF_ext_flcpx, n_tx, n_rx, length, start_point); float_to_chan_est(dl_ch_estimates_ext, dl_ch_estimates_ext_flcpx, n_tx, n_rx, length, start_point); free(W_MMSE); free(H); free(W_MMSE_re); free(dl_ch_estimates_ext_flcpx); free(rxdataF_ext_flcpx); } /*THIS FUNCTION TAKES FLOAT_POINT INPUT. SHOULD NOT BE USED WITH OAI*/ void mmse_processing_core_flp(float complex** rxdataF_ext_flcpx, float complex **H, int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, float noise_power, int n_tx, int n_rx, int length, int start_point){ int aatx, aarx, re; float max = 0; float one_over_max = 0; float complex **W_MMSE= malloc(n_tx*n_rx*sizeof(float complex*)); for (int j=0; j<n_tx*n_rx; j++) { W_MMSE[j] = malloc(sizeof(float complex)*length); } float complex *H_re= malloc(n_tx*n_rx*sizeof(float complex)); float complex *W_MMSE_re= malloc(n_tx*n_rx*sizeof(float complex)); for (re=0; re<length; re++){ for (aatx=0; aatx<n_tx; aatx++){ for (aarx=0; aarx<n_rx; aarx++) { H_re[aatx*n_rx + aarx] = H[aatx*n_rx + aarx][re]; #ifdef DEBUG_MMSE if (re == 0) printf(" H_re[%d]= (%f + i%f)\n", aatx*n_rx + aarx, creal(H_re[aatx*n_rx + aarx]), cimag(H_re[aatx*n_rx + aarx])); #endif } } compute_MMSE(H_re, n_tx, noise_power, W_MMSE_re); for (aatx=0; aatx<n_tx; aatx++){ for (aarx=0; aarx<n_rx; aarx++) { W_MMSE[aatx*n_rx + aarx][re] = W_MMSE_re[aatx*n_rx + aarx]; if (fabs(creal(W_MMSE_re[aatx*n_rx + aarx])) > max) max = fabs(creal(W_MMSE_re[aatx*n_rx + aarx])); if (fabs(cimag(W_MMSE_re[aatx*n_rx + aarx])) > max) max = fabs(cimag(W_MMSE_re[aatx*n_rx + aarx])); } } } one_over_max = 1.0/max; for (re=0; re<length; re++) for (aatx=0; aatx<n_tx; aatx++) for (aarx=0; aarx<n_rx; aarx++){ #ifdef DEBUG_MMSE if (re == 0) printf(" W_MMSE[%d] = (%f + i%f)\n", aatx*n_rx + aarx, creal(W_MMSE[aatx*n_rx + aarx][re]), cimag(W_MMSE[aatx*n_rx + aarx][re])); #endif W_MMSE[aatx*n_rx + aarx][re] = one_over_max*W_MMSE[aatx*n_rx + aarx][re]; #ifdef DEBUG_MMSE if (re == 0) printf(" AFTER NORM W_MMSE[%d] = (%f + i%f), max = %f \n", aatx*n_rx + aarx, creal(W_MMSE[aatx*n_rx + aarx][re]), cimag(W_MMSE[aatx*n_rx + aarx][re]), max); #endif } mult_mmse_rxdataF(W_MMSE, rxdataF_ext_flcpx, n_tx, n_rx, length, start_point); mult_mmse_chan_est(W_MMSE, H, n_tx, n_rx, length, start_point); float_to_rxdataF(rxdataF_ext, rxdataF_ext_flcpx, n_tx, n_rx, length, start_point); float_to_chan_est(dl_ch_estimates_ext, H, n_tx, n_rx, length, start_point); free(H_re); free(W_MMSE); free(W_MMSE_re); } void dlsch_channel_aver_band(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, struct complex32 *chan_avg, unsigned char symbol, unsigned short nb_rb) { #if defined(__x86_64__)||defined(__i386__) short rb; unsigned char aatx,aarx,nre=12,symbol_mod; __m128i *dl_ch128, avg128D; int32_t chan_est_avg[4]; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) nre=8; else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB==1)) nre=10; else nre=12; for (aatx=0; aatx<frame_parms->nb_antennas_tx; aatx++){ for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch128=(__m128i *)&dl_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; avg128D = _mm_setzero_si128(); // print_shorts("avg128D 1",&avg128D); for (rb=0;rb<nb_rb;rb++) { /* printf("symbol %d, ant %d, nre*nrb %d, rb %d \n", symbol, aatx*frame_parms->nb_antennas_rx + aarx, nb_rb*nre, rb); print_shorts("aver dl_ch128",&dl_ch128[0]); print_shorts("aver dl_ch128",&dl_ch128[1]); print_shorts("aver dl_ch128",&dl_ch128[2]); avg128D = _mm_add_epi16(avg128D, dl_ch128[0]);*/ //print_shorts("avg128D 2",&avg128D); avg128D = _mm_add_epi16(avg128D, dl_ch128[1]); // print_shorts("avg128D 3",&avg128D); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) { dl_ch128+=2; }else { avg128D = _mm_add_epi16(avg128D,dl_ch128[2]); // print_shorts("avg128D 4",&avg128D); dl_ch128+=3; } } chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].r =(((int16_t*)&avg128D)[0] + ((int16_t*)&avg128D)[2] + ((int16_t*)&avg128D)[4] + ((int16_t*)&avg128D)[6])/(nb_rb*nre); // printf("symb %d chan_avg re [%d] = %d\n", symbol, aatx*frame_parms->nb_antennas_rx + aarx, chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].r); chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i =(((int16_t*)&avg128D)[1] + ((int16_t*)&avg128D)[3] + ((int16_t*)&avg128D)[5] + ((int16_t*)&avg128D)[7])/(nb_rb*nre); // printf("symb %d chan_avg im [%d] = %d\n", symbol, aatx*frame_parms->nb_antennas_rx + aarx, chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i); //printf("symb %d chan_avg im [%d] = %d\n", symbol, aatx*frame_parms->nb_antennas_rx + aarx, chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i); chan_est_avg[aatx*frame_parms->nb_antennas_rx + aarx] = (((int32_t)chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i)<<16)|(((int32_t)chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].r) & 0xffff); //printf("symb %d chan_est_avg [%d] = %d\n", symbol, aatx*frame_parms->nb_antennas_rx + aarx, chan_est_avg[aatx*frame_parms->nb_antennas_rx + aarx]); dl_ch128=(__m128i *)&dl_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { dl_ch128[0] = _mm_set1_epi32(chan_est_avg[aatx*frame_parms->nb_antennas_rx + aarx]); dl_ch128[1] = _mm_set1_epi32(chan_est_avg[aatx*frame_parms->nb_antennas_rx + aarx]); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) { dl_ch128+=2; }else { dl_ch128[2] = _mm_set1_epi32(chan_est_avg[aatx*frame_parms->nb_antennas_rx + aarx]); dl_ch128+=3; } } } } _mm_empty(); _m_empty(); #elif defined(__arm__) #endif } void rxdataF_to_float(int32_t **rxdataF_ext, float complex **rxdataF_f, int n_rx, int length, int start_point) { short re; int aarx; int16_t imag; int16_t real; for (aarx=0; aarx<n_rx; aarx++) { for (re=0; re<length; re++){ imag = (int16_t) (rxdataF_ext[aarx][start_point + re] >> 16); real = (int16_t) (rxdataF_ext[aarx][start_point + re] & 0xffff); rxdataF_f[aarx][re] = (float)(real/(32768.0)) + I*(float)(imag/(32768.0)); #ifdef DEBUG_MMSE if (re==0){ printf("rxdataF_to_float: aarx = %d, real= %d, imag = %d\n", aarx, real, imag); //printf("rxdataF_to_float: rxdataF_ext[%d][%d] = %d\n", aarx, start_point + re, rxdataF_ext[aarx][start_point + re]); //printf("rxdataF_to_float: ant %d, re = %d, rxdataF_f real = %f, rxdataF_f imag = %f \n", aarx, re, creal(rxdataF_f[aarx][re]), cimag(rxdataF_f[aarx][re])); } #endif } } } void chan_est_to_float(int32_t **dl_ch_estimates_ext, float complex **dl_ch_estimates_ext_f, int n_tx, int n_rx, int length, int start_point) { short re; int aatx,aarx; int16_t imag; int16_t real; for (aatx=0; aatx<n_tx; aatx++){ for (aarx=0; aarx<n_rx; aarx++) { for (re=0; re<length; re++){ imag = (int16_t) (dl_ch_estimates_ext[aatx*n_rx + aarx][start_point + re] >> 16); real = (int16_t) (dl_ch_estimates_ext[aatx*n_rx + aarx][start_point+ re] & 0xffff); dl_ch_estimates_ext_f[aatx*n_rx + aarx][re] = (float)(real/(32768.0)) + I*(float)(imag/(32768.0)); #ifdef DEBUG_MMSE if (re==0){ printf("ant %d, re = %d, real = %d, imag = %d \n", aatx*n_rx + aarx, re, real, imag); printf("ant %d, re = %d, real = %f, imag = %f \n", aatx*n_rx + aarx, re, creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]), cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])); } #endif } } } } void float_to_chan_est(int32_t **dl_ch_estimates_ext, float complex **dl_ch_estimates_ext_f, int n_tx, int n_rx, int length, int start_point) { short re; int aarx, aatx; int16_t imag; int16_t real; for (aatx=0; aatx<n_tx; aatx++){ for (aarx=0; aarx<n_rx; aarx++) { for (re=0; re<length; re++){ if (cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])<-1) imag = 0x8000; else if (cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])>=1) imag = 0x7FFF; else imag = cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])*32768; if (creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])<-1) real = 0x8000; else if (creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])>=1) real = 0x7FFF; else real = creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])*32768; dl_ch_estimates_ext[aatx*n_rx + aarx][start_point + re] = (((int32_t)imag)<<16)|((int32_t)real & 0xffff); #ifdef DEBUG_MMSE if (re==0){ printf(" float_to_chan_est: chan est real = %f, chan est imag = %f\n",creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]), cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])); printf("float_to_chan_est: real fixed = %d, imag fixed = %d\n", real, imag); printf("float_to_chan_est: ant %d, re = %d, dl_ch_estimates_ext = %d \n", aatx*n_rx + aarx, re, dl_ch_estimates_ext[aatx*n_rx + aarx][start_point + re]); } #endif } } } } void float_to_rxdataF(int32_t **rxdataF_ext, float complex **rxdataF_f, int n_tx, int n_rx, int length, int start_point) { short re; int aarx; int16_t imag; int16_t real; for (aarx=0; aarx<n_rx; aarx++) { for (re=0; re<length; re++){ if (cimag(rxdataF_f[aarx][re])<-1) imag = 0x8000; else if (cimag(rxdataF_f[aarx][re])>=1) imag = 0x7FFF; else imag = cimag(rxdataF_f[aarx][re])*32768; if (creal(rxdataF_f[aarx][re])<-1) real = 0x8000; else if (creal(rxdataF_f[aarx][re])>=1) real = 0x7FFF; else real = creal(rxdataF_f[aarx][re])*32768; rxdataF_ext[aarx][start_point + re] = (((int32_t)imag)<<16)|(((int32_t)real) & 0xffff); #ifdef DEBUG_MMSE if (re==0){ printf(" float_to_rxdataF: real = %f, imag = %f\n",creal(rxdataF_f[aarx][re]), cimag(rxdataF_f[aarx][re])); printf("float_to_rxdataF: real fixed = %d, imag fixed = %d\n", real, imag); printf("float_to_rxdataF: ant %d, re = %d, rxdataF_ext = %d \n", aarx, re, rxdataF_ext[aarx][start_point + re]); } #endif } } } void mult_mmse_rxdataF(float complex** Wmmse, float complex** rxdataF_ext_f, int n_tx, int n_rx, int length, int start_point) { short re; int aarx, aatx; float complex* rxdata_re = malloc(n_rx*sizeof(float complex)); float complex* rxdata_mmse_re = malloc(n_rx*sizeof(float complex)); float complex* Wmmse_re = malloc(n_tx*n_rx*sizeof(float complex)); for (re=0;re<length; re++){ for (aarx=0; aarx<n_rx; aarx++){ rxdata_re[aarx] = rxdataF_ext_f[aarx][re]; #ifdef DEBUG_MMSE if (re==0) printf("mult_mmse_rxdataF before: rxdata_re[%d] = (%f, %f)\n", aarx, creal(rxdata_re[aarx]), cimag(rxdata_re[aarx])); #endif } for (aatx=0; aatx<n_tx; aatx++){ for (aarx=0; aarx<n_rx; aarx++){ Wmmse_re[aatx*n_rx + aarx] = Wmmse[aatx*n_rx + aarx][re]; } } mutl_matrix_matrix_col_based(Wmmse_re, rxdata_re, n_rx, n_tx, n_rx, 1, rxdata_mmse_re); for (aarx=0; aarx<n_rx; aarx++){ rxdataF_ext_f[aarx][re] = rxdata_mmse_re[aarx]; #ifdef DEBUG_MMSE if (re==0) printf("mult_mmse_rxdataF after: rxdataF_ext_f[%d] = (%f, %f)\n", aarx, creal(rxdataF_ext_f[aarx][re]), cimag(rxdataF_ext_f[aarx][re])); #endif } } free(rxdata_re); free(rxdata_mmse_re); free(Wmmse_re); } void mult_mmse_chan_est(float complex** Wmmse, float complex** dl_ch_estimates_ext_f, int n_tx, int n_rx, int length, int start_point) { short re; int aarx, aatx; float complex* chan_est_re = malloc(n_tx*n_rx*sizeof(float complex)); float complex* chan_est_mmse_re = malloc(n_tx*n_rx*sizeof(float complex)); float complex* Wmmse_re = malloc(n_tx*n_rx*sizeof(float complex)); for (re=0;re<length; re++){ for (aatx=0; aatx<n_tx; aatx++){ for (aarx=0; aarx<n_rx; aarx++){ chan_est_re[aatx*n_rx + aarx] = dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]; Wmmse_re[aatx*n_rx + aarx] = Wmmse[aatx*n_rx + aarx][re]; #ifdef DEBUG_MMSE if (re==0) printf("mult_mmse_chan_est: chan_est_re[%d] = (%f, %f)\n", aatx*n_rx + aarx, creal(chan_est_re[aatx*n_rx + aarx]), cimag(chan_est_re[aatx*n_rx + aarx])); #endif } } mutl_matrix_matrix_col_based(Wmmse_re, chan_est_re, n_rx, n_tx, n_rx, n_tx, chan_est_mmse_re); for (aatx=0; aatx<n_tx; aatx++){ for (aarx=0; aarx<n_rx; aarx++){ dl_ch_estimates_ext_f[aatx*n_rx + aarx][re] = chan_est_mmse_re[aatx*n_rx + aarx]; #ifdef DEBUG_MMSE if (re==0) printf("mult_mmse_chan_est: dl_ch_estimates_ext_f[%d][%d] = (%f, %f)\n", aatx*n_rx + aarx, re, creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]), cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])); #endif } } } free(Wmmse_re); free(chan_est_re); free(chan_est_mmse_re); } //compute average channel_level of effective (precoded) channel void dlsch_channel_level_TM34(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, unsigned char *pmi_ext, int *avg_0, int *avg_1, uint8_t symbol, unsigned short nb_rb, unsigned int mmse_flag, MIMO_mode_t mimo_mode){ #if defined(__x86_64__)||defined(__i386__) short rb; unsigned char aarx,nre=12,symbol_mod; __m128i *dl_ch0_128,*dl_ch1_128, dl_ch0_128_tmp, dl_ch1_128_tmp, avg_0_128D, avg_1_128D; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; //clear average level // avg_0_128D = _mm_setzero_si128(); // avg_1_128D = _mm_setzero_si128(); avg_0[0] = 0; avg_0[1] = 0; avg_1[0] = 0; avg_1[1] = 0; // 5 is always a symbol with no pilots for both normal and extended prefix if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) nre=8; else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB==1)) nre=10; else nre=12; for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; avg_0_128D = _mm_setzero_si128(); avg_1_128D = _mm_setzero_si128(); for (rb=0; rb<nb_rb; rb++) { // printf("rb %d : \n",rb); //print_shorts("ch0\n",&dl_ch0_128[0]); //print_shorts("ch1\n",&dl_ch1_128[0]); dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[0]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[0]); if (mmse_flag == 0){ if (mimo_mode==LARGE_CDD) prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) prec2A_TM4_128(0,&dl_ch0_128_tmp,&dl_ch1_128_tmp); else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) prec2A_TM4_128(1,&dl_ch0_128_tmp,&dl_ch1_128_tmp); else if (mimo_mode==DUALSTREAM_PUSCH_PRECODING) prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); } // mmtmpD0 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg_0_128D = _mm_add_epi32(avg_0_128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); avg_1_128D = _mm_add_epi32(avg_1_128D,_mm_madd_epi16(dl_ch1_128_tmp,dl_ch1_128_tmp)); dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[1]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[1]); if (mmse_flag == 0){ if (mimo_mode==LARGE_CDD) prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) prec2A_TM4_128(0,&dl_ch0_128_tmp,&dl_ch1_128_tmp); else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) prec2A_TM4_128(1,&dl_ch0_128_tmp,&dl_ch1_128_tmp); else if (mimo_mode==DUALSTREAM_PUSCH_PRECODING) prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); } // mmtmpD1 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg_0_128D = _mm_add_epi32(avg_0_128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); avg_1_128D = _mm_add_epi32(avg_1_128D,_mm_madd_epi16(dl_ch1_128_tmp,dl_ch1_128_tmp)); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) { dl_ch0_128+=2; dl_ch1_128+=2; } else { dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[2]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[2]); if (mmse_flag == 0){ if (mimo_mode==LARGE_CDD) prec2A_TM3_128(&dl_ch0_128_tmp,&dl_ch1_128_tmp); else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODING1) prec2A_TM4_128(0,&dl_ch0_128_tmp,&dl_ch1_128_tmp); else if (mimo_mode==DUALSTREAM_UNIFORM_PRECODINGj) prec2A_TM4_128(1,&dl_ch0_128_tmp,&dl_ch1_128_tmp); else if (mimo_mode==DUALSTREAM_PUSCH_PRECODING) prec2A_TM4_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); } // mmtmpD2 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg_1_128D = _mm_add_epi32(avg_1_128D,_mm_madd_epi16(dl_ch1_128_tmp,dl_ch1_128_tmp)); avg_0_128D = _mm_add_epi32(avg_0_128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); dl_ch0_128+=3; dl_ch1_128+=3; } } avg_0[aarx] = (((int*)&avg_0_128D)[0])/(nb_rb*nre) + (((int*)&avg_0_128D)[1])/(nb_rb*nre) + (((int*)&avg_0_128D)[2])/(nb_rb*nre) + (((int*)&avg_0_128D)[3])/(nb_rb*nre); // printf("From Chan_level aver stream 0 %d =%d\n", aarx, avg_0[aarx]); avg_1[aarx] = (((int*)&avg_1_128D)[0])/(nb_rb*nre) + (((int*)&avg_1_128D)[1])/(nb_rb*nre) + (((int*)&avg_1_128D)[2])/(nb_rb*nre) + (((int*)&avg_1_128D)[3])/(nb_rb*nre); // printf("From Chan_level aver stream 1 %d =%d\n", aarx, avg_1[aarx]); } //avg_0[0] = max(avg_0[0],avg_0[1]); //avg_1[0] = max(avg_1[0],avg_1[1]); //avg_0[0]= max(avg_0[0], avg_1[0]); avg_0[0] = avg_0[0] + avg_0[1]; // printf("From Chan_level aver stream 0 final =%d\n", avg_0[0]); avg_1[0] = avg_1[0] + avg_1[1]; // printf("From Chan_level aver stream 1 final =%d\n", avg_1[0]); avg_0[0] = min (avg_0[0], avg_1[0]); avg_1[0] = avg_0[0]; _mm_empty(); _m_empty(); #elif defined(__arm__) #endif } //compute average channel_level of effective (precoded) channel void dlsch_channel_level_TM56(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, unsigned char *pmi_ext, int *avg, uint8_t symbol, unsigned short nb_rb) { #if defined(__x86_64__)||defined(__i386__) short rb; unsigned char aarx,nre=12,symbol_mod; __m128i *dl_ch0_128,*dl_ch1_128, dl_ch0_128_tmp, dl_ch1_128_tmp,avg128D; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; //clear average level avg128D = _mm_setzero_si128(); avg[0] = 0; avg[1] = 0; // 5 is always a symbol with no pilots for both normal and extended prefix if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) nre=8; else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB==1)) nre=10; else nre=12; for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[0]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[0]); prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); // mmtmpD0 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[1]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[1]); prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); // mmtmpD1 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) { dl_ch0_128+=2; dl_ch1_128+=2; } else { dl_ch0_128_tmp = _mm_load_si128(&dl_ch0_128[2]); dl_ch1_128_tmp = _mm_load_si128(&dl_ch1_128[2]); prec2A_TM56_128(pmi_ext[rb],&dl_ch0_128_tmp,&dl_ch1_128_tmp); // mmtmpD2 = _mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch0_128_tmp,dl_ch0_128_tmp)); dl_ch0_128+=3; dl_ch1_128+=3; } } avg[aarx] = (((int*)&avg128D)[0])/(nb_rb*nre) + (((int*)&avg128D)[1])/(nb_rb*nre) + (((int*)&avg128D)[2])/(nb_rb*nre) + (((int*)&avg128D)[3])/(nb_rb*nre); } // choose maximum of the 2 effective channels avg[0] = cmax(avg[0],avg[1]); _mm_empty(); _m_empty(); #elif defined(__arm__) #endif } //compute average channel_level for TM7 void dlsch_channel_level_TM7(int **dl_bf_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, int *avg, uint8_t symbol, unsigned short nb_rb) { #if defined(__x86_64__)||defined(__i386__) short rb; unsigned char aatx,aarx,nre=12,symbol_mod; __m128i *dl_ch128,avg128D; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { //clear average level avg128D = _mm_setzero_si128(); // 5 is always a symbol with no pilots for both normal and extended prefix dl_ch128=(__m128i *)&dl_bf_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb<nb_rb; rb++) { // printf("rb %d : ",rb); // print_shorts("ch",&dl_ch128[0]); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[0],dl_ch128[0])); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[1],dl_ch128[1])); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) { dl_ch128+=2; } else { avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[2],dl_ch128[2])); dl_ch128+=3; } /* if (rb==0) { print_shorts("dl_ch128",&dl_ch128[0]); print_shorts("dl_ch128",&dl_ch128[1]); print_shorts("dl_ch128",&dl_ch128[2]); } */ } if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))) nre=10; else if ((frame_parms->Ncp==0) && (symbol==3 || symbol==6 || symbol==9 || symbol==12)) nre=9; else if ((frame_parms->Ncp==1) && (symbol==4 || symbol==7 || symbol==9)) nre=8; else nre=12; avg[(aatx<<1)+aarx] = (((int*)&avg128D)[0] + ((int*)&avg128D)[1] + ((int*)&avg128D)[2] + ((int*)&avg128D)[3])/(nb_rb*nre); // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); } _mm_empty(); _m_empty(); #elif defined(__arm__) #endif } //#define ONE_OVER_2_Q15 16384 void dlsch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, int **rxdataF_comp, int **dl_ch_mag, int **dl_ch_magb, unsigned char symbol, unsigned short nb_rb) { #if defined(__x86_64__)||defined(__i386__) short *rxF0,*rxF1; __m128i *ch_mag0,*ch_mag1,*ch_mag0b,*ch_mag1b, *rxF0_128; unsigned char rb,re; int jj = (symbol*frame_parms->N_RB_DL*12); uint8_t symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; uint8_t pilots = ((symbol_mod==0)||(symbol_mod==(4-frame_parms->Ncp))) ? 1 : 0; rxF0_128 = (__m128i*) &rxdataF_comp[0][jj]; //amp = _mm_set1_epi16(ONE_OVER_2_Q15); // printf("Doing alamouti!\n"); rxF0 = (short*)&rxdataF_comp[0][jj]; //tx antenna 0 h0*y rxF1 = (short*)&rxdataF_comp[2][jj]; //tx antenna 1 h1*y ch_mag0 = (__m128i *)&dl_ch_mag[0][jj]; ch_mag1 = (__m128i *)&dl_ch_mag[2][jj]; ch_mag0b = (__m128i *)&dl_ch_magb[0][jj]; ch_mag1b = (__m128i *)&dl_ch_magb[2][jj]; for (rb=0; rb<nb_rb; rb++) { for (re=0; re<((pilots==0)?12:8); re+=2) { // Alamouti RX combining // printf("Alamouti: symbol %d, rb %d, re %d: rxF0 (%d,%d,%d,%d), rxF1 (%d,%d,%d,%d)\n",symbol,rb,re,rxF0[0],rxF0[1],rxF0[2],rxF0[3],rxF1[0],rxF1[1],rxF1[2],rxF1[3]); rxF0[0] = rxF0[0] + rxF1[2]; rxF0[1] = rxF0[1] - rxF1[3]; rxF0[2] = rxF0[2] - rxF1[0]; rxF0[3] = rxF0[3] + rxF1[1]; // printf("Alamouti: rxF0 after (%d,%d,%d,%d)\n",rxF0[0],rxF0[1],rxF0[2],rxF0[3]); rxF0+=4; rxF1+=4; } // compute levels for 16QAM or 64 QAM llr unit ch_mag0[0] = _mm_adds_epi16(ch_mag0[0],ch_mag1[0]); ch_mag0[1] = _mm_adds_epi16(ch_mag0[1],ch_mag1[1]); ch_mag0b[0] = _mm_adds_epi16(ch_mag0b[0],ch_mag1b[0]); ch_mag0b[1] = _mm_adds_epi16(ch_mag0b[1],ch_mag1b[1]); // account for 1/sqrt(2) scaling at transmission //ch_mag0[0] = _mm_srai_epi16(ch_mag0[0],1); //ch_mag0[1] = _mm_srai_epi16(ch_mag0[1],1); //ch_mag0b[0] = _mm_srai_epi16(ch_mag0b[0],1); //ch_mag0b[1] = _mm_srai_epi16(ch_mag0b[1],1); //rxF0_128[0] = _mm_mulhi_epi16(rxF0_128[0],amp); //rxF0_128[0] = _mm_slli_epi16(rxF0_128[0],1); //rxF0_128[1] = _mm_mulhi_epi16(rxF0_128[1],amp); //rxF0_128[1] = _mm_slli_epi16(rxF0_128[1],1); //rxF0_128[0] = _mm_srai_epi16(rxF0_128[0],1); //rxF0_128[1] = _mm_srai_epi16(rxF0_128[1],1); if (pilots==0) { ch_mag0[2] = _mm_adds_epi16(ch_mag0[2],ch_mag1[2]); ch_mag0b[2] = _mm_adds_epi16(ch_mag0b[2],ch_mag1b[2]); //ch_mag0[2] = _mm_srai_epi16(ch_mag0[2],1); //ch_mag0b[2] = _mm_srai_epi16(ch_mag0b[2],1); //rxF0_128[2] = _mm_mulhi_epi16(rxF0_128[2],amp); //rxF0_128[2] = _mm_slli_epi16(rxF0_128[2],1); //rxF0_128[2] = _mm_srai_epi16(rxF0_128[2],1); ch_mag0+=3; ch_mag1+=3; ch_mag0b+=3; ch_mag1b+=3; rxF0_128+=3; } else { ch_mag0+=2; ch_mag1+=2; ch_mag0b+=2; ch_mag1b+=2; rxF0_128+=2; } } _mm_empty(); _m_empty(); #elif defined(__arm__) #endif } //============================================================================================== // Extraction functions //============================================================================================== unsigned short dlsch_extract_rbs_single(int **rxdataF, int **dl_ch_estimates, int **rxdataF_ext, int **dl_ch_estimates_ext, unsigned short pmi, unsigned char *pmi_ext, unsigned int *rb_alloc, unsigned char symbol, unsigned char subframe, uint32_t high_speed_flag, LTE_DL_FRAME_PARMS *frame_parms) { unsigned short rb,nb_rb=0; unsigned char rb_alloc_ind; unsigned char i,aarx,l,nsymb,skip_half=0,sss_symb,pss_symb=0; int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; unsigned char symbol_mod,pilots=0,j=0,poffset=0; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; pilots = ((symbol_mod==0)||(symbol_mod==(4-frame_parms->Ncp))) ? 1 : 0; l=symbol; nsymb = (frame_parms->Ncp==NORMAL) ? 14:12; if (frame_parms->frame_type == TDD) { // TDD sss_symb = nsymb-1; pss_symb = 2; } else { sss_symb = (nsymb>>1)-2; pss_symb = (nsymb>>1)-1; } if (symbol_mod==(4-frame_parms->Ncp)) poffset=3; for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { if (high_speed_flag == 1) dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; else dl_ch0 = &dl_ch_estimates[aarx][5]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; if ((frame_parms->N_RB_DL&1) == 0) // even number of RBs for (rb=0;rb<frame_parms->N_RB_DL;rb++) { if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; // For second half of RBs skip DC carrier if (rb==(frame_parms->N_RB_DL>>1)) { rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; //dl_ch0++; } // PBCH if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if ((frame_parms->frame_type == TDD) && (subframe==6)) { //TDD Subframe 6 if ((rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if (rb_alloc_ind==1) { *pmi_ext = (pmi>>((rb>>2)<<1))&3; memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); /* printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); printf("\n"); */ if (pilots==0) { for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; /* printf("%d : (%d,%d)\n",(rxF+i-&rxdataF[aarx][( (symbol*(frame_parms->ofdm_symbol_size)))]), ((short*)&rxF[i])[0],((short*)&rxF[i])[1]);*/ } dl_ch0_ext+=12; rxF_ext+=12; } else { j=0; for (i=0; i<12; i++) { if ((i!=(frame_parms->nushift+poffset)) && (i!=((frame_parms->nushift+poffset+6)%12))) { rxF_ext[j]=rxF[i]; // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=10; rxF_ext+=10; } } dl_ch0+=12; rxF+=12; } else { // Odd number of RBs for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) { #ifdef DEBUG_DLSCH_DEMOD printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); #endif skip_half=0; if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; //PSS in subframe 0/5 if FDD if (frame_parms->frame_type == FDD) { //FDD if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if ((frame_parms->frame_type == TDD) && (subframe==6)){ //TDD Subframe 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if (rb_alloc_ind==1) { #ifdef DEBUG_DLSCH_DEMOD printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); #endif if (pilots==0) { // printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); for (i=0; i<6; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=6; rxF_ext+=6; } else if (skip_half==2) { memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int)); for (i=0; i<6; i++) { rxF_ext[i]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=6; rxF_ext+=6; } else { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=12; rxF_ext+=12; } } else { // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); j=0; if (skip_half==1) { for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j++]=dl_ch0[i]; } } rxF_ext+=5; dl_ch0_ext+=5; } else if (skip_half==2) { for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j++]=dl_ch0[i+6]; } } dl_ch0_ext+=5; rxF_ext+=5; } else { for (i=0; i<12; i++) { if ((i!=(frame_parms->nushift+poffset)) && (i!=((frame_parms->nushift+poffset+6)%12))) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=10; rxF_ext+=10; } } } dl_ch0+=12; rxF+=12; } // first half loop // Do middle RB (around DC) if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; // PBCH if ((subframe==0) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (l==sss_symb) ) { rb_alloc_ind = 0; } if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } //PSS if ((frame_parms->frame_type == TDD) && (subframe==6) && (l==pss_symb) ) { rb_alloc_ind = 0; } // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); // printf("DC rb %d (%p)\n",rb,rxF); if (rb_alloc_ind==1) { #ifdef DEBUG_DLSCH_DEMOD printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); #endif if (pilots==0) { for (i=0; i<6; i++) { dl_ch0_ext[i]=dl_ch0[i]; rxF_ext[i]=rxF[i]; } rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { dl_ch0_ext[i]=dl_ch0[i]; rxF_ext[i]=rxF[(1+i-6)]; } dl_ch0_ext+=12; rxF_ext+=12; } else { // pilots==1 j=0; for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); #endif } } rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { if (i!=((frame_parms->nushift+6+poffset)%12)) { dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); #endif } } dl_ch0_ext+=10; rxF_ext+=10; } // symbol_mod==0 } // rballoc==1 else { rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; } dl_ch0+=12; rxF+=7; rb++; for (;rb<frame_parms->N_RB_DL;rb++) { // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); // printf("rb %d (%p)\n",rb,rxF); skip_half=0; if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } //PSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if ((frame_parms->frame_type == TDD) && (subframe==6)) { //TDD Subframe 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if (rb_alloc_ind==1) { #ifdef DEBUG_DLSCH_DEMOD printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); #endif /* printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); printf("\n"); */ if (pilots==0) { // printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); for (i=0; i<6; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=6; rxF_ext+=6; } else if (skip_half==2) { memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int)); for (i=0; i<6; i++) { rxF_ext[i]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=6; rxF_ext+=6; } else { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=12; rxF_ext+=12; } } else { // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); j=0; if (skip_half==1) { for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=5; rxF_ext+=5; } else if (skip_half==2) { for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j++]=dl_ch0[i+6]; } } dl_ch0_ext+=5; rxF_ext+=5; } else { for (i=0; i<12; i++) { if ((i!=(frame_parms->nushift+poffset)) && (i!=((frame_parms->nushift+poffset+6)%12))) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=10; rxF_ext+=10; } } // pilots=0 } dl_ch0+=12; rxF+=12; } } } return(nb_rb/frame_parms->nb_antennas_rx); } unsigned short dlsch_extract_rbs_dual(int **rxdataF, int **dl_ch_estimates, int **rxdataF_ext, int **dl_ch_estimates_ext, unsigned short pmi, unsigned char *pmi_ext, unsigned int *rb_alloc, unsigned char symbol, unsigned char subframe, uint32_t high_speed_flag, LTE_DL_FRAME_PARMS *frame_parms, MIMO_mode_t mimo_mode) { int prb,nb_rb=0; int prb_off,prb_off2; int rb_alloc_ind,skip_half=0,sss_symb,pss_symb=0,nsymb,l; int i,aarx; int32_t *dl_ch0,*dl_ch0p,*dl_ch0_ext,*dl_ch1,*dl_ch1p,*dl_ch1_ext,*rxF,*rxF_ext; int symbol_mod,pilots=0,j=0; unsigned char *pmi_loc; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; // printf("extract_rbs: symbol_mod %d\n",symbol_mod); if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) pilots=1; nsymb = (frame_parms->Ncp==NORMAL) ? 14:12; l=symbol; if (frame_parms->frame_type == TDD) { // TDD sss_symb = nsymb-1; pss_symb = 2; } else { sss_symb = (nsymb>>1)-2; pss_symb = (nsymb>>1)-1; } for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { if (high_speed_flag==1) { dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; dl_ch1 = &dl_ch_estimates[2+aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; } else { dl_ch0 = &dl_ch_estimates[aarx][5]; dl_ch1 = &dl_ch_estimates[2+aarx][5]; } pmi_loc = pmi_ext; // pointers to extracted RX signals and channel estimates rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; dl_ch1_ext = &dl_ch_estimates_ext[2+aarx][symbol*(frame_parms->N_RB_DL*12)]; for (prb=0; prb<frame_parms->N_RB_DL; prb++) { skip_half=0; if (prb < 32) rb_alloc_ind = (rb_alloc[0]>>prb) & 1; else if (prb < 64) rb_alloc_ind = (rb_alloc[1]>>(prb-32)) & 1; else if (prb < 96) rb_alloc_ind = (rb_alloc[2]>>(prb-64)) & 1; else if (prb < 100) rb_alloc_ind = (rb_alloc[3]>>(prb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; if ((frame_parms->N_RB_DL&1) == 0) { // even number of RBs // PBCH if ((subframe==0) && (prb>=((frame_parms->N_RB_DL>>1)-3)) && (prb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; // printf("symbol %d / rb %d: skipping PBCH REs\n",symbol,prb); } //SSS if (((subframe==0)||(subframe==5)) && (prb>=((frame_parms->N_RB_DL>>1)-3)) && (prb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; // printf("symbol %d / rb %d: skipping SSS REs\n",symbol,prb); } //PSS in subframe 0/5 if FDD if (frame_parms->frame_type == FDD) { //FDD if (((subframe==0)||(subframe==5)) && (prb>=((frame_parms->N_RB_DL>>1)-3)) && (prb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; // printf("symbol %d / rb %d: skipping PSS REs\n",symbol,prb); } } if ((frame_parms->frame_type == TDD) && (subframe==6)) { //TDD Subframe 6 if ((prb>=((frame_parms->N_RB_DL>>1)-3)) && (prb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if (rb_alloc_ind==1) { // PRB is allocated prb_off = 12*prb; prb_off2 = 1+(12*(prb-(frame_parms->N_RB_DL>>1))); dl_ch0p = dl_ch0+(12*prb); dl_ch1p = dl_ch1+(12*prb); if (prb<(frame_parms->N_RB_DL>>1)){ rxF = &rxdataF[aarx][prb_off+ frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size))]; } else { rxF = &rxdataF[aarx][prb_off2+ (symbol*(frame_parms->ofdm_symbol_size))]; } /* if (mimo_mode <= PUSCH_PRECODING1) *pmi_loc = (pmi>>((prb>>2)<<1))&3; else *pmi_loc=(pmi>>prb)&1;*/ *pmi_loc = get_pmi(frame_parms->N_RB_DL,mimo_mode,pmi,prb); pmi_loc++; if (pilots == 0) { memcpy(dl_ch0_ext,dl_ch0p,12*sizeof(int)); memcpy(dl_ch1_ext,dl_ch1p,12*sizeof(int)); memcpy(rxF_ext,rxF,12*sizeof(int)); dl_ch0_ext +=12; dl_ch1_ext +=12; rxF_ext +=12; } else { // pilots==1 j=0; for (i=0; i<12; i++) { if ((i!=frame_parms->nushift) && (i!=frame_parms->nushift+3) && (i!=frame_parms->nushift+6) && (i!=((frame_parms->nushift+9)%12))) { rxF_ext[j]=rxF[i]; // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0p[i]; dl_ch1_ext[j++]=dl_ch1p[i]; } } dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; } // pilots==1 } } else { // Odd number of RBs // PBCH if ((subframe==0) && (prb>((frame_parms->N_RB_DL>>1)-3)) && (prb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; // printf("symbol %d / rb %d: skipping PBCH REs\n",symbol,prb); } //SSS if (((subframe==0)||(subframe==5)) && (prb>((frame_parms->N_RB_DL>>1)-3)) && (prb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; // printf("symbol %d / rb %d: skipping SSS REs\n",symbol,prb); } //PSS in subframe 0/5 if FDD if (frame_parms->frame_type == FDD) { //FDD if (((subframe==0)||(subframe==5)) && (prb>((frame_parms->N_RB_DL>>1)-3)) && (prb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; // printf("symbol %d / rb %d: skipping PSS REs\n",symbol,prb); } } if ((frame_parms->frame_type == TDD) && ((subframe==1) || (subframe==6))) { //TDD Subframe 1-6 if ((prb>((frame_parms->N_RB_DL>>1)-3)) && (prb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if (rb_alloc_ind == 1) { skip_half=0; //Check if we have to drop half a PRB due to PSS/SSS/PBCH // skip_half == 0 means full PRB // skip_half == 1 means first half is used (leftmost half-PRB from PSS/SSS/PBCH) // skip_half == 2 means second half is used (rightmost half-PRB from PSS/SSS/PBCH) //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (prb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (prb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (prb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (prb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; //PSS Subframe 0,5 if (((frame_parms->frame_type == FDD) && (((subframe==0)||(subframe==5)))) || //FDD Subframes 0,5 ((frame_parms->frame_type == TDD) && (((subframe==1) || (subframe==6))))) { //TDD Subframes 1,6 if ((prb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((prb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } prb_off = 12*prb; prb_off2 = 7+(12*(prb-(frame_parms->N_RB_DL>>1)-1)); dl_ch0p = dl_ch0+(12*prb); dl_ch1p = dl_ch1+(12*prb); if (prb<=(frame_parms->N_RB_DL>>1)){ rxF = &rxdataF[aarx][prb_off+ frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size))]; } else { rxF = &rxdataF[aarx][prb_off2+ (symbol*(frame_parms->ofdm_symbol_size))]; } #ifdef DEBUG_DLSCH_DEMOD printf("symbol %d / rb %d: alloc %d skip_half %d (rxF %p, rxF_ext %p) prb_off (%d,%d)\n",symbol,prb,rb_alloc_ind,skip_half,rxF,rxF_ext,prb_off,prb_off2); #endif /* if (mimo_mode <= PUSCH_PRECODING1) *pmi_loc = (pmi>>((prb>>2)<<1))&3; else *pmi_loc=(pmi>>prb)&1; // printf("symbol_mod %d (pilots %d) rb %d, sb %d, pmi %d (pmi_loc %p,rxF %p, ch00 %p, ch01 %p, rxF_ext %p dl_ch0_ext %p dl_ch1_ext %p)\n",symbol_mod,pilots,prb,prb>>2,*pmi_loc,pmi_loc,rxF,dl_ch0, dl_ch1, rxF_ext,dl_ch0_ext,dl_ch1_ext); */ *pmi_loc = get_pmi(frame_parms->N_RB_DL,mimo_mode,pmi,prb); pmi_loc++; if (prb != (frame_parms->N_RB_DL>>1)) { // This PRB is not around DC if (pilots==0) { if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0p,6*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1p,6*sizeof(int32_t)); memcpy(rxF_ext,rxF,6*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD for (i=0;i<6;i++) printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif dl_ch0_ext+=6; dl_ch1_ext+=6; rxF_ext+=6; } else if (skip_half==2) { memcpy(dl_ch0_ext,dl_ch0p+6,6*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1p+6,6*sizeof(int32_t)); memcpy(rxF_ext,rxF+6,6*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD for (i=0;i<6;i++) printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif dl_ch0_ext+=6; dl_ch1_ext+=6; rxF_ext+=6; } else { // skip_half==0 memcpy(dl_ch0_ext,dl_ch0p,12*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1p,12*sizeof(int32_t)); memcpy(rxF_ext,rxF,12*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD for (i=0;i<12;i++) printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; } } else { // pilots=1 j=0; if (skip_half==1) { for (i=0; i<6; i++) { if ((i!=frame_parms->nushift) && (i!=((frame_parms->nushift+3)%6))) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("(pilots,skip1)extract rb %d, re %d (%d)=> (%d,%d)\n",prb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j]=dl_ch0p[i]; dl_ch1_ext[j++]=dl_ch1p[i]; } } dl_ch0_ext+=4; dl_ch1_ext+=4; rxF_ext+=4; } else if (skip_half==2) { for (i=0; i<6; i++) { if ((i!=frame_parms->nushift) && (i!=((frame_parms->nushift+3)%6))) { rxF_ext[j]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD printf("(pilots,skip2)extract rb %d, re %d (%d) => (%d,%d)\n",prb,i,j,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j]=dl_ch0p[i+6]; dl_ch1_ext[j++]=dl_ch1p[i+6]; } } dl_ch0_ext+=4; dl_ch1_ext+=4; rxF_ext+=4; } else { //skip_half==0 for (i=0; i<12; i++) { if ((i!=frame_parms->nushift) && (i!=frame_parms->nushift+3) && (i!=frame_parms->nushift+6) && (i!=((frame_parms->nushift+9)%12))) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("(pilots)extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j] =dl_ch0p[i]; dl_ch1_ext[j++]=dl_ch1p[i]; } } dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; } //skip_half==0 } //pilots==1 } else { // Do middle RB (around DC) if (pilots==0) { memcpy(dl_ch0_ext,dl_ch0p,6*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1p,6*sizeof(int32_t)); memcpy(rxF_ext,rxF,6*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD for (i=0; i<6; i++) { printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); } #endif rxF_ext+=6; dl_ch0_ext+=6; dl_ch1_ext+=6; dl_ch0p+=6; dl_ch1p+=6; rxF = &rxdataF[aarx][1+((symbol*(frame_parms->ofdm_symbol_size)))]; memcpy(dl_ch0_ext,dl_ch0p,6*sizeof(int32_t)); memcpy(dl_ch1_ext,dl_ch1p,6*sizeof(int32_t)); memcpy(rxF_ext,rxF,6*sizeof(int32_t)); #ifdef DEBUG_DLSCH_DEMOD for (i=0; i<6; i++) { printf("extract rb %d, re %d => (%d,%d)\n",prb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); } #endif rxF_ext+=6; dl_ch0_ext+=6; dl_ch1_ext+=6; } else { // pilots==1 j=0; for (i=0; i<6; i++) { if ((i!=frame_parms->nushift) && (i!=((frame_parms->nushift+3)%6))) { dl_ch0_ext[j]=dl_ch0p[i]; dl_ch1_ext[j]=dl_ch1p[i]; rxF_ext[j++]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("(pilots)extract rb %d, re %d (%d) => (%d,%d)\n",prb,i,j,*(short *)&rxF[i],*(1+(short*)&rxF[i])); #endif } } rxF = &rxdataF[aarx][1+symbol*(frame_parms->ofdm_symbol_size)]; for (; i<12; i++) { if ((i!=((frame_parms->nushift+6)%12)) && (i!=((frame_parms->nushift+9)%12))) { dl_ch0_ext[j]=dl_ch0p[i]; dl_ch1_ext[j]=dl_ch1p[i]; rxF_ext[j++]=rxF[i-6]; #ifdef DEBUG_DLSCH_DEMOD printf("(pilots)extract rb %d, re %d (%d) => (%d,%d)\n",prb,i,j,*(short *)&rxF[1+i-6],*(1+(short*)&rxF[1+i-6])); #endif } } dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; } //pilots==1 } // if Middle PRB } // if odd PRB } // if rballoc==1 } // for prb } // for aarx return(nb_rb/frame_parms->nb_antennas_rx); } unsigned short dlsch_extract_rbs_TM7(int **rxdataF, int **dl_bf_ch_estimates, int **rxdataF_ext, int **dl_bf_ch_estimates_ext, unsigned int *rb_alloc, unsigned char symbol, unsigned char subframe, uint32_t high_speed_flag, LTE_DL_FRAME_PARMS *frame_parms) { unsigned short rb,nb_rb=0; unsigned char rb_alloc_ind; unsigned char i,aarx,l,nsymb,skip_half=0,sss_symb,pss_symb=0; int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; unsigned char symbol_mod,pilots=0,uespec_pilots=0,j=0,poffset=0,uespec_poffset=0; int8_t uespec_nushift = frame_parms->Nid_cell%3; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; pilots = ((symbol_mod==0)||(symbol_mod==(4-frame_parms->Ncp))) ? 1 : 0; l=symbol; nsymb = (frame_parms->Ncp==NORMAL) ? 14:12; if (frame_parms->Ncp==0){ if (symbol==3 || symbol==6 || symbol==9 || symbol==12) uespec_pilots = 1; } else{ if (symbol==4 || symbol==7 || symbol==10) uespec_pilots = 1; } if (frame_parms->frame_type == TDD) {// TDD sss_symb = nsymb-1; pss_symb = 2; } else { sss_symb = (nsymb>>1)-2; pss_symb = (nsymb>>1)-1; } if (symbol_mod==(4-frame_parms->Ncp)) poffset=3; if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7)) uespec_poffset=2; for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) { if (high_speed_flag == 1) dl_ch0 = &dl_bf_ch_estimates[aarx][symbol*(frame_parms->ofdm_symbol_size)]; else dl_ch0 = &dl_bf_ch_estimates[aarx][0]; dl_ch0_ext = &dl_bf_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; if ((frame_parms->N_RB_DL&1) == 0) // even number of RBs for (rb=0; rb<frame_parms->N_RB_DL; rb++) { if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; // For second half of RBs skip DC carrier if (rb==(frame_parms->N_RB_DL>>1)) { rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; //dl_ch0++; } // PBCH if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if ((frame_parms->frame_type == TDD) && (subframe==6)) { //TDD Subframe 6 if ((rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if (rb_alloc_ind==1) { /* printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); printf("\n"); */ if (pilots==0 && uespec_pilots==0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; } dl_ch0_ext+=12; rxF_ext+=12; } else if(pilots==1 && uespec_pilots==0) { j=0; for (i=0; i<12; i++) { if ((i!=(frame_parms->nushift+poffset)) && (i!=((frame_parms->nushift+poffset+6)%12))) { rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=10; rxF_ext+=10; } else if (pilots==0 && uespec_pilots==1) { j=0; for (i=0; i<12; i++){ if (frame_parms->Ncp==0){ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ rxF_ext[j] = rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; } } else{ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j] = rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; } } } dl_ch0_ext+=9-frame_parms->Ncp; rxF_ext+=9-frame_parms->Ncp; } else { LOG_E(PHY,"dlsch_extract_rbs_TM7(dl_demodulation.c):pilot or ue spec pilot detection error\n"); exit(-1); } } dl_ch0+=12; rxF+=12; } else { // Odd number of RBs for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) { skip_half=0; if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; //PSS in subframe 0/5 if FDD if (frame_parms->frame_type == FDD) { //FDD if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if (rb_alloc_ind==1) { #ifdef DEBUG_DLSCH_DEMOD printf("rb %d/symbol %d pilots %d, uespec_pilots %d, (skip_half %d)\n",rb,l,pilots,uespec_pilots,skip_half); #endif if (pilots==0 && uespec_pilots==0) { //printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); for (i=0; i<6; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=6; rxF_ext+=6; } else if (skip_half==2) { memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int)); for (i=0; i<6; i++) { rxF_ext[i]=rxF[(i+6)]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=6; rxF_ext+=6; } else { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); for (i=0; i<12; i++){ rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",symbol,rb,i,*(short *)&rxF[i],*(1+(short*)&rxF[i])); #endif } dl_ch0_ext+=12; rxF_ext+=12; } } else if (pilots==1 && uespec_pilots==0) { // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); j=0; if (skip_half==1) { for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=5; rxF_ext+=5; } else if (skip_half==2) { for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=5; rxF_ext+=5; } else { for (i=0; i<12; i++) { if ((i!=(frame_parms->nushift+poffset)) && (i!=((frame_parms->nushift+poffset+6)%12))) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=10; rxF_ext+=10; } } else if(pilots==0 && uespec_pilots==1){ //printf("Extracting with uespec pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); j=0; if (skip_half==1) { if (frame_parms->Ncp==0){ for (i=0; i<6; i++) { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6); rxF_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6); } else{ for (i=0; i<6; i++) { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=4; rxF_ext+=4; } } else if (skip_half==2) { if(frame_parms->Ncp==0){ for (i=0; i<6; i++) { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6); rxF_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6); } else { for (i=0; i<6; i++) { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=4; rxF_ext+=4; } } else { for (i=0; i<12; i++){ if (frame_parms->Ncp==0){ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ rxF_ext[j] = rxF[i]; dl_ch0_ext[j++] = dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d, j %d => (%d,%d)\n",symbol,rb,i,j-1,*(short *)&dl_ch0[j],*(1+(short*)&dl_ch0[i])); #endif } } else{ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j] = rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } } dl_ch0_ext+=9-frame_parms->Ncp; rxF_ext+=9-frame_parms->Ncp; } } else { LOG_E(PHY,"dlsch_extract_rbs_TM7(dl_demodulation.c):pilot or ue spec pilot detection error\n"); exit(-1); } } dl_ch0+=12; rxF+=12; } // first half loop // Do middle RB (around DC) if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; // PBCH if ((subframe==0) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //PSS if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } //printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); //printf("DC rb %d (%p)\n",rb,rxF); if (rb_alloc_ind==1) { //printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); if (pilots==0 && uespec_pilots==0) { for (i=0; i<6; i++) { dl_ch0_ext[i]=dl_ch0[i]; rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { dl_ch0_ext[i]=dl_ch0[i]; rxF_ext[i]=rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=12; rxF_ext+=12; } else if(pilots==1 && uespec_pilots==0){ // pilots==1 j=0; for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { if (i!=((frame_parms->nushift+6+poffset)%12)) { dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=10; rxF_ext+=10; } else if(pilots==0 && uespec_pilots==1) { j=0; for (i=0; i<6; i++) { if (frame_parms->Ncp==0){ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++] = rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } else { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++] = rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } } rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; for (; i<12; i++) { if (frame_parms->Ncp==0){ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++]=rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } else { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ dl_ch0_ext[j]=dl_ch0[i]; rxF_ext[j++] = rxF[(1+i-6)]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } } dl_ch0_ext+=9-frame_parms->Ncp; rxF_ext+=9-frame_parms->Ncp; }// symbol_mod==0 } // rballoc==1 else { rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; } dl_ch0+=12; rxF+=7; rb++; for (; rb<frame_parms->N_RB_DL; rb++) { // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); // printf("rb %d (%p)\n",rb,rxF); skip_half=0; if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind==1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; //PSS if (frame_parms->frame_type == FDD) { if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if ((frame_parms->frame_type == TDD) && ((subframe==1)||(subframe==6))) { //TDD Subframe 1 and 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if (rb_alloc_ind==1) { #ifdef DEBUG_DLSCH_DEMOD printf("rb %d/symbol %d (skip_half %d)\n",rb,l,skip_half); #endif /* printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); printf("\n"); */ if (pilots==0 && uespec_pilots==0) { //printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); for (i=0; i<6; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=6; rxF_ext+=6; } else if (skip_half==2) { memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int)); for (i=0; i<6; i++) { rxF_ext[i]=rxF[i+6]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=6; rxF_ext+=6; } else { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); //printf("symbol %d, extract rb %d, => (%d,%d)\n",symbol,rb,*(short *)&dl_ch0[j],*(1+(short*)&dl_ch0[i])); for (i=0; i<12; i++) { rxF_ext[i]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } dl_ch0_ext+=12; rxF_ext+=12; } } else if (pilots==1 && uespec_pilots==0){ //printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); j=0; if (skip_half==1) { for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=5; rxF_ext+=5; } else if (skip_half==2) { for (i=0; i<6; i++) { if (i!=((frame_parms->nushift+poffset)%6)) { rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=5; rxF_ext+=5; } else { for (i=0; i<12; i++) { if ((i!=(frame_parms->nushift+poffset)) && (i!=((frame_parms->nushift+poffset+6)%12))) { rxF_ext[j]=rxF[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); #endif dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=10; rxF_ext+=10; } } else if(pilots==0 && uespec_pilots==1) { j=0; if (skip_half==1) { if (frame_parms->Ncp==0){ for (i=0; i<6; i++) { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6); rxF_ext+=6-(uespec_nushift+uespec_poffset<6)-(uespec_nushift+uespec_poffset+4<6)-((uespec_nushift+uespec_poffset+8)%12<6); } else{ for (i=0; i<6; i++) { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j]=rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=4; rxF_ext+=4; } } else if (skip_half==2) { if(frame_parms->Ncp==0){ for (i=0; i<6; i++) { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ rxF_ext[j]=rxF[i+6]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6); rxF_ext+=6-(uespec_nushift+uespec_poffset>6)-(uespec_nushift+uespec_poffset+4>6)-((uespec_nushift+uespec_poffset+8)%12>6); } else { for (i=0; i<6; i++) { if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j]=rxF[(i+6)]; dl_ch0_ext[j++]=dl_ch0[i+6]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } dl_ch0_ext+=4; rxF_ext+=4; } } else { for (i=0; i<12; i++){ if (frame_parms->Ncp==0){ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+4 && i!=(uespec_nushift+uespec_poffset+8)%12){ rxF_ext[j] = rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } else{ if (i!=uespec_nushift+uespec_poffset && i!=uespec_nushift+uespec_poffset+3 && i!=uespec_nushift+uespec_poffset+6 && i!=(uespec_nushift+uespec_poffset+9)%12){ rxF_ext[j] = rxF[i]; dl_ch0_ext[j++]=dl_ch0[i]; #ifdef DEBUG_DLSCH_DEMOD printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[i],*(1+(short*)&rxF_ext[i])); #endif } } } dl_ch0_ext+=9-frame_parms->Ncp; rxF_ext+=9-frame_parms->Ncp; } }// pilots=0 } dl_ch0+=12; rxF+=12; } } } _mm_empty(); _m_empty(); return(nb_rb/frame_parms->nb_antennas_rx); } //============================================================================================== void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t subframe,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid) { unsigned int nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; char fname[32],vname[32]; int N_RB_DL=ue->frame_parms.N_RB_DL; sprintf(fname,"dlsch%d_rxF_r%d_ext0.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_ext0",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb,1,1); if (ue->frame_parms.nb_antennas_rx >1) { sprintf(fname,"dlsch%d_rxF_r%d_ext1.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_ext1",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->rxdataF_ext[1],12*N_RB_DL*nsymb,1,1); } sprintf(fname,"dlsch%d_ch_r%d_ext00.m",eNB_id,round); sprintf(vname,"dl%d_ch_r%d_ext00",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); if (ue->transmission_mode[eNB_id]==7){ sprintf(fname,"dlsch%d_bf_ch_r%d.m",eNB_id,round); sprintf(vname,"dl%d_bf_ch_r%d",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_bf_ch_estimates[0],512*nsymb,1,1); //LOG_M(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates[0],512,1,1); sprintf(fname,"dlsch%d_bf_ch_r%d_ext00.m",eNB_id,round); sprintf(vname,"dl%d_bf_ch_r%d_ext00",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_bf_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); } if (ue->frame_parms.nb_antennas_rx == 2) { sprintf(fname,"dlsch%d_ch_r%d_ext01.m",eNB_id,round); sprintf(vname,"dl%d_ch_r%d_ext01",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); } if (ue->frame_parms.nb_antenna_ports_eNB == 2) { sprintf(fname,"dlsch%d_ch_r%d_ext10.m",eNB_id,round); sprintf(vname,"dl%d_ch_r%d_ext10",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); if (ue->frame_parms.nb_antennas_rx == 2) { sprintf(fname,"dlsch%d_ch_r%d_ext11.m",eNB_id,round); sprintf(vname,"dl%d_ch_r%d_ext11",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); } } sprintf(fname,"dlsch%d_rxF_r%d_uespec0.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_uespec0",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->rxdataF_uespec_pilots[0],12*N_RB_DL,1,1); /* LOG_M("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); LOG_M("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); LOG_M("dlsch%d_ch_ext11.m","dl11_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); */ sprintf(fname,"dlsch%d_r%d_rho.m",eNB_id,round); sprintf(vname,"dl_rho_r%d_%d",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_ch_rho_ext[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); sprintf(fname,"dlsch%d_r%d_rho2.m",eNB_id,round); sprintf(vname,"dl_rho2_r%d_%d",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_ch_rho2_ext[0],12*N_RB_DL*nsymb,1,1); sprintf(fname,"dlsch%d_rxF_r%d_comp0.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_comp0",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb,1,1); if (ue->frame_parms.nb_antenna_ports_eNB == 2) { sprintf(fname,"dlsch%d_rxF_r%d_comp1.m",eNB_id,round); sprintf(vname,"dl%d_rxF_r%d_comp1",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp1[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); } sprintf(fname,"dlsch%d_rxF_r%d_llr.m",eNB_id,round); sprintf(vname,"dl%d_r%d_llr",eNB_id,round); LOG_M(fname,vname, ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->llr[0],coded_bits_per_codeword[0],1,0); sprintf(fname,"dlsch%d_r%d_mag1.m",eNB_id,round); sprintf(vname,"dl%d_r%d_mag1",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_ch_mag0[0],12*N_RB_DL*nsymb,1,1); sprintf(fname,"dlsch%d_r%d_mag2.m",eNB_id,round); sprintf(vname,"dl%d_r%d_mag2",eNB_id,round); LOG_M(fname,vname,ue->pdsch_vars[ue->current_thread_id[subframe]][eNB_id]->dl_ch_magb0[0],12*N_RB_DL*nsymb,1,1); // printf("log2_maxh = %d\n",ue->pdsch_vars[eNB_id]->log2_maxh); } #ifdef DEBUG_DLSCH_DEMOD /* void print_bytes(char *s,__m128i *x) { char *tempb = (char *)x; printf("%s : %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",s, tempb[0],tempb[1],tempb[2],tempb[3],tempb[4],tempb[5],tempb[6],tempb[7], tempb[8],tempb[9],tempb[10],tempb[11],tempb[12],tempb[13],tempb[14],tempb[15] ); } void print_shorts(char *s,__m128i *x) { short *tempb = (short *)x; printf("%s : %d,%d,%d,%d,%d,%d,%d,%d\n",s, tempb[0],tempb[1],tempb[2],tempb[3],tempb[4],tempb[5],tempb[6],tempb[7]); } void print_shorts2(char *s,__m64 *x) { short *tempb = (short *)x; printf("%s : %d,%d,%d,%d\n",s, tempb[0],tempb[1],tempb[2],tempb[3]); } void print_ints(char *s,__m128i *x) { int *tempb = (int *)x; printf("%s : %d,%d,%d,%d\n",s, tempb[0],tempb[1],tempb[2],tempb[3]); }*/ #endif