/* * 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 */ #include #include "PHY/TOOLS/tools_defs.h" #include "sim.h" //#define DEBUG_CH //#define DOPPLER_DEBUG uint8_t multipath_channel_nosigconv(channel_desc_t *desc) { random_channel(desc,0); return(1); } //#define CHANNEL_SSE #ifdef CHANNEL_SSE void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *desc, double tx_sig_re[NB_ANTENNAS_TX][30720*2], double tx_sig_im[NB_ANTENANS_TX][30720*2], double rx_sig_re[NB_ANTENNAS_RX][30720*2], double rx_sig_im[NB_ANTENNAS_RX][30720*2], uint32_t length, uint8_t keep_channel, int log_channel) { int i,ii,j,l; int length1, length2, tail; simde__m128d rx_tmp128_re_f, rx_tmp128_im_f, rx_tmp128_re, rx_tmp128_im, rx_tmp128_1, rx_tmp128_2, rx_tmp128_3, rx_tmp128_4, tx128_re, tx128_im, ch128_x, ch128_y, pathloss128; double path_loss = pow(10,desc->path_loss_dB/20); uint64_t dd = desc->channel_offset; pathloss128 = simde_mm_set1_pd(path_loss); #ifdef DEBUG_CH printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %lu, len %d \n",keep_channel,path_loss,desc->path_loss_dB,desc->nb_rx,desc->nb_tx,dd,desc->channel_length); #endif if (keep_channel) { // do nothing - keep channel } else { random_channel(desc,0); } start_meas(&desc->convolution); #ifdef DEBUG_CH for (int l = 0; l<(int)desc->channel_length; l++) { printf("%p (%f,%f) ",desc->ch[0],desc->ch[0][l].x,desc->ch[0][l].y); } printf("\n"); #endif tail = ((int)length-dd)%2; if(tail) length1 = ((int)length-dd)-1; else length1 = ((int)length-dd); length2 = length1/2; for (i=0; inb_rx; ii++) { // rx_tmp.x = 0; // rx_tmp.y = 0; rx_tmp128_re_f = simde_mm_setzero_pd(); rx_tmp128_im_f = simde_mm_setzero_pd(); for (j=0; jnb_tx; j++) { for (l = 0; l<(int)desc->channel_length; l++) { if ((i>=0) && (i-l)>=0) { //SIMD correct only if length1 > 2*channel_length...which is almost always satisfied // tx.x = tx_sig_re[j][i-l]; // tx.y = tx_sig_im[j][i-l]; tx128_re = simde_mm_loadu_pd(&tx_sig_re[j][2 * i - l]); // tx_sig_re[j][i-l+1], tx_sig_re[j][i-l] tx128_im = simde_mm_loadu_pd(&tx_sig_im[j][2 * i - l]); } else { //tx.x =0; //tx.y =0; tx128_re = simde_mm_setzero_pd(); tx128_im = simde_mm_setzero_pd(); } ch128_x = simde_mm_set1_pd(desc->ch[ii + (j * desc->nb_rx)][l].x); ch128_y = simde_mm_set1_pd(desc->ch[ii + (j * desc->nb_rx)][l].y); // rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y); // rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y); rx_tmp128_1 = simde_mm_mul_pd(tx128_re, ch128_x); rx_tmp128_2 = simde_mm_mul_pd(tx128_re, ch128_y); rx_tmp128_3 = simde_mm_mul_pd(tx128_im, ch128_x); rx_tmp128_4 = simde_mm_mul_pd(tx128_im, ch128_y); rx_tmp128_re = simde_mm_sub_pd(rx_tmp128_1, rx_tmp128_4); rx_tmp128_im = simde_mm_add_pd(rx_tmp128_2, rx_tmp128_3); rx_tmp128_re_f = simde_mm_add_pd(rx_tmp128_re_f, rx_tmp128_re); rx_tmp128_im_f = simde_mm_add_pd(rx_tmp128_im_f, rx_tmp128_im); } //l } // j //rx_sig_re[ii][i+dd] = rx_tmp.x*path_loss; //rx_sig_im[ii][i+dd] = rx_tmp.y*path_loss; rx_tmp128_re_f = simde_mm_mul_pd(rx_tmp128_re_f, pathloss128); rx_tmp128_im_f = simde_mm_mul_pd(rx_tmp128_im_f, pathloss128); simde_mm_storeu_pd(&rx_sig_re[ii][2 * i + dd], rx_tmp128_re_f); // max index: length-dd -1 + dd = length -1 simde_mm_storeu_pd(&rx_sig_im[ii][2 * i + dd], rx_tmp128_im_f); /* if ((ii==0)&&((i%32)==0)) { printf("%p %p %f,%f => %e,%e\n",rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]); } */ //rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]); //rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]); } // ii } // i stop_meas(&desc->convolution); } #else void __attribute__ ((no_sanitize_address)) multipath_channel(channel_desc_t *desc, double *tx_sig_re[NB_ANTENNAS_TX], double *tx_sig_im[NB_ANTENNAS_TX], double *rx_sig_re[NB_ANTENNAS_RX], double *rx_sig_im[NB_ANTENNAS_RX], uint32_t length, uint8_t keep_channel, int log_channel) { double path_loss = pow(10,desc->path_loss_dB/20); uint64_t dd = desc->channel_offset; #ifdef DEBUG_CH printf("[CHANNEL] keep = %d : path_loss = %g (%f), nb_rx %d, nb_tx %d, dd %lu, len %d \n", keep_channel, path_loss, desc->path_loss_dB, desc->nb_rx, desc->nb_tx, dd, desc->channel_length); #endif if (keep_channel) { // do nothing - keep channel } else { random_channel(desc,0); } #ifdef DEBUG_CH for (int l = 0; l<(int)desc->channel_length; l++) { printf("ch[%i] = (%f, %f)\n", l, desc->ch[0][l].r, desc->ch[0][l].i); } #endif struct complexd cexp_doppler[length]; if (desc->max_Doppler != 0.0) { get_cexp_doppler(cexp_doppler, desc, length); } for (int i=0; i<((int)length-dd); i++) { for (int ii=0; iinb_rx; ii++) { struct complexd rx_tmp={0}; for (int j=0; jnb_tx; j++) { struct complexd *chan=desc->ch[ii+(j*desc->nb_rx)]; for (int l = 0; l<(int)desc->channel_length; l++) { if ((i>=0) && (i-l)>=0) { struct complexd tx; tx.r = tx_sig_re[j][i-l]; tx.i = tx_sig_im[j][i-l]; rx_tmp.r += (tx.r * chan[l].r) - (tx.i * chan[l].i); rx_tmp.i += (tx.i * chan[l].r) + (tx.r * chan[l].i); } #if 0 if (i==0 && log_channel == 1) { printf("channel[%d][%d][%d] = %f dB \t(%e, %e)\n", ii, j, l, 10 * log10(pow(chan[l].r, 2.0) + pow(chan[l].i, 2.0)), chan[l].r, chan[l].i); } #endif } //l } // j #if 0 if (desc->max_Doppler != 0.0) rx_tmp = cdMul(rx_tmp, cexp_doppler[i]); #endif #ifdef DOPPLER_DEBUG printf("[k %2i] cexp_doppler = (%7.4f, %7.4f), abs(cexp_doppler) = %.4f\n", i, cexp_doppler[i].r, cexp_doppler[i].i, sqrt(cexp_doppler[i].r * cexp_doppler[i].r + cexp_doppler[i].i * cexp_doppler[i].i)); #endif rx_sig_re[ii][i+dd] = rx_tmp.r*path_loss; rx_sig_im[ii][i+dd] = rx_tmp.i*path_loss; #ifdef DEBUG_CH if ((i%32)==0) { printf("rx aa %d: %f, %f => %e, %e\n", ii, rx_tmp.r, rx_tmp.i, rx_sig_re[ii][i-dd], rx_sig_im[ii][i-dd]); } #endif //rx_sig_re[ii][i] = sqrt(.5)*(tx_sig_re[0][i] + tx_sig_re[1][i]); //rx_sig_im[ii][i] = sqrt(.5)*(tx_sig_im[0][i] + tx_sig_im[1][i]); } // ii } // i } #endif