232 lines
8.1 KiB
C
232 lines
8.1 KiB
C
/*
|
|
* 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 <math.h>
|
|
#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 (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; i<length2; i++) { //
|
|
for (ii=0; ii<desc->nb_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; j<desc->nb_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 (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; ii<desc->nb_rx; ii++) {
|
|
struct complexd rx_tmp={0};
|
|
for (int j=0; j<desc->nb_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
|
|
|
|
|