Merge remote-tracking branch 'origin/develop-nr_cppcheck' into integration_develop-nr_2019w42
Conflicts: executables/nr-gnb.c openair1/PHY/NR_REFSIG/nr_dmrs_rx.c openair1/SIMULATION/NR_PHY/ulsim.c
This commit is contained in:
@@ -41,9 +41,9 @@
|
||||
/* name of shared library implementing the transport */
|
||||
#define OAI_TP_LIBNAME "oai_transpro"
|
||||
/* name of shared library implementing the basic/rf simulator */
|
||||
#define OAI_RFSIM_LIBNAME "rfsimulator"
|
||||
#define OAI_RFSIM_LIBNAME "rfsimulator"
|
||||
/* name of shared library implementing the basic/rf simulator */
|
||||
#define OAI_BASICSIM_LIBNAME "tcp_bridge_oai"
|
||||
#define OAI_BASICSIM_LIBNAME "tcp_bridge_oai"
|
||||
/* flags for BBU to determine whether the attached radio head is local or remote */
|
||||
#define RAU_LOCAL_RADIO_HEAD 0
|
||||
#define RAU_REMOTE_RADIO_HEAD 1
|
||||
@@ -420,7 +420,6 @@ typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_
|
||||
|
||||
#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size)
|
||||
|
||||
#define sample_t struct complex16 // 2*16 bits complex number
|
||||
|
||||
typedef struct {
|
||||
uint64_t magic; // Magic value (see defines above)
|
||||
@@ -446,8 +445,6 @@ typedef struct {
|
||||
|
||||
#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size)
|
||||
|
||||
#define sample_t struct complex16 // 2*16 bits complex number
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
|
||||
@@ -42,11 +42,11 @@
|
||||
#include <net/if.h>
|
||||
#include <netinet/ether.h>
|
||||
|
||||
#define MAX_INST 4
|
||||
#define DEFAULT_IF "lo"
|
||||
#define MAX_INST 4
|
||||
#define DEFAULT_IF "lo"
|
||||
|
||||
#define TX_FLAG 1
|
||||
#define RX_FLAG 0
|
||||
#define TX_FLAG 1
|
||||
#define RX_FLAG 0
|
||||
|
||||
#include "if_defs.h"
|
||||
#define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp))
|
||||
|
||||
@@ -1,63 +1,81 @@
|
||||
#General
|
||||
This is an RF simulator that allows to test OAI without an RF board.
|
||||
# General
|
||||
This is an RF simulator that allows to test OAI without an RF board. It replaces an actual RF board driver.
|
||||
|
||||
It replaces an actual RF board driver.
|
||||
As much as possible, it works like an RF board, but not in real-time: It can run faster than real-time if there is enough CPU, or slower (it is CPU-bound instead of real-time RF sampling-bound).
|
||||
|
||||
As much as possible, it works like an RF board, but not in realtime: It can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound)
|
||||
# build
|
||||
|
||||
#build
|
||||
## From [build_oai](../../../doc/BUILD.md) script
|
||||
The RF simulator is implemented as an OAI device and always built when you build the OAI eNB or the OAI UE.
|
||||
|
||||
## From build_oai
|
||||
You can build it the same way, and together with actual RF driver
|
||||
Using the `-w SIMU` option it is possible to just re-build the RF simulator device.
|
||||
|
||||
Example:
|
||||
```bash
|
||||
./build_oai --ue-nas-use-tun --UE --eNB -w SIMU
|
||||
./build_oai --UE --eNB
|
||||
Will compile UE
|
||||
Will compile eNB
|
||||
CMAKE_CMD=cmake ..
|
||||
No local radio head and no transport protocol selected
|
||||
No radio head has been selected (HW set to None)
|
||||
No transport protocol has been selected (TP set to None)
|
||||
RF HW set to None
|
||||
Flags for Deadline scheduler: False
|
||||
......................
|
||||
......................
|
||||
Compiling rfsimulator
|
||||
Log file for compilation has been written to: /usr/local/oai/rfsimu_config/openairinterface5g/cmake_targets/log/rfsimulator.Rel15.txt
|
||||
rfsimulator compiled
|
||||
......................
|
||||
......................
|
||||
```
|
||||
It is also possible to build actual RF and use choose on each run:
|
||||
```bash
|
||||
./build_oai --ue-nas-use-tun --UE --eNB -w USRP --rfsimulator
|
||||
```
|
||||
Will build both the eNB (lte-softmodem) and the UE (lte-uesoftmodem)
|
||||
We recommend using the option --ue-nas-use-tun that is much simpler to use than the OAI kernel driver.
|
||||
|
||||
## Add the rfsimulator after initial build
|
||||
After any regular build, you can compile the driver
|
||||
|
||||
After any regular build you can compile the device from the build directory:
|
||||
```bash
|
||||
cd <the_compilation_dir_from_build_oai_script>/build
|
||||
cd <path to oai sources>/openairinterface5g/cmake_targets/ran_build/build
|
||||
make rfsimulator
|
||||
```
|
||||
Then, you can use it freely
|
||||
This is equivalent to using `-w SIMU` when running the `build_oai` script.
|
||||
|
||||
# Usage
|
||||
Setting the env variable RFSIMULATOR enables the RF board simulator. It should be set to "server" in the eNB or gNB.
|
||||
To use the RF simulator add the `--rfsim` option to the command line. By default the RF simulator device will try to connect to host 127.0.0.1, port 4043, which is usually the behavior for the UE.
|
||||
|
||||
The RF simulator is using the configuration module, and its parameters are defined in a specific section called "rfsimulator".
|
||||
|
||||
| parameter | usage | default |
|
||||
|:---------------------|:------------------------------------------------------------------------------------------------------------------|----:|
|
||||
| serveraddr | ip address to connect to, or "enb" to behave as a tcp server | 127.0.0.1 |
|
||||
| serverport | port number to connect to or to listen on (eNB, which behaves as a tcp server) | 4043 |
|
||||
| options | list of comma separated run-time options, two are supported: `chanmod` to enable channel modeling and `saviq` to write transmitted iqs to a file | all options disabled |
|
||||
| modelname | Name of the channel model to apply on received iqs when the `chanmod` option is enabled | AWGN |
|
||||
| IQfile | Path to the file to be used to store iqs, when the `saviq` option is enabled | /tmp/rfsimulator.iqs |
|
||||
|
||||
Setting the env variable RFSIMULATOR can be used instead of using the serveraddr parameter; it is to preserve compatibility with previous version.
|
||||
|
||||
## 4G case
|
||||
|
||||
For the UE, it should be set to the IP address of the eNB
|
||||
example:
|
||||
For the UE, it should be set to the IP address of the eNB. For example:
|
||||
```bash
|
||||
sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50
|
||||
```
|
||||
For the eNodeB, use a valid configuration file setup for USRP board tests and start the softmodem as usual, **but** adding the `--rfsim` option.
|
||||
|
||||
For the eNB, use a valid configuration file setup for the USRP board tests and start the softmodem as usual, **but**, adding the `--rfsim` option.
|
||||
```bash
|
||||
sudo RFSIMULATOR=enb ./lte-softmodem -O <config file> --rfsim
|
||||
```
|
||||
|
||||
Except this, the UE and the eNB can be used as if the RF is real
|
||||
|
||||
If you reach 'RA not active' on UE, be careful to generate a valid SIM
|
||||
Except this, the UE and the eNB can be used as if the RF is real. noS1 mode can also be used with the RF simulator.
|
||||
|
||||
If you reach 'RA not active' on UE, be careful to generate a valid SIM.
|
||||
```bash
|
||||
$OPENAIR_DIR/targets/bin/conf2uedata -c $OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o .
|
||||
```
|
||||
|
||||
## 5G case
|
||||
After regular build, add the simulation driver
|
||||
(don't use ./build_oai -w SIMU until we merge 4G and 5G branches)
|
||||
|
||||
The 5G RF simulator will be aligned with the 4G as the efforts for merging the 5G specific branches into the develop make progresses.
|
||||
|
||||
After regular build, add the simulation driver (do not use ./build_oai -w SIMU until 4G and 5G branches are merged).
|
||||
```bash
|
||||
cd ran_build/build
|
||||
make rfsimulator
|
||||
@@ -77,46 +95,40 @@ sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C 3510000000
|
||||
|
||||
Of course, set the gNB machine IP address if the UE and the gNB are not on the same machine.
|
||||
|
||||
In UE, you can add "-d" to get the softscope
|
||||
In the UE, you can add `-d` option to get the softscope.
|
||||
|
||||
### Store and replay
|
||||
|
||||
You can store emitted I/Q samples:
|
||||
You can store emitted I/Q samples. If you set the option `saviq`, the simulator will write all the I/Q samples into this file. Then, you can replay with the executable `replay_node`.
|
||||
|
||||
If you set the environment variable: saveIQfile to a file name
|
||||
The simulator will write all IQ samples into this file
|
||||
|
||||
Then, you can replay with the executable "replay_node"
|
||||
|
||||
First compile it, as the other binaries
|
||||
```
|
||||
First compile it like other binaries:
|
||||
```bash
|
||||
make replay_node
|
||||
```
|
||||
You can use this binary as I/Q data source to feed whatever UE or NB with recorded I/Q samples.
|
||||
You can use this binary as I/Q data source to feed whatever UE or gNB with recorded I/Q samples.
|
||||
|
||||
The file format is successive blocks of a header followed by the I/Q array.
|
||||
If you have existing stored I/Q, you can adpat the tool "replay_node" to convert your format to the rfsimulator format.
|
||||
The file format is successive blocks of a header followed by the I/Q array. If you have existing stored I/Q, you can adapt the tool `replay_node` to convert your format to the rfsimulator format.
|
||||
|
||||
The format intend to be compatible with the OAI store/replay feature on USRP
|
||||
The format intends to be compatible with the OAI store/replay feature on USRP.
|
||||
|
||||
### Channel simulation
|
||||
The RF channel simulator is called.
|
||||
In current version all channel paramters are hard coded in the call to:
|
||||
|
||||
When the `chanmod` option is enabled, the RF channel simulator is called.
|
||||
|
||||
In the current version all channel parameters are set depending on the model name via a call to:
|
||||
```bash
|
||||
new_channel_desc_scm(bridge->tx_num_channels,
|
||||
bridge->rx_num_channels,
|
||||
AWGN,
|
||||
<model name>,
|
||||
bridge->sample_rate,
|
||||
bridge->tx_bw,
|
||||
0.0, // forgetting_factor
|
||||
0, // maybe used for TA
|
||||
0); // path_loss in dB
|
||||
0, // maybe used for TA
|
||||
0); // path_loss in dB
|
||||
```
|
||||
Only the input noise can be changed on command line with the `-s` parameter.
|
||||
|
||||
Only the input noise can be changed on command line with -s parameter.
|
||||
With path loss = 0 set `-s 5` to see a little noise. `-s` is a shortcut to `channelmod.s`. It is expected to enhance the channel modelization flexibility by the addition of more parameters in the channelmod section.
|
||||
|
||||
With path loss = 0 set "-s 5" to see a little noise.
|
||||
|
||||
## Caveats
|
||||
Still issues in power control: txgain, rxgain are not used
|
||||
# Caveats
|
||||
Still issues in power control: txgain, rxgain are not used.
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Author: Laurent THOMAS, Open Cells for Nokia
|
||||
copyleft: OpenAirInterface Software Alliance and it's licence
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#include <common/utils/assertions.h>
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include <common/config/config_userapi.h>
|
||||
#include <openair1/SIMULATION/TOOLS/sim.h>
|
||||
|
||||
/*
|
||||
Legacy study:
|
||||
The parameters are:
|
||||
gain&loss (decay, signal power, ...)
|
||||
either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average
|
||||
=> don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE
|
||||
will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop)
|
||||
lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas);
|
||||
a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain
|
||||
|
||||
multi_path (auto convolution, ISI, ...)
|
||||
either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes
|
||||
legacy: we regenerate each sub frame in UL, and each frame only in DL
|
||||
*/
|
||||
void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_sig,
|
||||
int rxAnt,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS,
|
||||
uint32_t CirSize
|
||||
) {
|
||||
// channelDesc->path_loss_dB should contain the total path gain
|
||||
// so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...)
|
||||
// UE and NB gain control to be added
|
||||
// Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...)
|
||||
const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0);
|
||||
// Energy in one sample to calibrate input noise
|
||||
//Fixme: modified the N0W computation, not understand the origin value
|
||||
const double KT=1.38e-23*290; //Boltzman*temperature
|
||||
// sampling rate is linked to acquisition band (the input pass band filter)
|
||||
const double noise_figure_watt = KT*channelDesc->sampling_rate;
|
||||
// Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ?
|
||||
// the parameter "-s" is declared as SNR, but the input power is not well defined
|
||||
// −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise)
|
||||
const double rxGain= 132.24 - channelmod_get_snr_dB();
|
||||
// sqrt(4*noise_figure_watt) is the thermal noise factor (volts)
|
||||
// fixme: the last constant is pure trial results to make decent noise
|
||||
const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10;
|
||||
// Fixme: we don't fill the offset length samples at begining ?
|
||||
// anyway, in today code, channel_offset=0
|
||||
const int dd = abs(channelDesc->channel_offset);
|
||||
const int nbTx=channelDesc->nb_tx;
|
||||
|
||||
for (int i=0; i<((int)nbSamples-dd); i++) {
|
||||
struct complex16 *out_ptr=after_channel_sig+dd+i;
|
||||
struct complex rx_tmp= {0};
|
||||
|
||||
for (int txAnt=0; txAnt < nbTx; txAnt++) {
|
||||
const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)];
|
||||
|
||||
//const struct complex *channelModelEnd=channelModel+channelDesc->channel_length;
|
||||
for (int l = 0; l<(int)channelDesc->channel_length; l++) {
|
||||
// let's assume TS+i >= l
|
||||
// fixme: the rfsimulator current structure is interleaved antennas
|
||||
// this has been designed to not have to wait a full block transmission
|
||||
// but it is not very usefull
|
||||
// it would be better to split out each antenna in a separate flow
|
||||
// that will allow to mix ru antennas freely
|
||||
struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize];
|
||||
rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y;
|
||||
rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y;
|
||||
} //l
|
||||
}
|
||||
|
||||
out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
|
||||
out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
|
||||
out_ptr++;
|
||||
}
|
||||
|
||||
if ( (TS*nbTx)%CirSize+nbSamples <= CirSize )
|
||||
// Cast to a wrong type for compatibility !
|
||||
LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n",
|
||||
10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)),
|
||||
10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)),
|
||||
channelDesc->path_loss_dB,
|
||||
10*log10(noise_per_sample));
|
||||
}
|
||||
@@ -24,12 +24,15 @@
|
||||
|
||||
#include <common/utils/assertions.h>
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include <common/utils/load_module_shlib.h>
|
||||
#include <common/config/config_userapi.h>
|
||||
#include "common_lib.h"
|
||||
#include <openair1/PHY/defs_eNB.h>
|
||||
#include "openair1/PHY/defs_UE.h"
|
||||
#define CHANNELMOD_DYNAMICLOAD
|
||||
#include <openair1/SIMULATION/TOOLS/sim.h>
|
||||
|
||||
#define PORT 4043 //TCP port for this simulator
|
||||
#define PORT 4043 //default TCP port for this simulator
|
||||
#define CirSize 3072000 // 100ms is enough
|
||||
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
|
||||
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
|
||||
@@ -39,12 +42,31 @@
|
||||
|
||||
// Fixme: datamodel, external variables in .h files, ...
|
||||
#include <common/ran_context.h>
|
||||
extern double snr_dB;
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
//
|
||||
|
||||
#define RFSIMU_SECTION "rfsimulator"
|
||||
#define RFSIMU_OPTIONS_PARAMNAME "options"
|
||||
# define RFSIM_CONFIG_HELP_OPTIONS " list of comma separated options to enable rf simulator functionalities. Available options: \n"\
|
||||
" chanmod: enable channel modelisation\n"\
|
||||
" saviq: enable saving written iqs to a file\n"
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* configuration parameters for the rfsimulator device */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define RFSIMULATOR_PARAMS_DESC {\
|
||||
{"serveraddr", "<ip address to connect to>\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\
|
||||
{"serverport", "<port to connect to>\n", 0, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\
|
||||
{RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0},\
|
||||
{"IQfile", "<file path to use when saving IQs>\n", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\
|
||||
{"modelname", "<channel model name>\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 }\
|
||||
};
|
||||
|
||||
pthread_mutex_t Sockmutex;
|
||||
|
||||
typedef struct complex16 sample_t; // 2*16 bits complex number
|
||||
|
||||
typedef struct buffer_s {
|
||||
int conn_sock;
|
||||
openair0_timestamp lastReceivedTS;
|
||||
@@ -63,91 +85,16 @@ typedef struct {
|
||||
openair0_timestamp nextTimestamp;
|
||||
uint64_t typeStamp;
|
||||
char *ip;
|
||||
uint16_t port;
|
||||
int saveIQfile;
|
||||
buffer_t buf[FD_SETSIZE];
|
||||
int rx_num_channels;
|
||||
int tx_num_channels;
|
||||
double sample_rate;
|
||||
double tx_bw;
|
||||
int channelmod;
|
||||
} rfsimulator_state_t;
|
||||
|
||||
/*
|
||||
Legacy study:
|
||||
The parameters are:
|
||||
gain&loss (decay, signal power, ...)
|
||||
either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average
|
||||
=> don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE
|
||||
will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop)
|
||||
lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas);
|
||||
a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain
|
||||
|
||||
multi_path (auto convolution, ISI, ...)
|
||||
either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes
|
||||
legacy: we regenerate each sub frame in UL, and each frame only in DL
|
||||
*/
|
||||
void rxAddInput( struct complex16 *input_sig,
|
||||
struct complex16 *after_channel_sig,
|
||||
int rxAnt,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS
|
||||
) {
|
||||
// channelDesc->path_loss_dB should contain the total path gain
|
||||
// so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...)
|
||||
// UE and NB gain control to be added
|
||||
// Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...)
|
||||
const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0);
|
||||
// Energy in one sample to calibrate input noise
|
||||
//Fixme: modified the N0W computation, not understand the origin value
|
||||
const double KT = 1.38e-23*290; //Boltzman*temperature
|
||||
// sampling rate is linked to acquisition band (the input pass band filter)
|
||||
const double noise_figure_watt = KT*channelDesc->sampling_rate;
|
||||
// Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ?
|
||||
// the parameter "-s" is declared as SNR, but the input power is not well defined
|
||||
// −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise)
|
||||
const double rxGain = 132.24 - snr_dB;
|
||||
// sqrt(4*noise_figure_watt) is the thermal noise factor (volts)
|
||||
// fixme: the last constant is pure trial results to make decent noise
|
||||
const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10;
|
||||
// Fixme: we don't fill the offset length samples at begining ?
|
||||
// anyway, in today code, channel_offset=0
|
||||
const int dd = abs(channelDesc->channel_offset);
|
||||
const int nbTx = channelDesc->nb_tx;
|
||||
|
||||
for (int i=0; i<((int)nbSamples-dd); i++) {
|
||||
struct complex16 *out_ptr=after_channel_sig+dd+i;
|
||||
struct complex rx_tmp= {0};
|
||||
|
||||
for (int txAnt=0; txAnt < nbTx; txAnt++) {
|
||||
const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)];
|
||||
|
||||
//const struct complex *channelModelEnd=channelModel+channelDesc->channel_length;
|
||||
for (int l = 0; l<(int)channelDesc->channel_length; l++) {
|
||||
// let's assume TS+i >= l
|
||||
// fixme: the rfsimulator current structure is interleaved antennas
|
||||
// this has been designed to not have to wait a full block transmission
|
||||
// but it is not very usefull
|
||||
// it would be better to split out each antenna in a separate flow
|
||||
// that will allow to mix ru antennas freely
|
||||
struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize];
|
||||
rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y;
|
||||
rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y;
|
||||
} //l
|
||||
}
|
||||
|
||||
out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
|
||||
out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
|
||||
out_ptr++;
|
||||
}
|
||||
|
||||
if ( (TS*nbTx)%CirSize+nbSamples <= CirSize )
|
||||
// Cast to a wrong type for compatibility !
|
||||
LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n",
|
||||
10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)),
|
||||
10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)),
|
||||
channelDesc->path_loss_dB,
|
||||
10*log10(noise_per_sample));
|
||||
}
|
||||
|
||||
void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||
buffer_t *ptr=&bridge->buf[sock];
|
||||
@@ -165,26 +112,29 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||
ev.events = EPOLLIN | EPOLLRDHUP;
|
||||
ev.data.fd = sock;
|
||||
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
|
||||
// create channel simulation model for this mode reception
|
||||
// snr_dB is pure global, coming from configuration paramter "-s"
|
||||
// Fixme: referenceSignalPower should come from the right place
|
||||
// but the datamodel is inconsistant
|
||||
// legacy: RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower
|
||||
// (must not come from ru[]->frame_parms as it doesn't belong to ru !!!)
|
||||
// Legacy sets it as:
|
||||
// ptr->channel_model->path_loss_dB = -132.24 + snr_dB - RC.ru[0]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
// we use directly the paramter passed on the command line ("-s")
|
||||
// the value channel_model->path_loss_dB seems only a storage place (new_channel_desc_scm() only copy the passed value)
|
||||
// Legacy changes directlty the variable channel_model->path_loss_dB place to place
|
||||
// while calling new_channel_desc_scm() with path losses = 0
|
||||
ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels,
|
||||
AWGN,
|
||||
bridge->sample_rate,
|
||||
bridge->tx_bw,
|
||||
0.0, // forgetting_factor
|
||||
0, // maybe used for TA
|
||||
0); // path_loss in dB
|
||||
random_channel(ptr->channel_model,false);
|
||||
|
||||
if ( bridge->channelmod > 0) {
|
||||
// create channel simulation model for this mode reception
|
||||
// snr_dB is pure global, coming from configuration paramter "-s"
|
||||
// Fixme: referenceSignalPower should come from the right place
|
||||
// but the datamodel is inconsistant
|
||||
// legacy: RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower
|
||||
// (must not come from ru[]->frame_parms as it doesn't belong to ru !!!)
|
||||
// Legacy sets it as:
|
||||
// ptr->channel_model->path_loss_dB = -132.24 + snr_dB - RC.ru[0]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
// we use directly the paramter passed on the command line ("-s")
|
||||
// the value channel_model->path_loss_dB seems only a storage place (new_channel_desc_scm() only copy the passed value)
|
||||
// Legacy changes directlty the variable channel_model->path_loss_dB place to place
|
||||
// while calling new_channel_desc_scm() with path losses = 0
|
||||
ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels,
|
||||
bridge->channelmod,
|
||||
bridge->sample_rate,
|
||||
bridge->tx_bw,
|
||||
0.0, // forgetting_factor
|
||||
0, // maybe used for TA
|
||||
0); // path_loss in dB
|
||||
random_channel(ptr->channel_model,false);
|
||||
}
|
||||
}
|
||||
|
||||
void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||
@@ -213,6 +163,7 @@ void socketError(rfsimulator_state_t *bridge, int sock) {
|
||||
rfsimulator: error: you have to run one UE and one eNB\n\
|
||||
For this, export RFSIMULATOR=enb (eNB case) or \n\
|
||||
RFSIMULATOR=<an ip address> (UE case)\n\
|
||||
or use rfsimulator.serveraddr configuration option\n\
|
||||
\x1b[m"
|
||||
|
||||
enum blocking_t {
|
||||
@@ -267,6 +218,48 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
|
||||
char *saveF=NULL;
|
||||
char *modelname=NULL;
|
||||
paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC;
|
||||
int p = config_paramidx_fromname(rfsimu_params,sizeof(rfsimu_params)/sizeof(paramdef_t), RFSIMU_OPTIONS_PARAMNAME) ;
|
||||
int ret = config_get( rfsimu_params,sizeof(rfsimu_params)/sizeof(paramdef_t),RFSIMU_SECTION);
|
||||
AssertFatal(ret >= 0, "configuration couldn't be performed");
|
||||
rfsimulator->saveIQfile = -1;
|
||||
|
||||
for(int i=0; i<rfsimu_params[p].numelt ; i++) {
|
||||
if (strcmp(rfsimu_params[p].strlistptr[i],"saviq") == 0) {
|
||||
rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666);
|
||||
|
||||
if ( rfsimulator->saveIQfile != -1 )
|
||||
LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF);
|
||||
else
|
||||
LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno));
|
||||
|
||||
break;
|
||||
} else if (strcmp(rfsimu_params[p].strlistptr[i],"chanmod") == 0) {
|
||||
init_channelmod();
|
||||
rfsimulator->channelmod=modelid_fromname(modelname);
|
||||
} else {
|
||||
fprintf(stderr,"Unknown rfsimulator option: %s\n",rfsimu_params[p].strlistptr[i]);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* for compatibility keep environment variable usage */
|
||||
if ( getenv("RFSIMULATOR") != NULL ) {
|
||||
rfsimulator->ip=getenv("RFSIMULATOR");
|
||||
}
|
||||
|
||||
if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 ||
|
||||
strncasecmp(rfsimulator->ip,"server",3) == 0 )
|
||||
rfsimulator->typeStamp = ENB_MAGICDL_FDD;
|
||||
else
|
||||
rfsimulator->typeStamp = UE_MAGICDL_FDD;
|
||||
}
|
||||
|
||||
int server_start(openair0_device *device) {
|
||||
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
|
||||
t->typeStamp=ENB_MAGICDL_FDD;
|
||||
@@ -277,7 +270,7 @@ int server_start(openair0_device *device) {
|
||||
sin_family:
|
||||
AF_INET,
|
||||
sin_port:
|
||||
htons(PORT),
|
||||
htons(t->port),
|
||||
sin_addr:
|
||||
{ s_addr: INADDR_ANY }
|
||||
};
|
||||
@@ -299,7 +292,7 @@ int start_ue(openair0_device *device) {
|
||||
sin_family:
|
||||
AF_INET,
|
||||
sin_port:
|
||||
htons(PORT),
|
||||
htons(t->port),
|
||||
sin_addr:
|
||||
{ s_addr: INADDR_ANY }
|
||||
};
|
||||
@@ -307,7 +300,7 @@ sin_addr:
|
||||
bool connected=false;
|
||||
|
||||
while(!connected) {
|
||||
LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", t->ip, PORT);
|
||||
LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", t->ip, t->port);
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
|
||||
LOG_I(HW,"rfsimulator: connection established\n");
|
||||
@@ -327,15 +320,15 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi
|
||||
rfsimulator_state_t *t = device->priv;
|
||||
LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp);
|
||||
|
||||
|
||||
for (int i=0; i<FD_SETSIZE; i++) {
|
||||
buffer_t *b=&t->buf[i];
|
||||
|
||||
if (b->conn_sock >= 0 ) {
|
||||
if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize)
|
||||
if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize )
|
||||
LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS);
|
||||
|
||||
samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
|
||||
fullwrite(b->conn_sock,&header, sizeof(header), t);
|
||||
fullwrite(b->conn_sock, &header, sizeof(header), t);
|
||||
sample_t tmpSamples[nsamps][nbAnt];
|
||||
|
||||
for(int a=0; a<nbAnt; a++) {
|
||||
@@ -488,39 +481,48 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
||||
|
||||
if ( first_sock == FD_SETSIZE ) {
|
||||
// no connected device (we are eNB, no UE is connected)
|
||||
if ( t->nextTimestamp == 0)
|
||||
LOG_W(HW,"No connected device, generating void samples...\n");
|
||||
|
||||
if (!flushInput(t, 10)) {
|
||||
for (int x=0; x < nbAnt; x++)
|
||||
memset(samplesVoid[x],0,sampleToByte(nsamps,1));
|
||||
|
||||
t->nextTimestamp+=nsamps;
|
||||
LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
|
||||
|
||||
if ( ((t->nextTimestamp/nsamps)%100) == 0)
|
||||
LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
|
||||
|
||||
*ptimestamp = t->nextTimestamp-nsamps;
|
||||
pthread_mutex_unlock(&Sockmutex);
|
||||
return nsamps;
|
||||
}
|
||||
} else {
|
||||
|
||||
bool have_to_wait;
|
||||
|
||||
do {
|
||||
have_to_wait=false;
|
||||
|
||||
for ( int sock=0; sock<FD_SETSIZE; sock++) {
|
||||
for (int sock=0; sock<FD_SETSIZE; sock++) {
|
||||
buffer_t *b=&t->buf[sock];
|
||||
|
||||
if ( b->circularBuf) {
|
||||
LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n",
|
||||
sock, b->lastWroteTS,
|
||||
b->lastReceivedTS,
|
||||
t->nextTimestamp+nsamps);
|
||||
|
||||
if ( b->lastReceivedTS > b->lastWroteTS ) {
|
||||
// The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance
|
||||
// This occurs for example when UE is in sync mode: it doesn't transmit
|
||||
// with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power
|
||||
struct complex16 v={0};
|
||||
void *samplesVoid[b->th.nbAnt];
|
||||
for ( int i=0; i <b->th.nbAnt; i++)
|
||||
samplesVoid[i]=(void*)&v;
|
||||
rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0);
|
||||
// The caller modem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance
|
||||
// This occurs for example when UE is in sync mode: it doesn't transmit
|
||||
// with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power
|
||||
struct complex16 v = {0};
|
||||
void *samplesVoid[b->th.nbAnt];
|
||||
|
||||
for ( int i=0; i < b->th.nbAnt; i++)
|
||||
samplesVoid[i]=(void *)&v;
|
||||
|
||||
rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,13 +558,24 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
||||
if (reGenerateChannel)
|
||||
random_channel(ptr->channel_model,0);
|
||||
|
||||
for (int a=0; a<nbAnt; a++)
|
||||
rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a],
|
||||
a,
|
||||
ptr->channel_model,
|
||||
nsamps,
|
||||
t->nextTimestamp
|
||||
);
|
||||
for (int a=0; a<nbAnt; a++) {
|
||||
if ( ptr->channel_model != NULL ) // apply a channel model
|
||||
rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a],
|
||||
a,
|
||||
ptr->channel_model,
|
||||
nsamps,
|
||||
t->nextTimestamp,
|
||||
CirSize
|
||||
);
|
||||
else { // no channel modeling
|
||||
sample_t *out=(sample_t *)samplesVoid[a];
|
||||
|
||||
for ( int i=0; i < nsamps; i++ ) {
|
||||
out[i].r+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].r;
|
||||
out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize].i;
|
||||
}
|
||||
} // end of no channel modeling
|
||||
} // end for a...
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,33 +618,9 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
// --log_config.hw_log_level debug
|
||||
// (for phy layer, replace "hw" by "phy")
|
||||
rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
|
||||
|
||||
if ((rfsimulator->ip=getenv("RFSIMULATOR")) == NULL ) {
|
||||
LOG_E(HW,helpTxt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rfsimulator_readconfig(rfsimulator);
|
||||
pthread_mutex_init(&Sockmutex, NULL);
|
||||
|
||||
if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 ||
|
||||
strncasecmp(rfsimulator->ip,"server",3) == 0 )
|
||||
rfsimulator->typeStamp = ENB_MAGICDL_FDD;
|
||||
else
|
||||
rfsimulator->typeStamp = UE_MAGICDL_FDD;
|
||||
|
||||
LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE");
|
||||
char *saveF;
|
||||
|
||||
if ((saveF=getenv("saveIQfile")) != NULL) {
|
||||
rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666);
|
||||
|
||||
if ( rfsimulator->saveIQfile != -1 )
|
||||
LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF);
|
||||
else
|
||||
LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno));
|
||||
} else
|
||||
rfsimulator->saveIQfile = -1;
|
||||
|
||||
device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ?
|
||||
server_start :
|
||||
start_ue;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <common/utils/simple_executable.h>
|
||||
|
||||
volatile int oai_exit = 0;
|
||||
|
||||
void fullwrite(int fd, void *_buf, int count) {
|
||||
char *buf = _buf;
|
||||
@@ -123,7 +124,7 @@ int main(int argc, char *argv[]) {
|
||||
setblocking(serviceSock, blocking);
|
||||
AssertFatal(read(fd,&header,sizeof(header)), "");
|
||||
fullwrite(serviceSock, &header, sizeof(header));
|
||||
int dataSize=sizeof(sample_t)*header.size*header.nbAnt;
|
||||
int dataSize=sizeof(int32_t)*header.size*header.nbAnt;
|
||||
|
||||
if (dataSize>bufSize) {
|
||||
void * new_buff = realloc(buff, dataSize);
|
||||
|
||||
@@ -230,6 +230,7 @@ eNBs =
|
||||
|
||||
|
||||
pdsch_maxNumRepetitionCEmodeA_r13 = "r16"; #0
|
||||
pusch_repetitionLevelCEmodeA_r13 = "l1"; #0
|
||||
#pdsch_maxNumRepetitionCEmodeB_r13 = "r384"; # NULL - 2
|
||||
|
||||
pusch_maxNumRepetitionCEmodeA_r13 = "r8"; #0
|
||||
|
||||
@@ -275,12 +275,24 @@ NETWORK_CONTROLLER :
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
/*
|
||||
#example config for rfsimulator
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "enb";
|
||||
serverport = "4043";
|
||||
options = ("saviq");
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
*/
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
|
||||
#include "../../ARCH/COMMON/common_lib.h"
|
||||
#include "targets/ARCH/COMMON/common_lib.h"
|
||||
|
||||
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
|
||||
#include "PHY/phy_extern.h"
|
||||
|
||||
|
||||
#include "LAYER2/MAC/mac.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "LAYER2/MAC/mac_proto.h"
|
||||
@@ -118,9 +117,9 @@ extern int oaisim_flag;
|
||||
|
||||
//uint16_t sf_ahead=4;
|
||||
extern uint16_t sf_ahead;
|
||||
|
||||
extern PARALLEL_CONF_t get_thread_parallel_conf(void);
|
||||
extern WORKER_CONF_t get_thread_worker_conf(void);
|
||||
#include "executables/thread-common.h"
|
||||
//extern PARALLEL_CONF_t get_thread_parallel_conf(void);
|
||||
//extern WORKER_CONF_t get_thread_worker_conf(void);
|
||||
|
||||
//pthread_t main_eNB_thread;
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ int32_t **txdata;
|
||||
|
||||
int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
|
||||
|
||||
static inline void saif_meas(int frame_rx, int subframe_rx) {
|
||||
static inline void saif_meas(unsigned int frame_rx, unsigned int subframe_rx) {
|
||||
static latency_stat_t __thread latency_stat;
|
||||
static struct timespec __thread last= {0};
|
||||
struct timespec now;
|
||||
@@ -238,7 +238,7 @@ static inline void saif_meas(int frame_rx, int subframe_rx) {
|
||||
if ( (diffTime>=1500) || ( !(frame_rx%1024) && subframe_rx == 0 ) ) {
|
||||
time_t current=time(NULL);
|
||||
printf("\n");
|
||||
printf("%.2f Period stats cnt=%7.7ld 0.. 250=%7.7ld 250.. 500=%7.7ld 500.. 600=%7.7ld 600.. 700=%7.7ld 700.. 800=%7.7ld - (frame_rx=%d) - %s",
|
||||
printf("%.2f Period stats cnt=%7.7ld 0.. 250=%7.7ld 250.. 500=%7.7ld 500.. 600=%7.7ld 600.. 700=%7.7ld 700.. 800=%7.7ld - (frame_rx=%u) - %s",
|
||||
now.tv_sec+(double)now.tv_nsec/1e9,
|
||||
latency_stat.counter,
|
||||
latency_stat.stat250, latency_stat.stat500,
|
||||
@@ -246,7 +246,7 @@ static inline void saif_meas(int frame_rx, int subframe_rx) {
|
||||
latency_stat.stat800,
|
||||
frame_rx,
|
||||
ctime(¤t));
|
||||
printf("%.2f Period stats cnt=%7.7ld 800.. 880=%7.7ld 880.. 960=%7.7ld 960..1040=%7.7ld 1040..1120=%7.7ld 1120..1200=%7.7ld - (frame_rx=%d) - %s",
|
||||
printf("%.2f Period stats cnt=%7.7ld 800.. 880=%7.7ld 880.. 960=%7.7ld 960..1040=%7.7ld 1040..1120=%7.7ld 1120..1200=%7.7ld - (frame_rx=%u) - %s",
|
||||
now.tv_sec+(double)now.tv_nsec/1e9,
|
||||
latency_stat.counter,
|
||||
latency_stat.stat880, latency_stat.stat960,
|
||||
@@ -254,7 +254,7 @@ static inline void saif_meas(int frame_rx, int subframe_rx) {
|
||||
latency_stat.stat1200,
|
||||
frame_rx,
|
||||
ctime(¤t));
|
||||
printf("%.2f Period stats cnt=%7.7ld 1200..1300=%7.7ld 1300..1500=%7.7ld 1500..2000=%7.7ld 2000..2500=%7.7ld >3000=%7.7ld - (frame_rx=%d) - %s",
|
||||
printf("%.2f Period stats cnt=%7.7ld 1200..1300=%7.7ld 1300..1500=%7.7ld 1500..2000=%7.7ld 2000..2500=%7.7ld >3000=%7.7ld - (frame_rx=%u) - %s",
|
||||
now.tv_sec+(double)now.tv_nsec/1e9,
|
||||
latency_stat.counter,
|
||||
latency_stat.stat1300, latency_stat.stat1500,
|
||||
@@ -326,7 +326,7 @@ int main(void)
|
||||
openair0_device rf_device;
|
||||
openair0_timestamp timestamp = 0;
|
||||
|
||||
int sub_frame = 0;
|
||||
unsigned int sub_frame = 0;
|
||||
unsigned int frame_rx = 0;
|
||||
|
||||
unsigned int nb_antennas_tx = 1;
|
||||
@@ -922,7 +922,7 @@ int main(void)
|
||||
|
||||
rxp[0] = (void*)&rxdata[0][sub_frame*nb_sample_per_tti];
|
||||
|
||||
readBlockSize = rf_device.trx_read_func( &rf_device,
|
||||
readBlockSize = rf_device.trx_read_func(&rf_device,
|
||||
×tamp,
|
||||
rxp,
|
||||
nb_sample_per_tti,
|
||||
|
||||
@@ -670,7 +670,7 @@ void *UE_thread(void *arg) {
|
||||
{
|
||||
proc = rxtx_proc[i];
|
||||
pthread_getname_np(proc->pthread_rxtx,threadname,128 );
|
||||
printf("RxTX Thread unlock latency on thread %s (it. %ld) (us) : max=%8.3f - mean=%8.3f - min=%8.3f\n",
|
||||
printf("RxTX Thread unlock latency on thread %s (it. %lu) (us) : max=%8.3f - mean=%8.3f - min=%8.3f\n",
|
||||
threadname,
|
||||
proc->syr_rdtsc_rxtx_th_unlock_iteration,
|
||||
proc->syr_rdtsc_rxtx_th_unlock_max,
|
||||
@@ -1192,9 +1192,9 @@ void histogram_save_in_csv( histo_time_t *histo , char *file_sufix)
|
||||
|
||||
for ( i = 0; i < HISTOGRAM_SIZE; i++ ) {
|
||||
if ( i + 1 == HISTOGRAM_SIZE )
|
||||
fprintf( fp, "%u+;%u\n", min_val, histo[i].count );
|
||||
fprintf( fp, "%d+;%u\n", min_val, histo[i].count );
|
||||
else
|
||||
fprintf( fp, "%u-%.0f;%u\n", min_val, histo[i].max, histo[i].count );
|
||||
fprintf( fp, "%d-%.0f;%u\n", min_val, histo[i].max, histo[i].count );
|
||||
min_val = histo[i].max;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,10 +50,6 @@
|
||||
|
||||
#include "assertions.h"
|
||||
#include "msc.h"
|
||||
|
||||
#include "../../ARCH/COMMON/common_lib.h"
|
||||
#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
|
||||
|
||||
#include "PHY/defs_common.h"
|
||||
#include "PHY/phy_extern.h"
|
||||
#include "PHY/types.h"
|
||||
@@ -64,7 +60,6 @@
|
||||
#include "PHY/LTE_TRANSPORT/if5_tools.h"
|
||||
#include "PHY/LTE_TRANSPORT/transport_proto.h"
|
||||
#include "PHY_INTERFACE/phy_interface.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "LAYER2/MAC/mac.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "LAYER2/MAC/mac_proto.h"
|
||||
@@ -78,6 +73,8 @@
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "enb_config.h"
|
||||
#include "targets/ARCH/COMMON/common_lib.h"
|
||||
#include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
|
||||
#include "targets/RT/USER/lte-softmodem.h"
|
||||
//#include "PHY/TOOLS/time_meas.h"
|
||||
|
||||
@@ -95,7 +92,6 @@ static int DEFENBS[] = {0};
|
||||
#include "s1ap_eNB.h"
|
||||
#include "SIMULATION/ETH_TRANSPORT/proto.h"
|
||||
|
||||
|
||||
#include "T.h"
|
||||
|
||||
#include "pdcp.h"
|
||||
@@ -104,9 +100,9 @@ extern volatile int oai_exit;
|
||||
extern int emulate_rf;
|
||||
extern int numerology;
|
||||
extern clock_source_t clock_source;
|
||||
|
||||
extern PARALLEL_CONF_t get_thread_parallel_conf(void);
|
||||
extern WORKER_CONF_t get_thread_worker_conf(void);
|
||||
#include "executables/thread-common.h"
|
||||
//extern PARALLEL_CONF_t get_thread_parallel_conf(void);
|
||||
//extern WORKER_CONF_t get_thread_worker_conf(void);
|
||||
extern void phy_init_RU(RU_t *);
|
||||
|
||||
void stop_RU(int nb_ru);
|
||||
|
||||
@@ -34,11 +34,11 @@
|
||||
#include "UTIL/OPT/opt.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
#include "executables/thread-common.h"
|
||||
#include <dlfcn.h>
|
||||
static softmodem_params_t softmodem_params;
|
||||
char *parallel_config=NULL;
|
||||
char *worker_config=NULL;
|
||||
double snr_dB=25;
|
||||
|
||||
uint64_t get_softmodem_optmask(void) {
|
||||
return softmodem_params.optmask;
|
||||
@@ -56,14 +56,10 @@ softmodem_params_t *get_softmodem_params(void) {
|
||||
void get_common_options(void) {
|
||||
uint32_t online_log_messages;
|
||||
uint32_t glog_level ;
|
||||
uint32_t start_telnetsrv;
|
||||
uint32_t noS1;
|
||||
uint32_t nokrnmod;
|
||||
uint32_t nonbiot;
|
||||
uint32_t rfsim;
|
||||
uint32_t basicsim;
|
||||
uint32_t start_telnetsrv = 0;
|
||||
uint32_t noS1 = 0, nokrnmod = 0, nonbiot = 0;
|
||||
uint32_t rfsim = 0, basicsim = 0, do_forms = 0;
|
||||
char *logmem_filename = NULL;
|
||||
uint32_t do_forms;
|
||||
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
|
||||
paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
|
||||
checkedparam_t cmdline_log_CheckParams[] = CMDLINE_LOGPARAMS_CHECK_DESC;
|
||||
|
||||
+36
-120
@@ -20,8 +20,7 @@
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#include "threads_t.h"
|
||||
#include "rt_wrapper.h"
|
||||
#include "../../ARCH/COMMON/common_lib.h"
|
||||
//#undef MALLOC
|
||||
@@ -30,12 +29,11 @@
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_eNB.h"
|
||||
#include "PHY/defs_UE.h"
|
||||
#include "SIMULATION/ETH_TRANSPORT/proto.h"
|
||||
|
||||
#include "flexran_agent.h"
|
||||
#include "s1ap_eNB.h"
|
||||
#include "SIMULATION/ETH_TRANSPORT/proto.h"
|
||||
#include "proto_agent.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
|
||||
/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
|
||||
#define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n"
|
||||
@@ -78,7 +76,6 @@
|
||||
#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n"
|
||||
#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n"
|
||||
#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n"
|
||||
#define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n"
|
||||
#define CONFIG_HLP_UE "Set the lte softmodem as a UE\n"
|
||||
#define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n"
|
||||
#define CONFIG_HLP_TPORT "tracer port\n"
|
||||
@@ -169,10 +166,10 @@
|
||||
|
||||
#define DEFAULT_DLF 2680000000
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters common to eNodeB and UE */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters common to eNodeB and UE */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define RF_CONFIG_FILE softmodem_params.rf_config_file
|
||||
#define PHY_TEST softmodem_params.phy_test
|
||||
#define WAIT_FOR_SYNC softmodem_params.wait_for_sync
|
||||
@@ -185,28 +182,27 @@
|
||||
#define SEND_DMRSSYNC softmodem_params.send_dmrs_sync
|
||||
#define USIM_TEST softmodem_params.usim_test
|
||||
#define CMDLINE_PARAMS_DESC { \
|
||||
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\
|
||||
{"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \
|
||||
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \
|
||||
{"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \
|
||||
{"clock", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \
|
||||
{"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&WAIT_FOR_SYNC, defintval:0, TYPE_INT, 0}, \
|
||||
{"single-thread-enable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&SINGLE_THREAD_FLAG, defintval:0, TYPE_INT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:2680000000, TYPE_UINT, 0}, \
|
||||
{"a" , CONFIG_HLP_CHOFF, 0, iptr:&CHAIN_OFFSET, defintval:0, TYPE_INT, 0}, \
|
||||
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
|
||||
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
|
||||
{"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \
|
||||
{"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \
|
||||
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \
|
||||
{"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&EMULATE_RF, defintval:0, TYPE_INT, 0}, \
|
||||
{"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \
|
||||
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
|
||||
{"noS1", CONFIG_HLP_NOS1, PARAMFLAG_BOOL, uptr:&noS1, defintval:0, TYPE_INT, 0}, \
|
||||
{"rfsim", CONFIG_HLP_RFSIM, PARAMFLAG_BOOL, uptr:&rfsim, defintval:0, TYPE_INT, 0}, \
|
||||
{"basicsim", CONFIG_HLP_RFSIM, PARAMFLAG_BOOL, uptr:&basicsim, defintval:0, TYPE_INT, 0}, \
|
||||
{"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \
|
||||
{"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \
|
||||
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\
|
||||
{"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \
|
||||
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \
|
||||
{"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \
|
||||
{"clock", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \
|
||||
{"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&WAIT_FOR_SYNC, defintval:0, TYPE_INT, 0}, \
|
||||
{"single-thread-enable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&SINGLE_THREAD_FLAG, defintval:0, TYPE_INT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:2680000000, TYPE_UINT, 0}, \
|
||||
{"a" , CONFIG_HLP_CHOFF, 0, iptr:&CHAIN_OFFSET, defintval:0, TYPE_INT, 0}, \
|
||||
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
|
||||
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
|
||||
{"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \
|
||||
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \
|
||||
{"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&EMULATE_RF, defintval:0, TYPE_INT, 0}, \
|
||||
{"parallel-config", CONFIG_HLP_PARALLEL_CMD, 0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \
|
||||
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
|
||||
{"noS1", CONFIG_HLP_NOS1, PARAMFLAG_BOOL, uptr:&noS1, defintval:0, TYPE_INT, 0}, \
|
||||
{"rfsim", CONFIG_HLP_RFSIM, PARAMFLAG_BOOL, uptr:&rfsim, defintval:0, TYPE_INT, 0}, \
|
||||
{"basicsim", CONFIG_HLP_RFSIM, PARAMFLAG_BOOL, uptr:&basicsim, defintval:0, TYPE_INT, 0}, \
|
||||
{"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \
|
||||
{"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \
|
||||
}
|
||||
|
||||
#define CONFIG_HLP_FLOG "Enable online log \n"
|
||||
@@ -242,51 +238,6 @@
|
||||
}
|
||||
|
||||
/***************************************************************************************************************************************/
|
||||
/* */
|
||||
#include "threads_t.h"
|
||||
//extern threads_t threads;
|
||||
|
||||
//extern THREAD_STRUCT thread_struct;
|
||||
THREAD_STRUCT thread_struct;
|
||||
|
||||
static inline void set_parallel_conf(char *parallel_conf) {
|
||||
mapping config[]= {
|
||||
FOREACH_PARALLEL(GENERATE_ENUMTXT)
|
||||
{NULL,-1}
|
||||
};
|
||||
thread_struct.parallel_conf = (PARALLEL_CONF_t)map_str_to_int(config, parallel_conf);
|
||||
if (thread_struct.parallel_conf == -1 ) {
|
||||
LOG_E(ENB_APP,"Impossible value: %s\n", parallel_conf);
|
||||
thread_struct.parallel_conf = PARALLEL_SINGLE_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_worker_conf(char *worker_conf) {
|
||||
mapping config[]={
|
||||
FOREACH_WORKER(GENERATE_ENUMTXT)
|
||||
{NULL, -1}
|
||||
};
|
||||
thread_struct.worker_conf = (WORKER_CONF_t)map_str_to_int(config, worker_conf);
|
||||
if (thread_struct.worker_conf == -1 ) {
|
||||
LOG_E(ENB_APP,"Impossible value: %s\n", worker_conf);
|
||||
thread_struct.worker_conf = WORKER_DISABLE ;
|
||||
}
|
||||
}
|
||||
|
||||
static inline PARALLEL_CONF_t get_thread_parallel_conf(void) {
|
||||
return thread_struct.parallel_conf;
|
||||
}
|
||||
|
||||
static inline WORKER_CONF_t get_thread_worker_conf(void) {
|
||||
return thread_struct.worker_conf;
|
||||
}
|
||||
|
||||
/*PARALLEL_CONF_t get_thread_parallel_conf(void);
|
||||
WORKER_CONF_t get_thread_worker_conf(void);
|
||||
void set_parallel_conf(char *parallel_conf);
|
||||
void set_worker_conf(char *worker_conf);
|
||||
*/
|
||||
|
||||
|
||||
#define SOFTMODEM_NOS1_BIT (1<<0)
|
||||
#define SOFTMODEM_NOKRNMOD_BIT (1<<1)
|
||||
@@ -295,23 +246,6 @@ void set_worker_conf(char *worker_conf);
|
||||
#define SOFTMODEM_BASICSIM_BIT (1<<11)
|
||||
#define SOFTMODEM_SIML1_BIT (1<<12)
|
||||
#define SOFTMODEM_DOFORMS_BIT (1<<15)
|
||||
typedef struct {
|
||||
uint64_t optmask;
|
||||
THREAD_STRUCT thread_struct;
|
||||
char rf_config_file[1024];
|
||||
int phy_test;
|
||||
uint8_t usim_test;
|
||||
int emulate_rf;
|
||||
int wait_for_sync; //eNodeB only
|
||||
int single_thread_flag; //eNodeB only
|
||||
int chain_offset;
|
||||
int numerology;
|
||||
unsigned int start_msc;
|
||||
uint32_t clock_source;
|
||||
uint32_t timing_source;
|
||||
int hw_timing_advance;
|
||||
uint32_t send_dmrs_sync;
|
||||
} softmodem_params_t;
|
||||
|
||||
#define IS_SOFTMODEM_NOS1 ( get_softmodem_optmask() & SOFTMODEM_NOS1_BIT)
|
||||
#define IS_SOFTMODEM_NOKRNMOD ( get_softmodem_optmask() & SOFTMODEM_NOKRNMOD_BIT)
|
||||
@@ -329,7 +263,6 @@ uint64_t get_pdcp_optmask(void);
|
||||
extern pthread_cond_t sync_cond;
|
||||
extern pthread_mutex_t sync_mutex;
|
||||
extern int sync_var;
|
||||
extern double snr_dB;
|
||||
|
||||
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
@@ -339,7 +272,7 @@ extern uint8_t exit_missed_slots;
|
||||
extern uint64_t num_missed_slots; // counter for the number of missed slots
|
||||
|
||||
extern int oaisim_flag;
|
||||
extern volatile int oai_exit;
|
||||
extern volatile int oai_exit;
|
||||
|
||||
extern openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
extern pthread_cond_t sync_cond;
|
||||
@@ -351,8 +284,7 @@ extern double cpuf;
|
||||
// In lte-enb.c
|
||||
extern void stop_eNB(int);
|
||||
extern void kill_eNB_proc(int inst);
|
||||
extern void init_eNB(int single_thread_flag,
|
||||
int wait_for_sync);
|
||||
extern void init_eNB(int single_thread_flag, int wait_for_sync);
|
||||
|
||||
// In lte-ru.c
|
||||
extern void stop_ru(RU_t *ru);
|
||||
@@ -361,15 +293,10 @@ extern void init_RU_proc(RU_t *ru);
|
||||
extern void stop_RU(int nb_ru);
|
||||
extern void kill_RU_proc(RU_t *ru);
|
||||
extern void set_function_spec_param(RU_t *ru);
|
||||
extern void init_RU(char*,
|
||||
clock_source_t clock_source,
|
||||
clock_source_t time_source,
|
||||
int send_dmrssync);
|
||||
extern void init_RU(char *, clock_source_t clock_source, clock_source_t time_source, int send_dmrssync);
|
||||
|
||||
// In lte-ue.c
|
||||
extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue,
|
||||
openair0_config_t *openair0_cfg);
|
||||
|
||||
extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
|
||||
extern void fill_ue_band_info(void);
|
||||
|
||||
extern void init_UE(int nb_inst,
|
||||
@@ -384,11 +311,7 @@ extern void init_UE(int nb_inst,
|
||||
int txpowermax,
|
||||
LTE_DL_FRAME_PARMS *fp);
|
||||
|
||||
extern void init_thread(int sched_runtime,
|
||||
int sched_deadline,
|
||||
int sched_fifo,
|
||||
cpu_set_t *cpuset,
|
||||
char *name);
|
||||
extern void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char *name);
|
||||
|
||||
extern void reset_opp_meas(void);
|
||||
extern void print_opp_meas(void);
|
||||
@@ -399,24 +322,17 @@ extern void kill_td_thread(PHY_VARS_eNB *);
|
||||
extern void kill_te_thread(PHY_VARS_eNB *);
|
||||
|
||||
extern void RCConfig_sim(void);
|
||||
extern void init_ocm(double,double);
|
||||
extern void init_ocm(void);
|
||||
extern void init_ue_devices(PHY_VARS_UE *);
|
||||
|
||||
PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t UE_id,
|
||||
uint8_t abstraction_flag);
|
||||
PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
|
||||
|
||||
void init_eNB_afterRU(void);
|
||||
extern int stop_L1L2(module_id_t enb_id);
|
||||
extern int restart_L1L2(module_id_t enb_id);
|
||||
|
||||
extern void init_UE_stub_single_thread(int nb_inst,
|
||||
int eMBMS_active,
|
||||
int uecap_xer_in,
|
||||
char *emul_iface);
|
||||
extern void init_UE_stub_single_thread(int nb_inst, int eMBMS_active, int uecap_xer_in, char *emul_iface);
|
||||
|
||||
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t UE_id,
|
||||
uint8_t abstraction_flag);
|
||||
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* \date 2012
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
|
||||
* \email: {knopp, florian.kaltenberger, navid.nikaein}@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
@@ -89,7 +89,6 @@
|
||||
#include "lte-softmodem.h"
|
||||
|
||||
|
||||
|
||||
/* temporary compilation wokaround (UE/eNB split */
|
||||
uint16_t sf_ahead;
|
||||
|
||||
@@ -173,14 +172,9 @@ static LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
|
||||
uint8_t exit_missed_slots=1;
|
||||
uint64_t num_missed_slots=0; // counter for the number of missed slots
|
||||
|
||||
/* prototypes from function implemented in lte-ue.c, probably should be elsewhere in a include
|
||||
file */
|
||||
// prototypes from function implemented in lte-ue.c, probably should be elsewhere in a include file.
|
||||
extern void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface);
|
||||
|
||||
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
|
||||
uint8_t UE_id,
|
||||
uint8_t abstraction_flag);
|
||||
|
||||
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
|
||||
extern void get_uethreads_params(void);
|
||||
|
||||
int transmission_mode=1;
|
||||
@@ -318,7 +312,6 @@ static void get_options(void) {
|
||||
int CC_id;
|
||||
int tddflag = 0;
|
||||
char *loopfile = NULL;
|
||||
|
||||
int dumpframe = 0;
|
||||
int timingadv = 0;
|
||||
uint8_t nfapi_mode = NFAPI_MONOLITHIC;
|
||||
@@ -592,7 +585,7 @@ int main( int argc, char **argv ) {
|
||||
if (config_mod == NULL) {
|
||||
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
|
||||
}
|
||||
|
||||
|
||||
mode = normal_txrx;
|
||||
memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
|
||||
set_latency_target();
|
||||
@@ -792,7 +785,7 @@ int main( int argc, char **argv ) {
|
||||
//p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
|
||||
|
||||
if (IS_SOFTMODEM_SIML1 ) {
|
||||
init_ocm(snr_dB,0);
|
||||
init_ocm();
|
||||
PHY_vars_UE_g[0][0]->no_timing_correction = 1;
|
||||
}
|
||||
|
||||
|
||||
+172
-224
@@ -64,65 +64,52 @@ sim_t sim;
|
||||
|
||||
void init_ru_devices(void);
|
||||
|
||||
void init_RU(char*,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync);
|
||||
void init_RU(char *,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync);
|
||||
|
||||
void *rfsim_top(void *n_frames);
|
||||
|
||||
void wait_RUs(void)
|
||||
{
|
||||
void wait_RUs(void) {
|
||||
int i;
|
||||
|
||||
// wait for all RUs to be configured over fronthaul
|
||||
pthread_mutex_lock(&RC.ru_mutex);
|
||||
|
||||
|
||||
while (RC.ru_mask>0) {
|
||||
pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_unlock(&RC.ru_mutex);
|
||||
|
||||
// copy frame parameters from RU to UEs
|
||||
for (i=0;i<NB_UE_INST;i++) {
|
||||
for (i=0; i<NB_UE_INST; i++) {
|
||||
sim.current_UE_rx_timestamp[i][0] = RC.ru[0]->frame_parms->samples_per_tti + RC.ru[0]->frame_parms->ofdm_symbol_size + RC.ru[0]->frame_parms->nb_prefix_samples0;
|
||||
|
||||
}
|
||||
|
||||
for (int ru_id=0;ru_id<RC.nb_RU;ru_id++) sim.current_ru_rx_timestamp[ru_id][0] = RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) sim.current_ru_rx_timestamp[ru_id][0] = RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
|
||||
printf("RUs are ready, let's go\n");
|
||||
}
|
||||
|
||||
void wait_eNBs(void)
|
||||
{
|
||||
void wait_eNBs(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void RCConfig_sim(void) {
|
||||
|
||||
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
|
||||
|
||||
// Get num RU instances
|
||||
config_getlist( &RUParamList,NULL,0, NULL);
|
||||
RC.nb_RU = RUParamList.numelt;
|
||||
|
||||
AssertFatal(RC.nb_RU>0,"we need at least 1 RU for simulation\n");
|
||||
printf("returned with %d rus\n",RC.nb_RU);
|
||||
|
||||
init_RU(NULL,internal,internal,0);
|
||||
|
||||
printf("Waiting for RUs to get set up\n");
|
||||
printf("Waiting for RUs to get set up\n");
|
||||
wait_RUs();
|
||||
|
||||
init_ru_devices();
|
||||
|
||||
static int nframes = 100000;
|
||||
|
||||
AssertFatal(0 == pthread_create(&sim.rfsim_thread,
|
||||
NULL,
|
||||
rfsim_top,
|
||||
(void*)&nframes), "");
|
||||
|
||||
(void *)&nframes), "");
|
||||
}
|
||||
|
||||
|
||||
@@ -165,75 +152,65 @@ extern int subframe_ru_mask,subframe_UE_mask;
|
||||
|
||||
|
||||
int ru_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
|
||||
|
||||
int ru_id = device->Mod_id;
|
||||
int CC_id = device->CC_id;
|
||||
|
||||
int subframe;
|
||||
int sample_count=0;
|
||||
|
||||
*ptimestamp = sim.last_ru_rx_timestamp[ru_id][CC_id];
|
||||
|
||||
|
||||
LOG_D(SIM,"RU_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps,
|
||||
(unsigned long long)sim.current_ru_rx_timestamp[ru_id][CC_id],
|
||||
(unsigned long long)sim.last_ru_rx_timestamp[ru_id][CC_id],
|
||||
(int)((*ptimestamp/RC.ru[ru_id]->frame_parms->samples_per_tti)%10));
|
||||
(int)((*ptimestamp/RC.ru[ru_id]->frame_parms->samples_per_tti)%10));
|
||||
|
||||
// if we're at a subframe boundary generate UL signals for this ru
|
||||
|
||||
while (sample_count<nsamps) {
|
||||
while (sim.current_ru_rx_timestamp[ru_id][CC_id]<
|
||||
(nsamps+sim.last_ru_rx_timestamp[ru_id][CC_id])) {
|
||||
(nsamps+sim.last_ru_rx_timestamp[ru_id][CC_id])) {
|
||||
LOG_D(SIM,"RU: current TS %"PRIi64", last TS %"PRIi64", sleeping\n",sim.current_ru_rx_timestamp[ru_id][CC_id],sim.last_ru_rx_timestamp[ru_id][CC_id]);
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
|
||||
|
||||
subframe = (sim.last_ru_rx_timestamp[ru_id][CC_id]/RC.ru[ru_id]->frame_parms->samples_per_tti)%10;
|
||||
|
||||
if (subframe_select(RC.ru[ru_id]->frame_parms,subframe) != SF_DL || RC.ru[ru_id]->frame_parms->frame_type == FDD) {
|
||||
LOG_D(SIM,"RU_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
|
||||
subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)sim.current_ru_rx_timestamp[ru_id][CC_id]);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,1);
|
||||
subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)sim.current_ru_rx_timestamp[ru_id][CC_id]);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,1);
|
||||
do_UL_sig(&sim,
|
||||
subframe,
|
||||
0, // abstraction_flag
|
||||
RC.ru[ru_id]->frame_parms,
|
||||
0, // frame is only used for abstraction
|
||||
ru_id,
|
||||
CC_id);
|
||||
subframe,
|
||||
0, // abstraction_flag
|
||||
RC.ru[ru_id]->frame_parms,
|
||||
0, // frame is only used for abstraction
|
||||
ru_id,
|
||||
CC_id);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,0);
|
||||
}
|
||||
|
||||
sim.last_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
sample_count += RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
}
|
||||
|
||||
|
||||
return(nsamps);
|
||||
}
|
||||
|
||||
int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
|
||||
{
|
||||
int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,1);
|
||||
int UE_id = device->Mod_id;
|
||||
int CC_id = device->CC_id;
|
||||
|
||||
int subframe;
|
||||
int sample_count=0;
|
||||
int read_size;
|
||||
int sptti = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;
|
||||
|
||||
*ptimestamp = sim.last_UE_rx_timestamp[UE_id][CC_id];
|
||||
|
||||
LOG_D(PHY,"UE %d DL simulation 0: UE_trx_read nsamps %d TS %llu (%llu, offset %d) antenna %d\n",
|
||||
UE_id,
|
||||
nsamps,
|
||||
(unsigned long long)sim.current_UE_rx_timestamp[UE_id][CC_id],
|
||||
(unsigned long long)sim.last_UE_rx_timestamp[UE_id][CC_id],
|
||||
(int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti),
|
||||
cc);
|
||||
|
||||
cc);
|
||||
|
||||
if (nsamps < sptti)
|
||||
read_size = nsamps;
|
||||
@@ -242,49 +219,43 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
|
||||
|
||||
while (sample_count<nsamps) {
|
||||
LOG_D(SIM,"UE %d: DL simulation 1: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
|
||||
while (sim.current_UE_rx_timestamp[UE_id][CC_id] <
|
||||
(sim.last_UE_rx_timestamp[UE_id][CC_id]+read_size)) {
|
||||
|
||||
while (sim.current_UE_rx_timestamp[UE_id][CC_id] <
|
||||
(sim.last_UE_rx_timestamp[UE_id][CC_id]+read_size)) {
|
||||
LOG_D(SIM,"UE %d: DL simulation 2: UE_trx_read : current TS %"PRIi64", last TS %"PRIi64", sleeping\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
|
||||
usleep(500);
|
||||
}
|
||||
LOG_D(SIM,"UE %d: DL simulation 3: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
|
||||
|
||||
LOG_D(SIM,"UE %d: DL simulation 3: UE_trx_read : current TS now %"PRIi64", last TS %"PRIi64"\n",UE_id,sim.current_UE_rx_timestamp[UE_id][CC_id],sim.last_UE_rx_timestamp[UE_id][CC_id]);
|
||||
// if we cross a subframe-boundary
|
||||
subframe = (sim.last_UE_rx_timestamp[UE_id][CC_id]/sptti)%10;
|
||||
|
||||
// tell top-level we are busy
|
||||
// tell top-level we are busy
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
sim.subframe_UE_mask|=(1<<UE_id);
|
||||
LOG_D(SIM,"Setting UE_id %d mask to busy (%d)\n",UE_id,sim.subframe_UE_mask);
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
|
||||
|
||||
|
||||
LOG_D(PHY,"UE %d: DL simulation 4: UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu,nsamps %d)\n",
|
||||
UE_id,subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)sim.current_UE_rx_timestamp[UE_id][CC_id],
|
||||
nsamps);
|
||||
|
||||
UE_id,subframe,(unsigned long long)*ptimestamp,
|
||||
(unsigned long long)sim.current_UE_rx_timestamp[UE_id][CC_id],
|
||||
nsamps);
|
||||
LOG_D(SIM,"UE %d: DL simulation 5: Doing DL simulation for %d samples starting in subframe %d at offset %d\n",
|
||||
UE_id,nsamps,subframe,
|
||||
(int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti));
|
||||
|
||||
UE_id,nsamps,subframe,
|
||||
(int)(sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti));
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_DL_SIGNAL,1);
|
||||
do_DL_sig(&sim,
|
||||
subframe,
|
||||
sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti,
|
||||
sptti,
|
||||
0, //abstraction_flag,
|
||||
&PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
|
||||
UE_id,
|
||||
CC_id);
|
||||
subframe,
|
||||
sim.last_UE_rx_timestamp[UE_id][CC_id]%sptti,
|
||||
sptti,
|
||||
0, //abstraction_flag,
|
||||
&PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
|
||||
UE_id,
|
||||
CC_id);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_DL_SIGNAL,0);
|
||||
LOG_D(PHY,"UE %d: DL simulation 6: UE_trx_read @ TS %"PRIi64" (%"PRIi64")=> frame %d, subframe %d\n",
|
||||
UE_id, sim.current_UE_rx_timestamp[UE_id][CC_id],
|
||||
sim.last_UE_rx_timestamp[UE_id][CC_id],
|
||||
(int)((sim.last_UE_rx_timestamp[UE_id][CC_id]/(sptti*10))&1023),
|
||||
subframe);
|
||||
|
||||
UE_id, sim.current_UE_rx_timestamp[UE_id][CC_id],
|
||||
sim.last_UE_rx_timestamp[UE_id][CC_id],
|
||||
(int)((sim.last_UE_rx_timestamp[UE_id][CC_id]/(sptti*10))&1023),
|
||||
subframe);
|
||||
sim.last_UE_rx_timestamp[UE_id][CC_id] += read_size;
|
||||
sample_count += read_size;
|
||||
}
|
||||
@@ -295,245 +266,222 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
|
||||
|
||||
|
||||
int ru_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
|
||||
|
||||
int ru_id = device->Mod_id;
|
||||
|
||||
LTE_DL_FRAME_PARMS *frame_parms = RC.ru[ru_id]->frame_parms;
|
||||
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
LOG_D(SIM,"[TXPATH] ru_trx_write: RU %d mask %d\n",ru_id,sim.subframe_ru_mask);
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
// compute amplitude of TX signal from first symbol in subframe
|
||||
// note: assumes that the packet is an entire subframe
|
||||
|
||||
// note: assumes that the packet is an entire subframe
|
||||
sim.ru_amp[ru_id] = 0;
|
||||
for (int aa=0; aa<RC.ru[ru_id]->nb_tx; aa++) {
|
||||
sim.ru_amp[ru_id] += (double)signal_energy((int32_t*)buff[aa],frame_parms->ofdm_symbol_size)/(12*frame_parms->N_RB_DL);
|
||||
}
|
||||
sim.ru_amp[ru_id] = sqrt(sim.ru_amp[ru_id]);
|
||||
|
||||
LOG_D(PHY,"Setting amp for RU %d to %f (%d)\n",ru_id,sim.ru_amp[ru_id], dB_fixed((double)signal_energy((int32_t*)buff[0],frame_parms->ofdm_symbol_size)));
|
||||
for (int aa=0; aa<RC.ru[ru_id]->nb_tx; aa++) {
|
||||
sim.ru_amp[ru_id] += (double)signal_energy((int32_t *)buff[aa],frame_parms->ofdm_symbol_size)/(12*frame_parms->N_RB_DL);
|
||||
}
|
||||
|
||||
sim.ru_amp[ru_id] = sqrt(sim.ru_amp[ru_id]);
|
||||
LOG_D(PHY,"Setting amp for RU %d to %f (%d)\n",ru_id,sim.ru_amp[ru_id], dB_fixed((double)signal_energy((int32_t *)buff[0],frame_parms->ofdm_symbol_size)));
|
||||
// tell top-level we are done
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
sim.subframe_ru_mask|=(1<<ru_id);
|
||||
LOG_D(SIM,"Setting RU %d to busy\n",ru_id);
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
|
||||
return(nsamps);
|
||||
}
|
||||
|
||||
int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
|
||||
|
||||
return(nsamps);
|
||||
}
|
||||
|
||||
void init_ru_devices(){
|
||||
|
||||
|
||||
void init_ru_devices() {
|
||||
module_id_t ru_id;
|
||||
RU_t *ru;
|
||||
|
||||
// allocate memory for RU if not already done
|
||||
if (RC.ru==NULL) RC.ru = (RU_t**)malloc(RC.nb_RU*sizeof(RU_t*));
|
||||
if (RC.ru==NULL) RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *));
|
||||
|
||||
for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
|
||||
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
LOG_D(SIM,"Initiaizing rfdevice for RU %d\n",ru_id);
|
||||
if (RC.ru[ru_id]==NULL) RC.ru[ru_id] = (RU_t*)malloc(sizeof(RU_t));
|
||||
ru = RC.ru[ru_id];
|
||||
ru->rfdevice.Mod_id = ru_id;
|
||||
ru->rfdevice.CC_id = 0;
|
||||
ru->rfdevice.trx_start_func = ru_trx_start;
|
||||
ru->rfdevice.trx_read_func = ru_trx_read;
|
||||
ru->rfdevice.trx_write_func = ru_trx_write;
|
||||
ru->rfdevice.trx_end_func = ru_trx_end;
|
||||
ru->rfdevice.trx_stop_func = ru_trx_stop;
|
||||
ru->rfdevice.trx_set_freq_func = ru_trx_set_freq;
|
||||
ru->rfdevice.trx_set_gains_func = ru_trx_set_gains;
|
||||
sim.last_ru_rx_timestamp[ru_id][0] = 0;
|
||||
|
||||
if (RC.ru[ru_id]==NULL) RC.ru[ru_id] = (RU_t *)malloc(sizeof(RU_t));
|
||||
|
||||
ru = RC.ru[ru_id];
|
||||
ru->rfdevice.Mod_id = ru_id;
|
||||
ru->rfdevice.CC_id = 0;
|
||||
ru->rfdevice.trx_start_func = ru_trx_start;
|
||||
ru->rfdevice.trx_read_func = ru_trx_read;
|
||||
ru->rfdevice.trx_write_func = ru_trx_write;
|
||||
ru->rfdevice.trx_end_func = ru_trx_end;
|
||||
ru->rfdevice.trx_stop_func = ru_trx_stop;
|
||||
ru->rfdevice.trx_set_freq_func = ru_trx_set_freq;
|
||||
ru->rfdevice.trx_set_gains_func = ru_trx_set_gains;
|
||||
sim.last_ru_rx_timestamp[ru_id][0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void init_ue_devices(PHY_VARS_UE *UE) {
|
||||
|
||||
AssertFatal(UE!=NULL,"UE context is not allocated\n");
|
||||
printf("Initializing UE %d.%d\n",UE->Mod_id,UE->CC_id);
|
||||
UE->rfdevice.Mod_id = UE->Mod_id;
|
||||
UE->rfdevice.CC_id = UE->CC_id;
|
||||
UE->rfdevice.trx_start_func = UE_trx_start;
|
||||
UE->rfdevice.trx_read_func = UE_trx_read;
|
||||
UE->rfdevice.trx_write_func = UE_trx_write;
|
||||
UE->rfdevice.trx_end_func = UE_trx_end;
|
||||
UE->rfdevice.trx_stop_func = UE_trx_stop;
|
||||
UE->rfdevice.trx_set_freq_func = UE_trx_set_freq;
|
||||
UE->rfdevice.trx_set_gains_func = UE_trx_set_gains;
|
||||
sim.last_UE_rx_timestamp[UE->Mod_id][UE->CC_id] = 0;
|
||||
AssertFatal(UE!=NULL,"UE context is not allocated\n");
|
||||
printf("Initializing UE %d.%d\n",UE->Mod_id,UE->CC_id);
|
||||
UE->rfdevice.Mod_id = UE->Mod_id;
|
||||
UE->rfdevice.CC_id = UE->CC_id;
|
||||
UE->rfdevice.trx_start_func = UE_trx_start;
|
||||
UE->rfdevice.trx_read_func = UE_trx_read;
|
||||
UE->rfdevice.trx_write_func = UE_trx_write;
|
||||
UE->rfdevice.trx_end_func = UE_trx_end;
|
||||
UE->rfdevice.trx_stop_func = UE_trx_stop;
|
||||
UE->rfdevice.trx_set_freq_func = UE_trx_set_freq;
|
||||
UE->rfdevice.trx_set_gains_func = UE_trx_set_gains;
|
||||
sim.last_UE_rx_timestamp[UE->Mod_id][UE->CC_id] = 0;
|
||||
}
|
||||
|
||||
void init_ocm(double snr_dB,double sinr_dB)
|
||||
{
|
||||
void init_ocm(void) {
|
||||
module_id_t UE_id, ru_id;
|
||||
int CC_id;
|
||||
|
||||
randominit(0);
|
||||
set_taus_seed(0);
|
||||
|
||||
|
||||
init_channelmod();
|
||||
double snr_dB = channelmod_get_snr_dB();
|
||||
double sinr_dB = channelmod_get_sinr_dB();
|
||||
init_channel_vars ();//fp, &s_re, &s_im, &r_re, &r_im, &r_re0, &r_im0);
|
||||
|
||||
// initialize channel descriptors
|
||||
LOG_I(PHY,"Initializing channel descriptors (nb_RU %d, nb_UE %d)\n",RC.nb_RU,NB_UE_INST);
|
||||
|
||||
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
|
||||
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
|
||||
LOG_I(PHY,"Initializing channel descriptors (RU %d, UE %d) for N_RB_DL %d\n",ru_id,UE_id,
|
||||
RC.ru[ru_id]->frame_parms->N_RB_DL);
|
||||
LOG_I(PHY,"Initializing channel descriptors (RU %d, UE %d) for N_RB_DL %d\n",ru_id,UE_id,
|
||||
RC.ru[ru_id]->frame_parms->N_RB_DL);
|
||||
sim.RU2UE[ru_id][UE_id][CC_id] =
|
||||
new_channel_desc_scm(RC.ru[ru_id]->nb_tx,
|
||||
PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_rx,
|
||||
AWGN,
|
||||
N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_DL),
|
||||
N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_DL),
|
||||
0.0,
|
||||
0,
|
||||
0);
|
||||
new_channel_desc_scm(RC.ru[ru_id]->nb_tx,
|
||||
PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_rx,
|
||||
AWGN,
|
||||
N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_DL),
|
||||
N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_DL),
|
||||
0.0,
|
||||
0,
|
||||
0);
|
||||
random_channel(sim.RU2UE[ru_id][UE_id][CC_id],0);
|
||||
LOG_D(OCM,"[SIM] Initializing channel (%s) from UE %d to ru %d\n", "AWGN",UE_id, ru_id);
|
||||
|
||||
|
||||
sim.UE2RU[UE_id][ru_id][CC_id] =
|
||||
new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx,
|
||||
RC.ru[ru_id]->nb_rx,
|
||||
AWGN,
|
||||
N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_UL),
|
||||
N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_UL),
|
||||
0.0,
|
||||
0,
|
||||
0);
|
||||
LOG_D(OCM,"[SIM] Initializing channel (%s) from UE %d to ru %d\n", "AWGN", UE_id, ru_id);
|
||||
|
||||
sim.UE2RU[UE_id][ru_id][CC_id] =
|
||||
new_channel_desc_scm(PHY_vars_UE_g[UE_id][CC_id]->frame_parms.nb_antennas_tx,
|
||||
RC.ru[ru_id]->nb_rx,
|
||||
AWGN,
|
||||
N_RB2sampling_rate(RC.ru[ru_id]->frame_parms->N_RB_UL),
|
||||
N_RB2channel_bandwidth(RC.ru[ru_id]->frame_parms->N_RB_UL),
|
||||
0.0,
|
||||
0,
|
||||
0);
|
||||
random_channel(sim.UE2RU[UE_id][ru_id][CC_id],0);
|
||||
|
||||
// to make channel reciprocal uncomment following line instead of previous. However this only works for SISO at the moment. For MIMO the channel would need to be transposed.
|
||||
//UE2RU[UE_id][ru_id] = RU2UE[ru_id][UE_id];
|
||||
AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
|
||||
AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
|
||||
|
||||
AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
|
||||
AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
|
||||
//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
|
||||
if (ru_id == (UE_id % RC.nb_RU)) {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
} else {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
}
|
||||
|
||||
LOG_I(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
|
||||
RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower,snr_dB);
|
||||
|
||||
//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
|
||||
if (ru_id == (UE_id % RC.nb_RU)) {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
} else {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
}
|
||||
|
||||
LOG_I(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
|
||||
RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower,
|
||||
snr_dB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void update_ocm(double snr_dB,double sinr_dB)
|
||||
{
|
||||
void update_ocm(double snr_dB,double sinr_dB) {
|
||||
module_id_t UE_id, ru_id;
|
||||
int CC_id;
|
||||
|
||||
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
|
||||
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
|
||||
AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
|
||||
|
||||
for (ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
|
||||
for (UE_id = 0; UE_id < NB_UE_INST; UE_id++) {
|
||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
|
||||
AssertFatal(sim.RU2UE[ru_id][UE_id][CC_id]!=NULL,"RU2UE[%d][%d][%d] is null\n",ru_id,UE_id,CC_id);
|
||||
AssertFatal(sim.UE2RU[UE_id][ru_id][CC_id]!=NULL,"UE2RU[%d][%d][%d] is null\n",UE_id,ru_id,CC_id);
|
||||
//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
|
||||
if (ru_id == (UE_id % RC.nb_RU)) {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
} else {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
}
|
||||
//pathloss: -132.24 dBm/15kHz RE + target SNR - eNB TX power per RE
|
||||
if (ru_id == (UE_id % RC.nb_RU)) {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + snr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
} else {
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
sim.UE2RU[UE_id][ru_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
}
|
||||
|
||||
LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
|
||||
RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower,snr_dB);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",ru_id,UE_id,CC_id,
|
||||
sim.RU2UE[ru_id][UE_id][CC_id]->path_loss_dB,
|
||||
RC.ru[ru_id]->frame_parms->pdsch_config_common.referenceSignalPower,
|
||||
snr_dB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void init_channel_vars(void)
|
||||
{
|
||||
|
||||
void init_channel_vars(void) {
|
||||
int i;
|
||||
|
||||
memset(sim.RU_output_mask,0,sizeof(int)*NUMBER_OF_UE_MAX);
|
||||
for (i=0;i<NB_UE_INST;i++)
|
||||
|
||||
for (i=0; i<NB_UE_INST; i++)
|
||||
pthread_mutex_init(&sim.RU_output_mutex[i],NULL);
|
||||
|
||||
memset(sim.UE_output_mask,0,sizeof(int)*NUMBER_OF_RU_MAX);
|
||||
for (i=0;i<RC.nb_RU;i++)
|
||||
pthread_mutex_init(&sim.UE_output_mutex[i],NULL);
|
||||
|
||||
for (i=0; i<RC.nb_RU; i++)
|
||||
pthread_mutex_init(&sim.UE_output_mutex[i],NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void *rfsim_top(void *n_frames) {
|
||||
|
||||
|
||||
wait_sync("rfsim_top");
|
||||
printf("Running rfsim with %d frames\n",*(int *)n_frames);
|
||||
|
||||
|
||||
printf("Running rfsim with %d frames\n",*(int*)n_frames);
|
||||
for (int frame = 0;
|
||||
frame < *(int*)n_frames;
|
||||
frame++) {
|
||||
|
||||
for (int frame = 0; frame < *(int *)n_frames; frame++) {
|
||||
for (int sf = 0; sf < 10; sf++) {
|
||||
int CC_id=0;
|
||||
int all_done=0;
|
||||
while (all_done==0) {
|
||||
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
|
||||
int subframe_ru_mask_local = (subframe_select(RC.ru[0]->frame_parms,(sf+4)%10)!=SF_UL) ? sim.subframe_ru_mask : ((1<<RC.nb_RU)-1);
|
||||
int subframe_UE_mask_local = (RC.ru[0]->frame_parms->frame_type == FDD || subframe_select(RC.ru[0]->frame_parms,(sf+4)%10)!=SF_DL) ? sim.subframe_UE_mask : ((1<<NB_UE_INST)-1);
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
LOG_D(SIM,"Frame %d, Subframe %d, NB_RU %d, NB_UE %d: Checking masks %x,%x\n",frame,sf,RC.nb_RU,NB_UE_INST,subframe_ru_mask_local,subframe_UE_mask_local);
|
||||
if ((subframe_ru_mask_local == ((1<<RC.nb_RU)-1)) &&
|
||||
(subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) all_done=1;
|
||||
else usleep(1500);
|
||||
while (all_done==0) {
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
int subframe_ru_mask_local = (subframe_select(RC.ru[0]->frame_parms,(sf+4)%10)!=SF_UL) ? sim.subframe_ru_mask : ((1<<RC.nb_RU)-1);
|
||||
int subframe_UE_mask_local = (RC.ru[0]->frame_parms->frame_type == FDD || subframe_select(RC.ru[0]->frame_parms,(sf+4)%10)!=SF_DL) ? sim.subframe_UE_mask : ((1<<NB_UE_INST)-1);
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
LOG_D(SIM,"Frame %d, Subframe %d, NB_RU %d, NB_UE %d: Checking masks %x,%x\n",frame,sf,RC.nb_RU,NB_UE_INST,subframe_ru_mask_local,subframe_UE_mask_local);
|
||||
|
||||
if ((subframe_ru_mask_local == ((1<<RC.nb_RU)-1)) &&
|
||||
(subframe_UE_mask_local == ((1<<NB_UE_INST)-1))) all_done=1;
|
||||
else usleep(1500);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//clear subframe masks for next round
|
||||
pthread_mutex_lock(&sim.subframe_mutex);
|
||||
sim.subframe_ru_mask=0;
|
||||
sim.subframe_UE_mask=0;
|
||||
pthread_mutex_unlock(&sim.subframe_mutex);
|
||||
|
||||
|
||||
// increment timestamps
|
||||
for (int ru_id=0;ru_id<RC.nb_RU;ru_id++) {
|
||||
sim.current_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
LOG_D(SIM,"RU %d/%d: TS %"PRIi64"\n",ru_id,CC_id,sim.current_ru_rx_timestamp[ru_id][CC_id]);
|
||||
|
||||
for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) {
|
||||
sim.current_ru_rx_timestamp[ru_id][CC_id] += RC.ru[ru_id]->frame_parms->samples_per_tti;
|
||||
LOG_D(SIM,"RU %d/%d: TS %"PRIi64"\n",ru_id,CC_id,sim.current_ru_rx_timestamp[ru_id][CC_id]);
|
||||
}
|
||||
for (int UE_inst = 0; UE_inst<NB_UE_INST;UE_inst++) {
|
||||
sim.current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
|
||||
LOG_D(SIM,"UE %d/%d: TS %"PRIi64"\n",UE_inst,CC_id,sim.current_UE_rx_timestamp[UE_inst][CC_id]);
|
||||
|
||||
for (int UE_inst = 0; UE_inst<NB_UE_INST; UE_inst++) {
|
||||
sim.current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
|
||||
LOG_D(SIM,"UE %d/%d: TS %"PRIi64"\n",UE_inst,CC_id,sim.current_UE_rx_timestamp[UE_inst][CC_id]);
|
||||
}
|
||||
if (oai_exit == 1) return((void*)NULL);
|
||||
|
||||
if (oai_exit == 1) return((void *)NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return((void*)NULL);
|
||||
return((void *)NULL);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "PHY/defs_UE.h"
|
||||
#include "PHY/defs_eNB.h"
|
||||
|
||||
void init_ocm(double snr_dB,double sinr_dB);
|
||||
void init_ocm(void);
|
||||
|
||||
void update_ocm(double snr_dB,double sinr_dB);
|
||||
|
||||
@@ -37,4 +37,4 @@ void update_ocm(double snr_dB,double sinr_dB);
|
||||
|
||||
void init_channel_vars(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user